forked from extern/nushell
Document and critically review ShellError
variants - Ep. 1 (#8229)
# Description The `ShellError` enum at the moment is kind of messy. Many variants are basic tuple structs where you always have to reference the implementation with its macro invocation to know which field serves which purpose. Furthermore we have both variants that are kind of redundant or either overly broad to be useful for the user to match on or overly specific with few uses. So I set out to start fixing the lacking documentation and naming to make it feasible to critically review the individual usages and fix those. Furthermore we can decide to join or split up variants that don't seem to be fit for purpose. Feel free to add review comments if you spot inconsistent use of `ShellError` variants. - Name fields on `ShellError::OperatorOverflow` - Name fields on `ShellError::PipelineMismatch` - Add doc to `ShellError::OnlySupportsThisInputType` - Name `ShellError::OnlySupportsThisInputType` - Name field on `ShellError::PipelineEmpty` - Comment about issues with `TypeMismatch*` - Fix a few `exp_input_type`s - Name fields on `ShellError::InvalidRange` # User-Facing Changes (None now, end goal more explicit and consistent error messages) # Tests + Formatting (No additional tests needed so far)
This commit is contained in:
committed by
GitHub
parent
0a1af85200
commit
438062d7fc
@ -228,20 +228,19 @@ impl PipelineData {
|
||||
},
|
||||
// Propagate errors by explicitly matching them before the final case.
|
||||
Value::Error { error } => Err(error),
|
||||
other => Err(ShellError::OnlySupportsThisInputType(
|
||||
"list, binary, raw data or range".into(),
|
||||
other.get_type().to_string(),
|
||||
span,
|
||||
// This line requires the Value::Error match above.
|
||||
other.expect_span(),
|
||||
)),
|
||||
other => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list, binary, raw data or range".into(),
|
||||
wrong_type: other.get_type().to_string(),
|
||||
dst_span: span,
|
||||
src_span: other.expect_span(),
|
||||
}),
|
||||
},
|
||||
PipelineData::Empty => Err(ShellError::OnlySupportsThisInputType(
|
||||
"list, binary, raw data or range".into(),
|
||||
"null".into(),
|
||||
span,
|
||||
span, // TODO: make PipelineData::Empty spanned, so that the span can be used here.
|
||||
)),
|
||||
PipelineData::Empty => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: "list, binary, raw data or range".into(),
|
||||
wrong_type: "null".into(),
|
||||
dst_span: span,
|
||||
src_span: span,
|
||||
}),
|
||||
other => Ok(PipelineIterator(other)),
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,13 @@ pub enum ShellError {
|
||||
/// Check the inputs to the operation and add guards for their sizes.
|
||||
/// Integers are generally of size i64, floats are generally f64.
|
||||
#[error("Operator overflow.")]
|
||||
#[diagnostic(code(nu::shell::operator_overflow), help("{2}"))]
|
||||
OperatorOverflow(String, #[label = "{0}"] Span, String),
|
||||
#[diagnostic(code(nu::shell::operator_overflow), help("{help}"))]
|
||||
OperatorOverflow {
|
||||
msg: String,
|
||||
#[label = "{msg}"]
|
||||
span: Span,
|
||||
help: String,
|
||||
},
|
||||
|
||||
/// The pipelined input into a command was not of the expected type. For example, it might
|
||||
/// expect a string input, but received a table instead.
|
||||
@ -45,20 +50,33 @@ pub enum ShellError {
|
||||
/// Check the relevant pipeline and extract or convert values as needed.
|
||||
#[error("Pipeline mismatch.")]
|
||||
#[diagnostic(code(nu::shell::pipeline_mismatch))]
|
||||
PipelineMismatch(
|
||||
String,
|
||||
#[label("expected: {0}")] Span,
|
||||
#[label("value originates from here")] Span,
|
||||
),
|
||||
PipelineMismatch {
|
||||
exp_input_type: String,
|
||||
#[label("expected: {exp_input_type}")]
|
||||
dst_span: Span,
|
||||
#[label("value originates from here")]
|
||||
src_span: Span,
|
||||
},
|
||||
|
||||
// TODO: properly unify
|
||||
/// The pipelined input into a command was not of the expected type. For example, it might
|
||||
/// expect a string input, but received a table instead.
|
||||
///
|
||||
/// (duplicate of [`ShellError::PipelineMismatch`] that reports the observed type)
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Check the relevant pipeline and extract or convert values as needed.
|
||||
#[error("Input type not supported.")]
|
||||
#[diagnostic(code(nu::shell::only_supports_this_input_type))]
|
||||
OnlySupportsThisInputType(
|
||||
String,
|
||||
String,
|
||||
#[label("only {0} input data is supported")] Span,
|
||||
#[label("input type: {1}")] Span,
|
||||
),
|
||||
OnlySupportsThisInputType {
|
||||
exp_input_type: String,
|
||||
wrong_type: String,
|
||||
#[label("only {exp_input_type} input data is supported")]
|
||||
dst_span: Span,
|
||||
#[label("input type: {wrong_type}")]
|
||||
src_span: Span,
|
||||
},
|
||||
|
||||
/// No input value was piped into the command.
|
||||
///
|
||||
@ -67,8 +85,12 @@ pub enum ShellError {
|
||||
/// Only use this command to process values from a previous expression.
|
||||
#[error("Pipeline empty.")]
|
||||
#[diagnostic(code(nu::shell::pipeline_mismatch))]
|
||||
PipelineEmpty(#[label("no input value was piped in")] Span),
|
||||
PipelineEmpty {
|
||||
#[label("no input value was piped in")]
|
||||
dst_span: Span,
|
||||
},
|
||||
|
||||
// TODO: remove non type error usages
|
||||
/// A command received an argument of the wrong type.
|
||||
///
|
||||
/// ## Resolution
|
||||
@ -78,6 +100,7 @@ pub enum ShellError {
|
||||
#[diagnostic(code(nu::shell::type_mismatch))]
|
||||
TypeMismatch(String, #[label = "{0}"] Span),
|
||||
|
||||
// TODO: merge with `TypeMismatch` as they are currently identical in capability
|
||||
/// A command received an argument of the wrong type.
|
||||
///
|
||||
/// ## Resolution
|
||||
@ -215,9 +238,14 @@ pub enum ShellError {
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Check to make sure both values are compatible, and that the values are enumerable in Nushell.
|
||||
#[error("Invalid range {0}..{1}")]
|
||||
#[error("Invalid range {left_flank}..{right_flank}")]
|
||||
#[diagnostic(code(nu::shell::invalid_range))]
|
||||
InvalidRange(String, String, #[label = "expected a valid range"] Span),
|
||||
InvalidRange {
|
||||
left_flank: String,
|
||||
right_flank: String,
|
||||
#[label = "expected a valid range"]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Catastrophic nushell failure. This reflects a completely unexpected or unrecoverable error.
|
||||
///
|
||||
|
@ -1996,11 +1996,7 @@ impl Value {
|
||||
if let Some(val) = lhs.checked_add(*rhs) {
|
||||
Ok(Value::Int { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"add operation overflowed".into(),
|
||||
span,
|
||||
"Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into()
|
||||
))
|
||||
Err(ShellError::OperatorOverflow { msg: "add operation overflowed".into(), span, help: "Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into() })
|
||||
}
|
||||
}
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
@ -2023,33 +2019,33 @@ impl Value {
|
||||
if let Some(val) = lhs.checked_add_signed(chrono::Duration::nanoseconds(*rhs)) {
|
||||
Ok(Value::Date { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"addition operation overflowed".into(),
|
||||
Err(ShellError::OperatorOverflow {
|
||||
msg: "addition operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
))
|
||||
help: "".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
||||
if let Some(val) = lhs.checked_add(*rhs) {
|
||||
Ok(Value::Duration { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"add operation overflowed".into(),
|
||||
Err(ShellError::OperatorOverflow {
|
||||
msg: "add operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
))
|
||||
help: "".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
|
||||
if let Some(val) = lhs.checked_add(*rhs) {
|
||||
Ok(Value::Filesize { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"add operation overflowed".into(),
|
||||
Err(ShellError::OperatorOverflow {
|
||||
msg: "add operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
))
|
||||
help: "".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -2110,11 +2106,7 @@ impl Value {
|
||||
if let Some(val) = lhs.checked_sub(*rhs) {
|
||||
Ok(Value::Int { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"subtraction operation overflowed".into(),
|
||||
span,
|
||||
"Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into()
|
||||
))
|
||||
Err(ShellError::OperatorOverflow { msg: "subtraction operation overflowed".into(), span, help: "Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into() })
|
||||
}
|
||||
}
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
@ -2135,43 +2127,43 @@ impl Value {
|
||||
if let Some(v) = result.num_nanoseconds() {
|
||||
Ok(Value::Duration { val: v, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"subtraction operation overflowed".into(),
|
||||
Err(ShellError::OperatorOverflow {
|
||||
msg: "subtraction operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
))
|
||||
help: "".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
(Value::Date { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
||||
match lhs.checked_sub_signed(chrono::Duration::nanoseconds(*rhs)) {
|
||||
Some(val) => Ok(Value::Date { val, span }),
|
||||
_ => Err(ShellError::OperatorOverflow(
|
||||
"subtraction operation overflowed".into(),
|
||||
_ => Err(ShellError::OperatorOverflow {
|
||||
msg: "subtraction operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
)),
|
||||
help: "".into(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
(Value::Duration { val: lhs, .. }, Value::Duration { val: rhs, .. }) => {
|
||||
if let Some(val) = lhs.checked_sub(*rhs) {
|
||||
Ok(Value::Duration { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"subtraction operation overflowed".into(),
|
||||
Err(ShellError::OperatorOverflow {
|
||||
msg: "subtraction operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
))
|
||||
help: "".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
(Value::Filesize { val: lhs, .. }, Value::Filesize { val: rhs, .. }) => {
|
||||
if let Some(val) = lhs.checked_sub(*rhs) {
|
||||
Ok(Value::Filesize { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"add operation overflowed".into(),
|
||||
Err(ShellError::OperatorOverflow {
|
||||
msg: "add operation overflowed".into(),
|
||||
span,
|
||||
"".into(),
|
||||
))
|
||||
help: "".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -2195,11 +2187,7 @@ impl Value {
|
||||
if let Some(val) = lhs.checked_mul(*rhs) {
|
||||
Ok(Value::Int { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"multiply operation overflowed".into(),
|
||||
span,
|
||||
"Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into()
|
||||
))
|
||||
Err(ShellError::OperatorOverflow { msg: "multiply operation overflowed".into(), span, help: "Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into() })
|
||||
}
|
||||
}
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
@ -3192,11 +3180,7 @@ impl Value {
|
||||
if let Some(val) = lhs.checked_pow(*rhs as u32) {
|
||||
Ok(Value::Int { val, span })
|
||||
} else {
|
||||
Err(ShellError::OperatorOverflow(
|
||||
"pow operation overflowed".into(),
|
||||
span,
|
||||
"Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into()
|
||||
))
|
||||
Err(ShellError::OperatorOverflow { msg: "pow operation overflowed".into(), span, help: "Consider using floating point values for increased range by promoting operand with 'into decimal'. Note: float has reduced precision!".into() })
|
||||
}
|
||||
}
|
||||
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
|
||||
|
Reference in New Issue
Block a user