Convert remainder of ShellError variants to named fields (#11276)

# Description

Removed variants that are no longer in use:
* `NoFile*`
* `UnexpectedAbbrComponent`

Converted:
* `OutsideSpannedLabeledError`
* `EvalBlockWithInput`
* `Break`
* `Continue`
* `Return`
* `NotAConstant`
* `NotAConstCommand`
* `NotAConstHelp`
* `InvalidGlobPattern`
* `ErrorExpandingGlob`

Fixes #10700 

# User-Facing Changes

None

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

N/A
This commit is contained in:
Eric Hodel 2023-12-09 16:46:21 -08:00 committed by GitHub
parent ca05553fc6
commit 3e5f81ae14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 328 additions and 298 deletions

View File

@ -139,7 +139,7 @@ pub fn evaluate_file(
false, false,
); );
let pipeline_data = match pipeline_data { let pipeline_data = match pipeline_data {
Err(ShellError::Return(_, _)) => { Err(ShellError::Return { .. }) => {
// allows early exists before `main` is run. // allows early exists before `main` is run.
return Ok(()); return Ok(());
} }

View File

@ -64,12 +64,10 @@ fn arg_glob_opt(
// user wasn't referring to a specific thing in filesystem, try to glob it. // user wasn't referring to a specific thing in filesystem, try to glob it.
match glob_with_parent(&pattern.item, options, cwd) { match glob_with_parent(&pattern.item, options, cwd) {
Ok(p) => Ok(p), Ok(p) => Ok(p),
Err(pat_err) => { Err(pat_err) => Err(ShellError::InvalidGlobPattern {
Err(ShellError::InvalidGlobPattern( msg: pat_err.msg.into(),
pat_err.msg.into(), span: pattern.span,
pattern.span, // improve specificity }),
))
}
} }
} }

View File

@ -27,7 +27,7 @@ impl Command for Break {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
Err(ShellError::Break(call.head)) Err(ShellError::Break { span: call.head })
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -27,7 +27,7 @@ impl Command for Continue {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
Err(ShellError::Continue(call.head)) Err(ShellError::Continue { span: call.head })
} }
fn examples(&self) -> Vec<Example> { fn examples(&self) -> Vec<Example> {

View File

@ -113,10 +113,10 @@ impl Command for For {
redirect_stdout, redirect_stdout,
redirect_stderr, redirect_stderr,
) { ) {
Err(ShellError::Break(_)) => { Err(ShellError::Break { .. }) => {
break; break;
} }
Err(ShellError::Continue(_)) => { Err(ShellError::Continue { .. }) => {
continue; continue;
} }
Err(err) => { Err(err) => {
@ -159,10 +159,10 @@ impl Command for For {
redirect_stdout, redirect_stdout,
redirect_stderr, redirect_stderr,
) { ) {
Err(ShellError::Break(_)) => { Err(ShellError::Break { .. }) => {
break; break;
} }
Err(ShellError::Continue(_)) => { Err(ShellError::Continue { .. }) => {
continue; continue;
} }
Err(err) => { Err(err) => {

View File

@ -48,10 +48,10 @@ impl Command for Loop {
call.redirect_stdout, call.redirect_stdout,
call.redirect_stderr, call.redirect_stderr,
) { ) {
Err(ShellError::Break(_)) => { Err(ShellError::Break { .. }) => {
break; break;
} }
Err(ShellError::Continue(_)) => { Err(ShellError::Continue { .. }) => {
continue; continue;
} }
Err(err) => { Err(err) => {

View File

@ -42,12 +42,15 @@ impl Command for Return {
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let return_value: Option<Value> = call.opt(engine_state, stack, 0)?; let return_value: Option<Value> = call.opt(engine_state, stack, 0)?;
if let Some(value) = return_value { if let Some(value) = return_value {
Err(ShellError::Return(call.head, Box::new(value))) Err(ShellError::Return {
span: call.head,
value: Box::new(value),
})
} else { } else {
Err(ShellError::Return( Err(ShellError::Return {
call.head, span: call.head,
Box::new(Value::nothing(call.head)), value: Box::new(Value::nothing(call.head)),
)) })
} }
} }

View File

@ -128,9 +128,9 @@ fn handle_catch(
/// `Err` when flow control to bubble up with `?` /// `Err` when flow control to bubble up with `?`
fn intercept_block_control(error: ShellError) -> Result<ShellError, ShellError> { fn intercept_block_control(error: ShellError) -> Result<ShellError, ShellError> {
match error { match error {
nu_protocol::ShellError::Break(_) => Err(error), nu_protocol::ShellError::Break { .. } => Err(error),
nu_protocol::ShellError::Continue(_) => Err(error), nu_protocol::ShellError::Continue { .. } => Err(error),
nu_protocol::ShellError::Return(_, _) => Err(error), nu_protocol::ShellError::Return { .. } => Err(error),
_ => Ok(error), _ => Ok(error),
} }
} }

View File

@ -62,10 +62,10 @@ impl Command for While {
call.redirect_stdout, call.redirect_stdout,
call.redirect_stderr, call.redirect_stderr,
) { ) {
Err(ShellError::Break(_)) => { Err(ShellError::Break { .. }) => {
break; break;
} }
Err(ShellError::Continue(_)) => { Err(ShellError::Continue { .. }) => {
continue; continue;
} }
Err(err) => { Err(err) => {

View File

@ -193,10 +193,10 @@ impl Command for UCp {
app_vals.push(path) app_vals.push(path)
} }
Err(e) => { Err(e) => {
return Err(ShellError::ErrorExpandingGlob( return Err(ShellError::ErrorExpandingGlob {
format!("error {} in path {}", e.error(), e.path().display()), msg: format!("error {} in path {}", e.error(), e.path().display()),
p.span, span: p.span,
)); });
} }
} }
} }

View File

@ -157,8 +157,8 @@ with 'transpose' first."#
redirect_stderr, redirect_stderr,
) { ) {
Ok(v) => Some(v.into_value(span)), Ok(v) => Some(v.into_value(span)),
Err(ShellError::Continue(v)) => Some(Value::nothing(v)), Err(ShellError::Continue { span }) => Some(Value::nothing(span)),
Err(ShellError::Break(_)) => None, Err(ShellError::Break { .. }) => None,
Err(error) => { Err(error) => {
let error = chain_error_with_input(error, x_is_error, input_span); let error = chain_error_with_input(error, x_is_error, input_span);
Some(Value::error(error, input_span)) Some(Value::error(error, input_span))
@ -180,8 +180,8 @@ with 'transpose' first."#
let x = match x { let x = match x {
Ok(x) => x, Ok(x) => x,
Err(ShellError::Continue(v)) => return Some(Value::nothing(v)), Err(ShellError::Continue { span }) => return Some(Value::nothing(span)),
Err(ShellError::Break(_)) => return None, Err(ShellError::Break { .. }) => return None,
Err(err) => return Some(Value::error(err, span)), Err(err) => return Some(Value::error(err, span)),
}; };
@ -203,8 +203,8 @@ with 'transpose' first."#
redirect_stderr, redirect_stderr,
) { ) {
Ok(v) => Some(v.into_value(span)), Ok(v) => Some(v.into_value(span)),
Err(ShellError::Continue(v)) => Some(Value::nothing(v)), Err(ShellError::Continue { span }) => Some(Value::nothing(span)),
Err(ShellError::Break(_)) => None, Err(ShellError::Break { .. }) => None,
Err(error) => { Err(error) => {
let error = chain_error_with_input(error, x_is_error, input_span); let error = chain_error_with_input(error, x_is_error, input_span);
Some(Value::error(error, input_span)) Some(Value::error(error, input_span))

View File

@ -83,7 +83,7 @@ impl Command for Items {
redirect_stderr, redirect_stderr,
) { ) {
Ok(v) => Some(v.into_value(span)), Ok(v) => Some(v.into_value(span)),
Err(ShellError::Break(_)) => None, Err(ShellError::Break { .. }) => None,
Err(error) => { Err(error) => {
let error = chain_error_with_input(error, false, input_span); let error = chain_error_with_input(error, false, input_span);
Some(Value::error(error, span)) Some(Value::error(error, span))

View File

@ -11,7 +11,10 @@ pub fn chain_error_with_input(
span: Span, span: Span,
) -> ShellError { ) -> ShellError {
if !input_is_error { if !input_is_error {
return ShellError::EvalBlockWithInput(span, vec![error_source]); return ShellError::EvalBlockWithInput {
span,
sources: vec![error_source],
};
} }
error_source error_source
} }

View File

@ -155,12 +155,12 @@ fn convert_string_to_value(string_input: String, span: Span) -> Result<Value, Sh
msg: "error parsing JSON text".into(), msg: "error parsing JSON text".into(),
span: Some(span), span: Some(span),
help: None, help: None,
inner: vec![ShellError::OutsideSpannedLabeledError( inner: vec![ShellError::OutsideSpannedLabeledError {
string_input, src: string_input,
"Error while parsing JSON text".into(), error: "Error while parsing JSON text".into(),
label, msg: label,
label_span, span: label_span,
)], }],
}) })
} }
x => Err(ShellError::CantConvert { x => Err(ShellError::CantConvert {

View File

@ -65,12 +65,12 @@ impl Command for FromNuon {
msg: "could not load nuon text".into(), msg: "could not load nuon text".into(),
span: Some(head), span: Some(head),
help: None, help: None,
inner: vec![ShellError::OutsideSpannedLabeledError( inner: vec![ShellError::OutsideSpannedLabeledError {
string_input, src: string_input,
"error when loading".into(), error: "error when loading".into(),
"excess values when loading".into(), msg: "excess values when loading".into(),
element.span(), span: element.span(),
)], }],
}); });
} else { } else {
return Err(ShellError::GenericError { return Err(ShellError::GenericError {
@ -105,12 +105,12 @@ impl Command for FromNuon {
msg: "could not load nuon text".into(), msg: "could not load nuon text".into(),
span: Some(head), span: Some(head),
help: None, help: None,
inner: vec![ShellError::OutsideSpannedLabeledError( inner: vec![ShellError::OutsideSpannedLabeledError {
string_input, src: string_input,
"error when loading".into(), error: "error when loading".into(),
"detected a pipeline in nuon file".into(), msg: "detected a pipeline in nuon file".into(),
expr.span(), span: expr.span(),
)], }],
}); });
} }
@ -145,12 +145,12 @@ impl Command for FromNuon {
msg: "could not parse nuon text".into(), msg: "could not parse nuon text".into(),
span: Some(head), span: Some(head),
help: None, help: None,
inner: vec![ShellError::OutsideSpannedLabeledError( inner: vec![ShellError::OutsideSpannedLabeledError {
string_input, src: string_input,
"error when parsing".into(), error: "error when parsing".into(),
err.to_string(), msg: err.to_string(),
err.span(), span: err.span(),
)], }],
}); });
} }
@ -175,99 +175,99 @@ fn convert_to_value(
original_text: &str, original_text: &str,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
match expr.expr { match expr.expr {
Expr::BinaryOp(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::BinaryOp(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"binary operators not supported in nuon".into(), msg: "binary operators not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::UnaryNot(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::UnaryNot(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"unary operators not supported in nuon".into(), msg: "unary operators not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Block(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Block(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"blocks not supported in nuon".into(), msg: "blocks not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Closure(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Closure(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"closures not supported in nuon".into(), msg: "closures not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Binary(val) => Ok(Value::binary(val, span)), Expr::Binary(val) => Ok(Value::binary(val, span)),
Expr::Bool(val) => Ok(Value::bool(val, span)), Expr::Bool(val) => Ok(Value::bool(val, span)),
Expr::Call(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Call(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"calls not supported in nuon".into(), msg: "calls not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::CellPath(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::CellPath(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"subexpressions and cellpaths not supported in nuon".into(), msg: "subexpressions and cellpaths not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::DateTime(dt) => Ok(Value::date(dt, span)), Expr::DateTime(dt) => Ok(Value::date(dt, span)),
Expr::ExternalCall(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::ExternalCall(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"calls not supported in nuon".into(), msg: "calls not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Filepath(val) => Ok(Value::string(val, span)), Expr::Filepath(val) => Ok(Value::string(val, span)),
Expr::Directory(val) => Ok(Value::string(val, span)), Expr::Directory(val) => Ok(Value::string(val, span)),
Expr::Float(val) => Ok(Value::float(val, span)), Expr::Float(val) => Ok(Value::float(val, span)),
Expr::FullCellPath(full_cell_path) => { Expr::FullCellPath(full_cell_path) => {
if !full_cell_path.tail.is_empty() { if !full_cell_path.tail.is_empty() {
Err(ShellError::OutsideSpannedLabeledError( Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"subexpressions and cellpaths not supported in nuon".into(), msg: "subexpressions and cellpaths not supported in nuon".into(),
expr.span, span: expr.span,
)) })
} else { } else {
convert_to_value(full_cell_path.head, span, original_text) convert_to_value(full_cell_path.head, span, original_text)
} }
} }
Expr::Garbage => Err(ShellError::OutsideSpannedLabeledError( Expr::Garbage => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"extra tokens in input file".into(), msg: "extra tokens in input file".into(),
expr.span, span: expr.span,
)), }),
Expr::MatchPattern(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::MatchPattern(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"extra tokens in input file".into(), msg: "extra tokens in input file".into(),
expr.span, span: expr.span,
)), }),
Expr::GlobPattern(val) => Ok(Value::string(val, span)), Expr::GlobPattern(val) => Ok(Value::string(val, span)),
Expr::ImportPattern(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::ImportPattern(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"imports not supported in nuon".into(), msg: "imports not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Overlay(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Overlay(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"overlays not supported in nuon".into(), msg: "overlays not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Int(val) => Ok(Value::int(val, span)), Expr::Int(val) => Ok(Value::int(val, span)),
Expr::Keyword(kw, ..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Keyword(kw, ..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
format!("{} not supported in nuon", String::from_utf8_lossy(&kw)), msg: format!("{} not supported in nuon", String::from_utf8_lossy(&kw)),
expr.span, span: expr.span,
)), }),
Expr::List(vals) => { Expr::List(vals) => {
let mut output = vec![]; let mut output = vec![];
for val in vals { for val in vals {
@ -276,19 +276,19 @@ fn convert_to_value(
Ok(Value::list(output, span)) Ok(Value::list(output, span))
} }
Expr::MatchBlock(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::MatchBlock(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"match blocks not supported in nuon".into(), msg: "match blocks not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Nothing => Ok(Value::nothing(span)), Expr::Nothing => Ok(Value::nothing(span)),
Expr::Operator(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Operator(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"operators not supported in nuon".into(), msg: "operators not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Range(from, next, to, operator) => { Expr::Range(from, next, to, operator) => {
let from = if let Some(f) = from { let from = if let Some(f) = from {
convert_to_value(*f, span, original_text)? convert_to_value(*f, span, original_text)?
@ -322,12 +322,12 @@ fn convert_to_value(
let key_str = match key.expr { let key_str = match key.expr {
Expr::String(key_str) => key_str, Expr::String(key_str) => key_str,
_ => { _ => {
return Err(ShellError::OutsideSpannedLabeledError( return Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"only strings can be keys".into(), msg: "only strings can be keys".into(),
key.span, span: key.span,
)) })
} }
}; };
@ -336,49 +336,49 @@ fn convert_to_value(
record.push(key_str, value); record.push(key_str, value);
} }
RecordItem::Spread(_, inner) => { RecordItem::Spread(_, inner) => {
return Err(ShellError::OutsideSpannedLabeledError( return Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"spread operator not supported in nuon".into(), msg: "spread operator not supported in nuon".into(),
inner.span, span: inner.span,
)); });
} }
} }
} }
Ok(Value::record(record, span)) Ok(Value::record(record, span))
} }
Expr::RowCondition(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::RowCondition(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"row conditions not supported in nuon".into(), msg: "row conditions not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Signature(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Signature(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"signatures not supported in nuon".into(), msg: "signatures not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Spread(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Spread(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"spread operator not supported in nuon".into(), msg: "spread operator not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::String(s) => Ok(Value::string(s, span)), Expr::String(s) => Ok(Value::string(s, span)),
Expr::StringInterpolation(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::StringInterpolation(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"string interpolation not supported in nuon".into(), msg: "string interpolation not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Subexpression(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Subexpression(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"subexpressions not supported in nuon".into(), msg: "subexpressions not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::Table(mut headers, cells) => { Expr::Table(mut headers, cells) => {
let mut cols = vec![]; let mut cols = vec![];
@ -388,12 +388,12 @@ fn convert_to_value(
let key_str = match &mut key.expr { let key_str = match &mut key.expr {
Expr::String(key_str) => key_str, Expr::String(key_str) => key_str,
_ => { _ => {
return Err(ShellError::OutsideSpannedLabeledError( return Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"only strings can be keys".into(), msg: "only strings can be keys".into(),
expr.span, span: expr.span,
)) })
} }
}; };
@ -416,12 +416,12 @@ fn convert_to_value(
} }
if cols.len() != vals.len() { if cols.len() != vals.len() {
return Err(ShellError::OutsideSpannedLabeledError( return Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"table has mismatched columns".into(), msg: "table has mismatched columns".into(),
expr.span, span: expr.span,
)); });
} }
output.push(Value::record( output.push(Value::record(
@ -439,12 +439,12 @@ fn convert_to_value(
let size = match val.expr { let size = match val.expr {
Expr::Int(val) => val, Expr::Int(val) => val,
_ => { _ => {
return Err(ShellError::OutsideSpannedLabeledError( return Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"non-integer unit value".into(), msg: "non-integer unit value".into(),
expr.span, span: expr.span,
)) })
} }
}; };
@ -484,37 +484,37 @@ fn convert_to_value(
Unit::Hour => Ok(Value::duration(size * 1000 * 1000 * 1000 * 60 * 60, span)), Unit::Hour => Ok(Value::duration(size * 1000 * 1000 * 1000 * 60 * 60, span)),
Unit::Day => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24) { Unit::Day => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24) {
Some(val) => Ok(Value::duration(val, span)), Some(val) => Ok(Value::duration(val, span)),
None => Err(ShellError::OutsideSpannedLabeledError( None => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"day duration too large".into(), error: "day duration too large".into(),
"day duration too large".into(), msg: "day duration too large".into(),
expr.span, span: expr.span,
)), }),
}, },
Unit::Week => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 7) { Unit::Week => match size.checked_mul(1000 * 1000 * 1000 * 60 * 60 * 24 * 7) {
Some(val) => Ok(Value::duration(val, span)), Some(val) => Ok(Value::duration(val, span)),
None => Err(ShellError::OutsideSpannedLabeledError( None => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"week duration too large".into(), error: "week duration too large".into(),
"week duration too large".into(), msg: "week duration too large".into(),
expr.span, span: expr.span,
)), }),
}, },
} }
} }
Expr::Var(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::Var(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"variables not supported in nuon".into(), msg: "variables not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
Expr::VarDecl(..) => Err(ShellError::OutsideSpannedLabeledError( Expr::VarDecl(..) => Err(ShellError::OutsideSpannedLabeledError {
original_text.to_string(), src: original_text.to_string(),
"Error when loading".into(), error: "Error when loading".into(),
"variable declarations not supported in nuon".into(), msg: "variable declarations not supported in nuon".into(),
expr.span, span: expr.span,
)), }),
} }
} }

View File

@ -108,7 +108,10 @@ impl Command for Du {
let exclude = args.exclude.map_or(Ok(None), move |x| { let exclude = args.exclude.map_or(Ok(None), move |x| {
Pattern::new(&x.item) Pattern::new(&x.item)
.map(Some) .map(Some)
.map_err(|e| ShellError::InvalidGlobPattern(e.msg.to_string(), x.span)) .map_err(|e| ShellError::InvalidGlobPattern {
msg: e.msg.into(),
span: x.span,
})
})?; })?;
let include_files = args.all; let include_files = args.all;

View File

@ -37,10 +37,10 @@ impl Command for SubCommand {
call: &Call, call: &Call,
_input: PipelineData, _input: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
Err(nu_protocol::ShellError::RemovedCommand( Err(nu_protocol::ShellError::RemovedCommand {
self.name().to_string(), removed: self.name().to_string(),
"format date".to_owned(), replacement: "format date".to_owned(),
call.head, span: call.head,
)) })
} }
} }

View File

@ -34,10 +34,10 @@ impl Command for LetEnv {
call: &Call, call: &Call,
_: PipelineData, _: PipelineData,
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
Err(nu_protocol::ShellError::RemovedCommand( Err(nu_protocol::ShellError::RemovedCommand {
self.name().to_string(), removed: self.name().to_string(),
"$env.<environment variable> = ...".to_owned(), replacement: "$env.<environment variable> = ...".to_owned(),
call.head, span: call.head,
)) })
} }
} }

View File

@ -305,11 +305,11 @@ impl ExternalCommand {
Some(s) => s.clone(), Some(s) => s.clone(),
None => "".to_string(), None => "".to_string(),
}; };
return Err(ShellError::RemovedCommand( return Err(ShellError::RemovedCommand {
command_name_lower, removed: command_name_lower,
replacement, replacement,
self.name.span, span: self.name.span,
)); });
} }
let suggestion = suggest_command(&self.name.item, engine_state); let suggestion = suggest_command(&self.name.item, engine_state);

