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 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))
}
@ -61,56 +61,54 @@ pub fn get_pipeline_elements(
stack: &mut Stack,
block: &Block,
span: Span,
) -> Result<Vec<Value>, ShellError> {
let mut element_values = vec![];
) -> Vec<Value> {
let eval_expression = get_eval_expression(engine_state);
for (pipeline_idx, pipeline) in block.pipelines.iter().enumerate() {
let mut i = 0;
while i < pipeline.elements.len() {
let pipeline_element = &pipeline.elements[i];
let pipeline_expression = &pipeline_element.expr;
let pipeline_span = pipeline_element.expr.span;
block
.pipelines
.iter()
.enumerate()
.flat_map(|(p_idx, pipeline)| {
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 =
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_name, command_args_value, ty) = if let Expr::Call(call) = &expression.expr
{
let command = engine_state.get_decl(call.decl_id);
(
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 {
("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! {
"cmd_index" => Value::string(index, span),
"cmd_name" => Value::string(command_name, value_span),
"type" => Value::string(value_type.to_string(), span),
"cmd_args" => Value::list(command_args_value, value_span),
"span_start" => Value::int(value_span_start, span),
"span_end" => Value::int(value_span_end, span),
"cmd_index" => Value::string(cmd_index, span),
"cmd_name" => Value::string(command_name, expr_span),
"type" => Value::string(ty, span),
"cmd_args" => Value::list(command_args_value, expr_span),
"span_start" => Value::int(expr_span.start as i64, span),
"span_end" => Value::int(expr_span.end as i64, span),
};
element_values.push(Value::record(record, value_span));
i += 1;
}
}
Ok(element_values)
Value::record(record, expr_span)
})
.collect()
}
fn get_arguments(
engine_state: &EngineState,
stack: &mut Stack,
call: Call,
call: &Call,
eval_expression_fn: fn(&EngineState, &mut Stack, &Expression) -> Result<Value, ShellError>,
) -> Vec<Value> {
let mut arg_value = vec![];