mirror of
https://github.com/nushell/nushell.git
synced 2025-05-09 12:34:26 +02:00
# Description Because the IR compiler was previously optional, compile errors were not treated as fatal errors, and were just logged like parse warnings are. This unfortunately meant that if a user encountered a compile error, they would see "Can't evaluate block in IR mode" as the actual error in addition to (hopefully) logging the compile error. This changes compile errors to be treated like parse errors so that they show up as the last error, helping users understand what's wrong a little bit more easily. Fixes #14333. # User-Facing Changes - Shouldn't see "Can't evaluate block in IR mode" - Should only see compile error - No evaluation should happen # Tests + Formatting Didn't add any tests specifically for this, but it might be good to have at least one that checks to ensure the compile error shows up and the "can't evaluate" error does not.
104 lines
3.0 KiB
Rust
104 lines
3.0 KiB
Rust
use log::info;
|
|
use nu_engine::{convert_env_values, eval_block};
|
|
use nu_parser::parse;
|
|
use nu_protocol::{
|
|
cli_error::report_compile_error,
|
|
debugger::WithoutDebug,
|
|
engine::{EngineState, Stack, StateWorkingSet},
|
|
report_parse_error, report_parse_warning, PipelineData, ShellError, Spanned, Value,
|
|
};
|
|
use std::sync::Arc;
|
|
|
|
use crate::util::print_pipeline;
|
|
|
|
#[derive(Default)]
|
|
pub struct EvaluateCommandsOpts {
|
|
pub table_mode: Option<Value>,
|
|
pub error_style: Option<Value>,
|
|
pub no_newline: bool,
|
|
}
|
|
|
|
/// Run a command (or commands) given to us by the user
|
|
pub fn evaluate_commands(
|
|
commands: &Spanned<String>,
|
|
engine_state: &mut EngineState,
|
|
stack: &mut Stack,
|
|
input: PipelineData,
|
|
opts: EvaluateCommandsOpts,
|
|
) -> Result<(), ShellError> {
|
|
let EvaluateCommandsOpts {
|
|
table_mode,
|
|
error_style,
|
|
no_newline,
|
|
} = opts;
|
|
|
|
// Handle the configured error style early
|
|
if let Some(e_style) = error_style {
|
|
match e_style.coerce_str()?.parse() {
|
|
Ok(e_style) => {
|
|
Arc::make_mut(&mut engine_state.config).error_style = e_style;
|
|
}
|
|
Err(err) => {
|
|
return Err(ShellError::GenericError {
|
|
error: "Invalid value for `--error-style`".into(),
|
|
msg: err.into(),
|
|
span: Some(e_style.span()),
|
|
help: None,
|
|
inner: vec![],
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Translate environment variables from Strings to Values
|
|
convert_env_values(engine_state, stack)?;
|
|
|
|
// Parse the source code
|
|
let (block, delta) = {
|
|
if let Some(ref t_mode) = table_mode {
|
|
Arc::make_mut(&mut engine_state.config).table.mode =
|
|
t_mode.coerce_str()?.parse().unwrap_or_default();
|
|
}
|
|
|
|
let mut working_set = StateWorkingSet::new(engine_state);
|
|
|
|
let output = parse(&mut working_set, None, commands.item.as_bytes(), false);
|
|
if let Some(warning) = working_set.parse_warnings.first() {
|
|
report_parse_warning(&working_set, warning);
|
|
}
|
|
|
|
if let Some(err) = working_set.parse_errors.first() {
|
|
report_parse_error(&working_set, err);
|
|
std::process::exit(1);
|
|
}
|
|
|
|
if let Some(err) = working_set.compile_errors.first() {
|
|
report_compile_error(&working_set, err);
|
|
std::process::exit(1);
|
|
}
|
|
|
|
(output, working_set.render())
|
|
};
|
|
|
|
// Update permanent state
|
|
engine_state.merge_delta(delta)?;
|
|
|
|
// Run the block
|
|
let pipeline = eval_block::<WithoutDebug>(engine_state, stack, &block, input)?;
|
|
|
|
if let PipelineData::Value(Value::Error { error, .. }, ..) = pipeline {
|
|
return Err(*error);
|
|
}
|
|
|
|
if let Some(t_mode) = table_mode {
|
|
Arc::make_mut(&mut engine_state.config).table.mode =
|
|
t_mode.coerce_str()?.parse().unwrap_or_default();
|
|
}
|
|
|
|
print_pipeline(engine_state, stack, pipeline, no_newline)?;
|
|
|
|
info!("evaluate {}:{}:{}", file!(), line!(), column!());
|
|
|
|
Ok(())
|
|
}
|