View File

@ -593,7 +593,7 @@ pub fn eval_block_with_early_return(
redirect_stdout, redirect_stdout,
redirect_stderr, redirect_stderr,
) { ) {
Err(ShellError::Return(_, value)) => Ok(PipelineData::Value(*value, None)), Err(ShellError::Return { span: _, value }) => Ok(PipelineData::Value(*value, None)),
x => x, x => x,
} }
} }

View File

@ -212,13 +212,13 @@ fn eval_const_call(
let decl = working_set.get_decl(call.decl_id); let decl = working_set.get_decl(call.decl_id);
if !decl.is_const() { if !decl.is_const() {
return Err(ShellError::NotAConstCommand(call.head)); return Err(ShellError::NotAConstCommand { span: call.head });
} }
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") { if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") {
// It would require re-implementing get_full_help() for const evaluation. Assuming that // It would require re-implementing get_full_help() for const evaluation. Assuming that
// getting help messages at parse-time is rare enough, we can simply disallow it. // getting help messages at parse-time is rare enough, we can simply disallow it.
return Err(ShellError::NotAConstHelp(call.head)); return Err(ShellError::NotAConstHelp { span: call.head });
} }
decl.run_const(working_set, call, input) decl.run_const(working_set, call, input)
@ -233,7 +233,7 @@ pub fn eval_const_subexpression(
for pipeline in block.pipelines.iter() { for pipeline in block.pipelines.iter() {
for element in pipeline.elements.iter() { for element in pipeline.elements.iter() {
let PipelineElement::Expression(_, expr) = element else { let PipelineElement::Expression(_, expr) = element else {
return Err(ShellError::NotAConstant(span)); return Err(ShellError::NotAConstant { span });
}; };
input = eval_constant_with_input(working_set, expr, input)? input = eval_constant_with_input(working_set, expr, input)?
@ -288,7 +288,7 @@ impl Eval for EvalConst {
_: String, _: String,
span: Span, span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(span)) Err(ShellError::NotAConstant { span })
} }
fn eval_var( fn eval_var(
@ -299,7 +299,7 @@ impl Eval for EvalConst {
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
match working_set.get_variable(var_id).const_val.as_ref() { match working_set.get_variable(var_id).const_val.as_ref() {
Some(val) => Ok(val.clone()), Some(val) => Ok(val.clone()),
None => Err(ShellError::NotAConstant(span)), None => Err(ShellError::NotAConstant { span }),
} }
} }
@ -322,7 +322,7 @@ impl Eval for EvalConst {
span: Span, span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
// TODO: It may be more helpful to give not_a_const_command error // TODO: It may be more helpful to give not_a_const_command error
Err(ShellError::NotAConstant(span)) Err(ShellError::NotAConstant { span })
} }
fn eval_subexpression( fn eval_subexpression(
@ -346,7 +346,7 @@ impl Eval for EvalConst {
_: bool, _: bool,
expr_span: Span, expr_span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(expr_span)) Err(ShellError::NotAConstant { span: expr_span })
} }
fn eval_assignment( fn eval_assignment(
@ -358,7 +358,7 @@ impl Eval for EvalConst {
_op_span: Span, _op_span: Span,
expr_span: Span, expr_span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(expr_span)) Err(ShellError::NotAConstant { span: expr_span })
} }
fn eval_row_condition_or_closure( fn eval_row_condition_or_closure(
@ -367,7 +367,7 @@ impl Eval for EvalConst {
_: usize, _: usize,
span: Span, span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(span)) Err(ShellError::NotAConstant { span })
} }
fn eval_string_interpolation( fn eval_string_interpolation(
@ -376,11 +376,11 @@ impl Eval for EvalConst {
_: &[Expression], _: &[Expression],
span: Span, span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(span)) Err(ShellError::NotAConstant { span })
} }
fn eval_overlay(_: &StateWorkingSet, span: Span) -> Result<Value, ShellError> { fn eval_overlay(_: &StateWorkingSet, span: Span) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(span)) Err(ShellError::NotAConstant { span })
} }
fn eval_glob_pattern( fn eval_glob_pattern(
@ -389,10 +389,10 @@ impl Eval for EvalConst {
_: String, _: String,
span: Span, span: Span,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(span)) Err(ShellError::NotAConstant { span })
} }
fn unreachable(expr: &Expression) -> Result<Value, ShellError> { fn unreachable(expr: &Expression) -> Result<Value, ShellError> {
Err(ShellError::NotAConstant(expr.span)) Err(ShellError::NotAConstant { span: expr.span })
} }
} }

