explain refactor (#12432)

# Description
Refactors the `explain` command. Part of this is fixing the `type`
column which used to always be `string` for each row.
This commit is contained in:
Ian Manske 2024-04-06 23:55:22 +00:00 committed by GitHub
parent 70520000d2
commit 6b4cbe7a98
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -41,7 +41,7 @@ impl Command for Explain {
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let mut stack = stack.captures_to_stack(capture_block.captures); let mut stack = stack.captures_to_stack(capture_block.captures);
let elements = get_pipeline_elements(engine_state, &mut stack, block, call.head)?; let elements = get_pipeline_elements(engine_state, &mut stack, block, call.head);
Ok(elements.into_pipeline_data(ctrlc)) Ok(elements.into_pipeline_data(ctrlc))
} }
@ -61,56 +61,54 @@ pub fn get_pipeline_elements(
stack: &mut Stack, stack: &mut Stack,
block: &Block, block: &Block,
span: Span, span: Span,
) -> Result<Vec<Value>, ShellError> { ) -> Vec<Value> {
let mut element_values = vec![];
let eval_expression = get_eval_expression(engine_state); let eval_expression = get_eval_expression(engine_state);
for (pipeline_idx, pipeline) in block.pipelines.iter().enumerate() { block
let mut i = 0; .pipelines
while i < pipeline.elements.len() { .iter()
let pipeline_element = &pipeline.elements[i]; .enumerate()
let pipeline_expression = &pipeline_element.expr; .flat_map(|(p_idx, pipeline)| {
let pipeline_span = pipeline_element.expr.span; pipeline
.elements
.iter()
.enumerate()
.map(move |(e_idx, element)| (format!("{p_idx}_{e_idx}"), element))
})
.map(move |(cmd_index, element)| {
let expression = &element.expr;
let expr_span = element.expr.span;
let element_str = let (command_name, command_args_value, ty) = if let Expr::Call(call) = &expression.expr
String::from_utf8_lossy(engine_state.get_span_contents(pipeline_span)); {
let value = Value::string(element_str.to_string(), pipeline_span);
let expr = pipeline_expression.expr.clone();
let (command_name, command_args_value) = if let Expr::Call(call) = expr {
let command = engine_state.get_decl(call.decl_id); let command = engine_state.get_decl(call.decl_id);
( (
command.name().to_string(), command.name().to_string(),
get_arguments(engine_state, stack, *call, eval_expression), get_arguments(engine_state, stack, call.as_ref(), eval_expression),
command.signature().get_output_type().to_string(),
) )
} else { } else {
("no-op".to_string(), vec![]) ("no-op".to_string(), vec![], expression.ty.to_string())
}; };
let index = format!("{pipeline_idx}_{i}");
let value_type = value.get_type();
let value_span = value.span();
let value_span_start = value_span.start as i64;
let value_span_end = value_span.end as i64;
let record = record! { let record = record! {
"cmd_index" => Value::string(index, span), "cmd_index" => Value::string(cmd_index, span),
"cmd_name" => Value::string(command_name, value_span), "cmd_name" => Value::string(command_name, expr_span),
"type" => Value::string(value_type.to_string(), span), "type" => Value::string(ty, span),
"cmd_args" => Value::list(command_args_value, value_span), "cmd_args" => Value::list(command_args_value, expr_span),
"span_start" => Value::int(value_span_start, span), "span_start" => Value::int(expr_span.start as i64, span),
"span_end" => Value::int(value_span_end, span), "span_end" => Value::int(expr_span.end as i64, span),
}; };
element_values.push(Value::record(record, value_span));
i += 1; Value::record(record, expr_span)
} })
} .collect()
Ok(element_values)
} }
fn get_arguments( fn get_arguments(
engine_state: &EngineState, engine_state: &EngineState,
stack: &mut Stack, stack: &mut Stack,
call: Call, call: &Call,
eval_expression_fn: fn(&EngineState, &mut Stack, &Expression) -> Result<Value, ShellError>, eval_expression_fn: fn(&EngineState, &mut Stack, &Expression) -> Result<Value, ShellError>,
) -> Vec<Value> { ) -> Vec<Value> {
let mut arg_value = vec![]; let mut arg_value = vec![];