View File

@ -944,14 +944,6 @@ pub enum ShellError {
span: Span, span: Span,
}, },
// These three are unused. Remove?
#[error("No file to be removed")]
NoFileToBeRemoved(),
#[error("No file to be moved")]
NoFileToBeMoved(),
#[error("No file to be copied")]
NoFileToBeCopied(),
/// Error while trying to read a file /// Error while trying to read a file
/// ///
/// ## Resolution /// ## Resolution
@ -1084,22 +1076,30 @@ pub enum ShellError {
}, },
/// This is a generic error type used for different situations. /// This is a generic error type used for different situations.
#[error("{1}")] #[error("{error}")]
#[diagnostic()] #[diagnostic()]
OutsideSpannedLabeledError(#[source_code] String, String, String, #[label("{2}")] Span), OutsideSpannedLabeledError {
#[source_code]
src: String,
error: String,
msg: String,
#[label("{msg}")]
span: Span,
},
/// Attempted to use a command that has been removed from Nushell. /// Attempted to use a command that has been removed from Nushell.
/// ///
/// ## Resolution /// ## Resolution
/// ///
/// Check the help for the new suggested command and update your script accordingly. /// Check the help for the new suggested command and update your script accordingly.
#[error("Removed command: {0}")] #[error("Removed command: {removed}")]
#[diagnostic(code(nu::shell::removed_command))] #[diagnostic(code(nu::shell::removed_command))]
RemovedCommand( RemovedCommand {
String, removed: String,
String, replacement: String,
#[label = "'{0}' has been removed from Nushell. Please use '{1}' instead."] Span, #[label("'{removed}' has been removed from Nushell. Please use '{replacement}' instead.")]
), span: Span,
},
/// Non-Unicode input received. /// Non-Unicode input received.
/// ///
@ -1110,32 +1110,38 @@ pub enum ShellError {
#[diagnostic(code(nu::shell::non_unicode_input))] #[diagnostic(code(nu::shell::non_unicode_input))]
NonUnicodeInput, NonUnicodeInput,
/// Unexpected abbr component.
///
/// ## Resolution
///
/// Check the path abbreviation to ensure that it is valid.
#[error("Unexpected abbr component `{0}`.")]
#[diagnostic(code(nu::shell::unexpected_path_abbreviateion))]
UnexpectedAbbrComponent(String),
// It should be only used by commands accepts block, and accept inputs from pipeline. // It should be only used by commands accepts block, and accept inputs from pipeline.
/// Failed to eval block with specific pipeline input. /// Failed to eval block with specific pipeline input.
#[error("Eval block failed with pipeline input")] #[error("Eval block failed with pipeline input")]
#[diagnostic(code(nu::shell::eval_block_with_input))] #[diagnostic(code(nu::shell::eval_block_with_input))]
EvalBlockWithInput(#[label("source value")] Span, #[related] Vec<ShellError>), EvalBlockWithInput {
#[label("source value")]
span: Span,
#[related]
sources: Vec<ShellError>,
},
/// Break event, which may become an error if used outside of a loop /// Break event, which may become an error if used outside of a loop
#[error("Break used outside of loop")] #[error("Break used outside of loop")]
Break(#[label = "used outside of loop"] Span), Break {
#[label("used outside of loop")]
span: Span,
},
/// Continue event, which may become an error if used outside of a loop /// Continue event, which may become an error if used outside of a loop
#[error("Continue used outside of loop")] #[error("Continue used outside of loop")]
Continue(#[label = "used outside of loop"] Span), Continue {
#[label("used outside of loop")]
span: Span,
},
/// Return event, which may become an error if used outside of a function /// Return event, which may become an error if used outside of a function
#[error("Return used outside of function")] #[error("Return used outside of function")]
Return(#[label = "used outside of function"] Span, Box<Value>), Return {
#[label("used outside of function")]
span: Span,
value: Box<Value>,
},
/// The code being executed called itself too many times. /// The code being executed called itself too many times.
/// ///
@ -1206,7 +1212,10 @@ This is an internal Nushell error, please file an issue https://github.com/nushe
code(nu::shell::not_a_constant), code(nu::shell::not_a_constant),
help("Only a subset of expressions are allowed constants during parsing. Try using the 'const' command or typing the value literally.") help("Only a subset of expressions are allowed constants during parsing. Try using the 'const' command or typing the value literally.")
)] )]
NotAConstant(#[label = "Value is not a parse-time constant"] Span), NotAConstant {
#[label("Value is not a parse-time constant")]
span: Span,
},
/// Tried running a command that is not const-compatible /// Tried running a command that is not const-compatible
/// ///
@ -1219,7 +1228,10 @@ This is an internal Nushell error, please file an issue https://github.com/nushe
code(nu::shell::not_a_const_command), code(nu::shell::not_a_const_command),
help("Only a subset of builtin commands, and custom commands built only from those commands, can run at parse time.") help("Only a subset of builtin commands, and custom commands built only from those commands, can run at parse time.")
)] )]
NotAConstCommand(#[label = "This command cannot run at parse time."] Span), NotAConstCommand {
#[label("This command cannot run at parse time.")]
span: Span,
},
/// Tried getting a help message at parse time. /// Tried getting a help message at parse time.
/// ///
@ -1231,7 +1243,10 @@ This is an internal Nushell error, please file an issue https://github.com/nushe
code(nu::shell::not_a_const_help), code(nu::shell::not_a_const_help),
help("Help messages are currently not supported to be constants.") help("Help messages are currently not supported to be constants.")
)] )]
NotAConstHelp(#[label = "Cannot get help message at parse time."] Span), NotAConstHelp {
#[label("This command cannot run at parse time.")]
span: Span,
},
/// Invalid glob pattern /// Invalid glob pattern
/// ///
@ -1243,7 +1258,11 @@ This is an internal Nushell error, please file an issue https://github.com/nushe
code(nu::shell::invalid_glob_pattern), code(nu::shell::invalid_glob_pattern),
help("Refer to xxx for help on nushell glob patterns.") help("Refer to xxx for help on nushell glob patterns.")
)] )]
InvalidGlobPattern(String, #[label = "{0}"] Span), InvalidGlobPattern {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Error expanding glob pattern /// Error expanding glob pattern
/// ///
@ -1256,7 +1275,11 @@ This is an internal Nushell error, please file an issue https://github.com/nushe
help("Correct glob pattern or file access issue") help("Correct glob pattern or file access issue")
)] )]
//todo: add error detail //todo: add error detail
ErrorExpandingGlob(String, #[label = "{0}"] Span), ErrorExpandingGlob {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Tried spreading a non-list inside a list. /// Tried spreading a non-list inside a list.
/// ///