Convert more ShellError variants to named fields (#11222)

# Description

Convert errors to named fields:
* NeedsPositiveValue
* MissingConfigValue
* UnsupportedConfigValue
* DowncastNotPossible
* NonUtf8Custom
* NonUtf8
* DidYouMeanCustom
* DidYouMean
* ReadingFile
* RemoveNotPossible
* ChangedModifiedTimeNotPossible
* ChangedAccessTimeNotPossible

Part of #10700
This commit is contained in:
Eric Hodel 2023-12-04 01:19:32 -08:00 committed by GitHub
parent b227eea668
commit 67eec92e76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 299 additions and 208 deletions

View File

@ -47,13 +47,13 @@ pub fn evaluate_file(
let working_set = StateWorkingSet::new(engine_state);
report_error(
&working_set,
&ShellError::NonUtf8Custom(
format!(
&ShellError::NonUtf8Custom {
msg: format!(
"Input file name '{}' is not valid UTF8",
file_path.to_string_lossy()
),
Span::unknown(),
),
span: Span::unknown(),
},
);
std::process::exit(1);
});

View File

@ -139,18 +139,18 @@ fn add_menu(
"columnar" => add_columnar_menu(line_editor, menu, engine_state, stack, config),
"list" => add_list_menu(line_editor, menu, engine_state, stack, config),
"description" => add_description_menu(line_editor, menu, engine_state, stack, config),
_ => Err(ShellError::UnsupportedConfigValue(
"columnar, list or description".to_string(),
menu.menu_type.into_abbreviated_string(config),
menu.menu_type.span(),
)),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "columnar, list or description".to_string(),
value: menu.menu_type.into_abbreviated_string(config),
span: menu.menu_type.span(),
}),
}
} else {
Err(ShellError::UnsupportedConfigValue(
"only record type".to_string(),
menu.menu_type.into_abbreviated_string(config),
menu.menu_type.span(),
))
Err(ShellError::UnsupportedConfigValue {
expected: "only record type".to_string(),
value: menu.menu_type.into_abbreviated_string(config),
span: menu.menu_type.span(),
})
}
}
@ -261,11 +261,11 @@ pub(crate) fn add_columnar_menu(
completer: Box::new(menu_completer),
}))
}
_ => Err(ShellError::UnsupportedConfigValue(
"block or omitted value".to_string(),
menu.source.into_abbreviated_string(config),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "block or omitted value".to_string(),
value: menu.source.into_abbreviated_string(config),
span,
)),
}),
}
}
@ -343,11 +343,11 @@ pub(crate) fn add_list_menu(
completer: Box::new(menu_completer),
}))
}
_ => Err(ShellError::UnsupportedConfigValue(
"block or omitted value".to_string(),
menu.source.into_abbreviated_string(config),
menu.source.span(),
)),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "block or omitted value".to_string(),
value: menu.source.into_abbreviated_string(config),
span: menu.source.span(),
}),
}
}
@ -461,11 +461,11 @@ pub(crate) fn add_description_menu(
completer: Box::new(menu_completer),
}))
}
_ => Err(ShellError::UnsupportedConfigValue(
"closure or omitted value".to_string(),
menu.source.into_abbreviated_string(config),
menu.source.span(),
)),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "closure or omitted value".to_string(),
value: menu.source.into_abbreviated_string(config),
span: menu.source.span(),
}),
}
}
@ -580,11 +580,11 @@ fn add_keybinding(
"emacs" => add_parsed_keybinding(emacs_keybindings, keybinding, config),
"vi_insert" => add_parsed_keybinding(insert_keybindings, keybinding, config),
"vi_normal" => add_parsed_keybinding(normal_keybindings, keybinding, config),
m => Err(ShellError::UnsupportedConfigValue(
"emacs, vi_insert or vi_normal".to_string(),
m.to_string(),
m => Err(ShellError::UnsupportedConfigValue {
expected: "emacs, vi_insert or vi_normal".to_string(),
value: m.to_string(),
span,
)),
}),
},
Value::List { vals, .. } => {
for inner_mode in vals {
@ -600,11 +600,11 @@ fn add_keybinding(
Ok(())
}
v => Err(ShellError::UnsupportedConfigValue(
"string or list of strings".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
v => Err(ShellError::UnsupportedConfigValue {
expected: "string or list of strings".to_string(),
value: v.into_abbreviated_string(config),
span: v.span(),
}),
}
}
@ -630,11 +630,11 @@ fn add_parsed_keybinding(
KeyModifiers::CONTROL | KeyModifiers::ALT | KeyModifiers::SHIFT
}
_ => {
return Err(ShellError::UnsupportedConfigValue(
"CONTROL, SHIFT, ALT or NONE".to_string(),
keybinding.modifier.into_abbreviated_string(config),
keybinding.modifier.span(),
))
return Err(ShellError::UnsupportedConfigValue {
expected: "CONTROL, SHIFT, ALT or NONE".to_string(),
value: keybinding.modifier.into_abbreviated_string(config),
span: keybinding.modifier.span(),
})
}
};
@ -654,11 +654,11 @@ fn add_parsed_keybinding(
let char = if let (Some(char), None) = (pos1, pos2) {
char
} else {
return Err(ShellError::UnsupportedConfigValue(
"char_<CHAR: unicode codepoint>".to_string(),
c.to_string(),
keybinding.keycode.span(),
));
return Err(ShellError::UnsupportedConfigValue {
expected: "char_<CHAR: unicode codepoint>".to_string(),
value: c.to_string(),
span: keybinding.keycode.span(),
});
};
KeyCode::Char(char)
@ -681,21 +681,21 @@ fn add_parsed_keybinding(
.parse()
.ok()
.filter(|num| matches!(num, 1..=20))
.ok_or(ShellError::UnsupportedConfigValue(
"(f1|f2|...|f20)".to_string(),
format!("unknown function key: {c}"),
keybinding.keycode.span(),
))?;
.ok_or(ShellError::UnsupportedConfigValue {
expected: "(f1|f2|...|f20)".to_string(),
value: format!("unknown function key: {c}"),
span: keybinding.keycode.span(),
})?;
KeyCode::F(fn_num)
}
"null" => KeyCode::Null,
"esc" | "escape" => KeyCode::Esc,
_ => {
return Err(ShellError::UnsupportedConfigValue(
"crossterm KeyCode".to_string(),
keybinding.keycode.into_abbreviated_string(config),
keybinding.keycode.span(),
))
return Err(ShellError::UnsupportedConfigValue {
expected: "crossterm KeyCode".to_string(),
value: keybinding.keycode.into_abbreviated_string(config),
span: keybinding.keycode.span(),
})
}
};
if let Some(event) = parse_event(&keybinding.event, config)? {
@ -719,7 +719,10 @@ impl<'config> EventType<'config> {
.map(Self::Send)
.or_else(|_| extract_value("edit", record, span).map(Self::Edit))
.or_else(|_| extract_value("until", record, span).map(Self::Until))
.map_err(|_| ShellError::MissingConfigValue("send, edit or until".to_string(), span))
.map_err(|_| ShellError::MissingConfigValue {
missing_value: "send, edit or until".to_string(),
span,
})
}
}
@ -749,11 +752,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
.iter()
.map(|value| match parse_event(value, config) {
Ok(inner) => match inner {
None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(),
"Nothing value (null)".to_string(),
value.span(),
)),
None => Err(ShellError::UnsupportedConfigValue {
expected: "List containing valid events".to_string(),
value: "Nothing value (null)".to_string(),
span: value.span(),
}),
Some(event) => Ok(event),
},
Err(e) => Err(e),
@ -762,11 +765,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
Ok(Some(ReedlineEvent::UntilFound(events)))
}
v => Err(ShellError::UnsupportedConfigValue(
"list of events".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
v => Err(ShellError::UnsupportedConfigValue {
expected: "list of events".to_string(),
value: v.into_abbreviated_string(config),
span: v.span(),
}),
},
},
Value::List { vals, .. } => {
@ -774,11 +777,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
.iter()
.map(|value| match parse_event(value, config) {
Ok(inner) => match inner {
None => Err(ShellError::UnsupportedConfigValue(
"List containing valid events".to_string(),
"Nothing value (null)".to_string(),
value.span(),
)),
None => Err(ShellError::UnsupportedConfigValue {
expected: "List containing valid events".to_string(),
value: "Nothing value (null)".to_string(),
span: value.span(),
}),
Some(event) => Ok(event),
},
Err(e) => Err(e),
@ -788,11 +791,11 @@ fn parse_event(value: &Value, config: &Config) -> Result<Option<ReedlineEvent>,
Ok(Some(ReedlineEvent::Multiple(events)))
}
Value::Nothing { .. } => Ok(None),
v => Err(ShellError::UnsupportedConfigValue(
"record or list of records, null to unbind key".to_string(),
v.into_abbreviated_string(config),
v.span(),
)),
v => Err(ShellError::UnsupportedConfigValue {
expected: "record or list of records, null to unbind key".to_string(),
value: v.into_abbreviated_string(config),
span: v.span(),
}),
}
}
@ -840,11 +843,11 @@ fn event_from_record(
ReedlineEvent::ExecuteHostCommand(cmd.into_string("", config))
}
v => {
return Err(ShellError::UnsupportedConfigValue(
"Reedline event".to_string(),
v.to_string(),
return Err(ShellError::UnsupportedConfigValue {
expected: "Reedline event".to_string(),
value: v.to_string(),
span,
))
})
}
};
@ -954,11 +957,11 @@ fn edit_from_record(
}
"complete" => EditCommand::Complete,
e => {
return Err(ShellError::UnsupportedConfigValue(
"reedline EditCommand".to_string(),
e.to_string(),
return Err(ShellError::UnsupportedConfigValue {
expected: "reedline EditCommand".to_string(),
value: e.to_string(),
span,
))
})
}
};
@ -971,7 +974,10 @@ fn extract_char(value: &Value, config: &Config) -> Result<char, ShellError> {
.into_string("", config)
.chars()
.next()
.ok_or_else(|| ShellError::MissingConfigValue("char to insert".to_string(), span))
.ok_or_else(|| ShellError::MissingConfigValue {
missing_value: "char to insert".to_string(),
span,
})
}
#[cfg(test)]
@ -1101,6 +1107,6 @@ mod test {
let span = Span::test_data();
let b = EventType::try_from_record(&event, span);
assert!(matches!(b, Err(ShellError::MissingConfigValue(_, _))));
assert!(matches!(b, Err(ShellError::MissingConfigValue { .. })));
}
}

View File

@ -90,11 +90,11 @@ pub fn eval_hook(
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue(
"valid source code".into(),
"source code with syntax errors".into(),
return Err(ShellError::UnsupportedConfigValue {
expected: "valid source code".into(),
value: "source code with syntax errors".into(),
span,
));
});
}
(output, working_set.render(), vars)
@ -164,11 +164,11 @@ pub fn eval_hook(
{
val
} else {
return Err(ShellError::UnsupportedConfigValue(
"boolean output".to_string(),
"other PipelineData variant".to_string(),
other_span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "boolean output".to_string(),
value: "other PipelineData variant".to_string(),
span: other_span,
});
}
}
Err(err) => {
@ -176,11 +176,11 @@ pub fn eval_hook(
}
}
} else {
return Err(ShellError::UnsupportedConfigValue(
"block".to_string(),
format!("{}", condition.get_type()),
other_span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "block".to_string(),
value: format!("{}", condition.get_type()),
span: other_span,
});
}
} else {
// always run the hook
@ -222,11 +222,11 @@ pub fn eval_hook(
if let Some(err) = working_set.parse_errors.first() {
report_error(&working_set, err);
return Err(ShellError::UnsupportedConfigValue(
"valid source code".into(),
"source code with syntax errors".into(),
source_span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "valid source code".into(),
value: "source code with syntax errors".into(),
span: source_span,
});
}
(output, working_set.render(), vars)
@ -277,11 +277,11 @@ pub fn eval_hook(
)?;
}
other => {
return Err(ShellError::UnsupportedConfigValue(
"block or string".to_string(),
format!("{}", other.get_type()),
source_span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "block or string".to_string(),
value: format!("{}", other.get_type()),
span: source_span,
});
}
}
}
@ -293,11 +293,11 @@ pub fn eval_hook(
output = run_hook_block(engine_state, stack, val.block_id, input, arguments, span)?;
}
other => {
return Err(ShellError::UnsupportedConfigValue(
"string, block, record, or list of commands".into(),
format!("{}", other.get_type()),
other.span(),
));
return Err(ShellError::UnsupportedConfigValue {
expected: "string, block, record, or list of commands".into(),
value: format!("{}", other.get_type()),
span: other.span(),
});
}
}

View File

@ -288,7 +288,10 @@ impl NuDataFrame {
.collect::<Vec<String>>();
let option = did_you_mean(&possibilities, column).unwrap_or_else(|| column.to_string());
ShellError::DidYouMean(option, span)
ShellError::DidYouMean {
suggestion: option,
span,
}
})?;
let df = DataFrame::new(vec![s.clone()]).map_err(|e| {

View File

@ -24,10 +24,10 @@ impl NuDataFrame {
match right {
Value::CustomValue { val: rhs, .. } => {
let rhs = rhs.as_any().downcast_ref::<NuDataFrame>().ok_or_else(|| {
ShellError::DowncastNotPossible(
"Unable to create dataframe".to_string(),
rhs_span,
)
ShellError::DowncastNotPossible {
msg: "Unable to create dataframe".to_string(),
span: rhs_span,
}
})?;
match (self.is_series(), rhs.is_series()) {

View File

@ -57,7 +57,10 @@ fn compute_with_value(
match right {
Value::CustomValue { val: rhs, .. } => {
let rhs = rhs.as_any().downcast_ref::<NuExpression>().ok_or_else(|| {
ShellError::DowncastNotPossible("Unable to create expression".to_string(), rhs_span)
ShellError::DowncastNotPossible {
msg: "Unable to create expression".into(),
span: rhs_span,
}
})?;
match rhs.as_ref() {

View File

@ -52,11 +52,11 @@ impl Command for HideEnv {
.cloned()
.collect();
if let Some(closest_match) = did_you_mean(&all_names, &name.item) {
return Err(ShellError::DidYouMeanCustom(
format!("Environment variable '{}' not found", name.item),
closest_match,
name.span,
));
return Err(ShellError::DidYouMeanCustom {
msg: format!("Environment variable '{}' not found", name.item),
suggestion: closest_match,
span: name.span,
});
} else {
return Err(ShellError::EnvVarNotFoundAtRuntime {
envvar_name: name.item,

View File

@ -96,7 +96,9 @@ impl Command for OverlayUse {
if let Some(name) = os_str.to_str() {
name.to_string()
} else {
return Err(ShellError::NonUtf8(name_arg.span));
return Err(ShellError::NonUtf8 {
span: name_arg.span,
});
}
} else {
return Err(ShellError::OverlayNotFoundAtRuntime {

View File

@ -248,7 +248,13 @@ mod test {
span,
),
Value::nothing(span),
Value::error(ShellError::DidYouMean("what?".to_string(), span), span),
Value::error(
ShellError::DidYouMean {
suggestion: "what?".to_string(),
span,
},
span,
),
Value::cell_path(
CellPath {
members: vec![PathMember::Int {

View File

@ -42,17 +42,25 @@ impl SQLiteDatabase {
span: Span,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<Self, ShellError> {
let mut file =
File::open(path).map_err(|e| ShellError::ReadingFile(e.to_string(), span))?;
let mut file = File::open(path).map_err(|e| ShellError::ReadingFile {
msg: e.to_string(),
span,
})?;
let mut buf: [u8; 16] = [0; 16];
file.read_exact(&mut buf)
.map_err(|e| ShellError::ReadingFile(e.to_string(), span))
.map_err(|e| ShellError::ReadingFile {
msg: e.to_string(),
span,
})
.and_then(|_| {
if buf == SQLITE_MAGIC_BYTES {
Ok(SQLiteDatabase::new(path, ctrlc))
} else {
Err(ShellError::ReadingFile("Not a SQLite file".into(), span))
Err(ShellError::ReadingFile {
msg: "Not a SQLite file".into(),
span,
})
}
})
}
@ -515,7 +523,7 @@ pub fn convert_sqlite_value_to_nu_value(value: ValueRef, span: Span) -> Value {
ValueRef::Text(buf) => {
let s = match std::str::from_utf8(buf) {
Ok(v) => v,
Err(_) => return Value::error(ShellError::NonUtf8(span), span),
Err(_) => return Value::error(ShellError::NonUtf8 { span }, span),
};
Value::string(s.to_string(), span)
}

View File

@ -746,14 +746,14 @@ mod windows_helper {
&mut find_data,
) {
Ok(_) => Ok(find_data),
Err(e) => Err(ShellError::ReadingFile(
format!(
Err(e) => Err(ShellError::ReadingFile {
msg: format!(
"Could not read metadata for '{}':\n '{}'",
filename.to_string_lossy(),
e
),
span,
)),
}),
}
}
}

View File

@ -393,7 +393,7 @@ fn rm(
if let Err(e) = result {
let msg = format!("Could not delete {:}: {e:}", f.to_string_lossy());
Value::error(ShellError::RemoveNotPossible(msg, span), span)
Value::error(ShellError::RemoveNotPossible { msg, span }, span)
} else if verbose {
let msg = if interactive && !confirmed {
"not deleted"

View File

@ -151,12 +151,13 @@ impl Command for Touch {
&item,
FileTime::from_system_time(date.expect("should be a valid date").into()),
) {
return Err(ShellError::ChangeModifiedTimeNotPossible(
format!("Failed to change the modified time: {err}"),
call.positional_nth(index)
return Err(ShellError::ChangeModifiedTimeNotPossible {
msg: format!("Failed to change the modified time: {err}"),
span: call
.positional_nth(index)
.expect("already checked positional")
.span,
));
});
};
}
@ -170,12 +171,13 @@ impl Command for Touch {
ref_date_atime.expect("should be a valid date").into(),
),
) {
return Err(ShellError::ChangeAccessTimeNotPossible(
format!("Failed to change the access time: {err}"),
call.positional_nth(index)
return Err(ShellError::ChangeAccessTimeNotPossible {
msg: format!("Failed to change the access time: {err}"),
span: call
.positional_nth(index)
.expect("already checked positional")
.span,
));
});
};
} else {
// Should not panic as we return an error above if we can't parse the date
@ -183,12 +185,13 @@ impl Command for Touch {
&item,
FileTime::from_system_time(date.expect("should be a valid date").into()),
) {
return Err(ShellError::ChangeAccessTimeNotPossible(
format!("Failed to change the access time: {err}"),
call.positional_nth(index)
return Err(ShellError::ChangeAccessTimeNotPossible {
msg: format!("Failed to change the access time: {err}"),
span: call
.positional_nth(index)
.expect("already checked positional")
.span,
));
});
};
}
}

View File

@ -50,7 +50,7 @@ impl Command for DropColumn {
let columns = if let Some(columns) = columns {
if columns.item < 0 {
return Err(ShellError::NeedsPositiveValue(columns.span));
return Err(ShellError::NeedsPositiveValue { span: columns.span });
} else {
columns.item as usize
}

View File

@ -96,7 +96,7 @@ fn first_helper(
// the first N elements is covered by `take`
let return_single_element = rows.is_none();
let rows_desired: usize = match rows {
Some(i) if i < 0 => return Err(ShellError::NeedsPositiveValue(head)),
Some(i) if i < 0 => return Err(ShellError::NeedsPositiveValue { span: head }),
Some(x) => x as usize,
None => 1,
};

View File

@ -77,7 +77,7 @@ impl Command for Last {
// It has the same issue.
let return_single_element = rows.is_none();
let rows_desired: usize = match rows {
Some(i) if i < 0 => return Err(ShellError::NeedsPositiveValue(head)),
Some(i) if i < 0 => return Err(ShellError::NeedsPositiveValue { span: head }),
Some(x) => x as usize,
None => 1,
};

View File

@ -145,10 +145,10 @@ fn from_csv(
let unicode_sep = u32::from_str_radix(&sep, 16);
char::from_u32(unicode_sep.unwrap_or(b'\x1f' as u32)).unwrap_or(',')
} else {
return Err(ShellError::NonUtf8Custom(
"separator should be a single char or a 4-byte unicode".to_string(),
call.span(),
));
return Err(ShellError::NonUtf8Custom {
msg: "separator should be a single char or a 4-byte unicode".into(),
span: call.span(),
});
}
}
None => ',',

View File

@ -390,7 +390,7 @@ fn to_xml(
let s = if let Ok(s) = String::from_utf8(b) {
s
} else {
return Err(ShellError::NonUtf8(head));
return Err(ShellError::NonUtf8 { span: head });
};
Ok(Value::string(s, head).into_pipeline_data())
})

View File

@ -302,16 +302,16 @@ impl UrlComponents {
return Ok(true);
}
match key {
"host" => Err(ShellError::UnsupportedConfigValue(
"non-empty string".into(),
"empty string".into(),
value_span,
)),
"scheme" => Err(ShellError::UnsupportedConfigValue(
"non-empty string".into(),
"empty string".into(),
value_span,
)),
"host" => Err(ShellError::UnsupportedConfigValue {
expected: "non-empty string".into(),
value: "empty string".into(),
span: value_span,
}),
"scheme" => Err(ShellError::UnsupportedConfigValue {
expected: "non-empty string".into(),
value: "empty string".into(),
span: value_span,
}),
_ => Ok(false),
}
}

View File

@ -82,12 +82,16 @@ impl Command for Du {
let max_depth: Option<Spanned<i64>> = call.get_flag(engine_state, stack, "max-depth")?;
if let Some(ref max_depth) = max_depth {
if max_depth.item < 0 {
return Err(ShellError::NeedsPositiveValue(max_depth.span));
return Err(ShellError::NeedsPositiveValue {
span: max_depth.span,
});
}
}
if let Some(ref min_size) = min_size {
if min_size.item < 0 {
return Err(ShellError::NeedsPositiveValue(min_size.span));
return Err(ShellError::NeedsPositiveValue {
span: min_size.span,
});
}
}
let current_dir = current_dir(engine_state, stack)?;

View File

@ -78,7 +78,7 @@ impl From<ShellError> for LabeledError {
msg: format!("can't convert from {input} to {expected}"),
span: Some(span),
},
ShellError::DidYouMean(suggestion, span) => LabeledError {
ShellError::DidYouMean { suggestion, span } => LabeledError {
label: "Name not found".into(),
msg: format!("did you mean '{suggestion}'?"),
span: Some(span),

View File

@ -129,5 +129,8 @@ pub fn extract_value<'record>(
) -> Result<&'record Value, ShellError> {
record
.get(name)
.ok_or_else(|| ShellError::MissingConfigValue(name.to_string(), span))
.ok_or_else(|| ShellError::MissingConfigValue {
missing_value: name.to_string(),
span,
})
}

View File

@ -46,23 +46,22 @@ pub(super) fn create_hooks(value: &Value) -> Result<Hooks, ShellError> {
"display_output" => hooks.display_output = Some(val.clone()),
"command_not_found" => hooks.command_not_found = Some(val.clone()),
x => {
return Err(ShellError::UnsupportedConfigValue(
"'pre_prompt', 'pre_execution', 'env_change', 'display_output', 'command_not_found'"
.to_string(),
x.to_string(),
span,
));
return Err(ShellError::UnsupportedConfigValue {
expected: "'pre_prompt', 'pre_execution', 'env_change', 'display_output', 'command_not_found'".into(),
value: x.into(),
span
});
}
}
}
Ok(hooks)
}
_ => Err(ShellError::UnsupportedConfigValue(
"record for 'hooks' config".into(),
"non-record value".into(),
_ => Err(ShellError::UnsupportedConfigValue {
expected: "record for 'hooks' config".into(),
value: "non-record value".into(),
span,
)),
}),
}
}

View File

@ -912,7 +912,11 @@ pub enum ShellError {
/// This can be for various reasons, such as your platform or permission flags. Refer to the specific error message for more details.
#[error("Not possible to change the access time")]
#[diagnostic(code(nu::shell::change_access_time_not_possible))]
ChangeAccessTimeNotPossible(String, #[label("{0}")] Span),
ChangeAccessTimeNotPossible {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Changing the modification time ("mtime") of this file is not possible.
///
@ -921,7 +925,11 @@ pub enum ShellError {
/// This can be for various reasons, such as your platform or permission flags. Refer to the specific error message for more details.
#[error("Not possible to change the modified time")]
#[diagnostic(code(nu::shell::change_modified_time_not_possible))]
ChangeModifiedTimeNotPossible(String, #[label("{0}")] Span),
ChangeModifiedTimeNotPossible {
msg: String,
#[label("{msg}")]
span: Span,
},
/// Unable to remove this item.
///
@ -930,7 +938,11 @@ pub enum ShellError {
/// Removal can fail for a number of reasons, such as permissions problems. Refer to the specific error message for more details.
#[error("Remove not possible")]
#[diagnostic(code(nu::shell::remove_not_possible))]
RemoveNotPossible(String, #[label("{0}")] Span),
RemoveNotPossible {
msg: String,
#[label("{msg}")]
span: Span,
},
// These three are unused. Remove?
#[error("No file to be removed")]
@ -947,7 +959,11 @@ pub enum ShellError {
/// The error will show the result from a file operation
#[error("Error trying to read file")]
#[diagnostic(code(nu::shell::error_reading_file))]
ReadingFile(String, #[label("{0}")] Span),
ReadingFile {
msg: String,
#[label("{msg}")]
span: Span,
},
/// A name was not found. Did you mean a different name?
///
@ -956,16 +972,25 @@ pub enum ShellError {
/// The error message will suggest a possible match for what you meant.
#[error("Name not found")]
#[diagnostic(code(nu::shell::name_not_found))]
DidYouMean(String, #[label("did you mean '{0}'?")] Span),
DidYouMean {
suggestion: String,
#[label("did you mean '{suggestion}'?")]
span: Span,
},
/// A name was not found. Did you mean a different name?
///
/// ## Resolution
///
/// The error message will suggest a possible match for what you meant.
#[error("{0}")]
#[error("{msg}")]
#[diagnostic(code(nu::shell::did_you_mean_custom))]
DidYouMeanCustom(String, String, #[label("did you mean '{1}'?")] Span),
DidYouMeanCustom {
msg: String,
suggestion: String,
#[label("did you mean '{suggestion}'?")]
span: Span,
},
/// The given input must be valid UTF-8 for further processing.
///
@ -974,7 +999,10 @@ pub enum ShellError {
/// Check your input's encoding. Are there any funny characters/bytes?
#[error("Non-UTF8 string")]
#[diagnostic(code(nu::parser::non_utf8))]
NonUtf8(#[label = "non-UTF8 string"] Span),
NonUtf8 {
#[label("non-UTF8 string")]
span: Span,
},
/// The given input must be valid UTF-8 for further processing.
///
@ -983,7 +1011,11 @@ pub enum ShellError {
/// Check your input's encoding. Are there any funny characters/bytes?
#[error("Non-UTF8 string")]
#[diagnostic(code(nu::parser::non_utf8_custom))]
NonUtf8Custom(String, #[label = "{0}"] Span),
NonUtf8Custom {
msg: String,
#[label("{msg}")]
span: Span,
},
/// A custom value could not be converted to a Dataframe.
///
@ -992,7 +1024,11 @@ pub enum ShellError {
/// Make sure conversion to a Dataframe is possible for this value or convert it to a type that does, first.
#[error("Casting error")]
#[diagnostic(code(nu::shell::downcast_not_possible))]
DowncastNotPossible(String, #[label("{0}")] Span),
DowncastNotPossible {
msg: String,
#[label("{msg}")]
span: Span,
},
/// The value given for this configuration is not supported.
///
@ -1001,7 +1037,12 @@ pub enum ShellError {
/// Refer to the specific error message for details and convert values as needed.
#[error("Unsupported config value")]
#[diagnostic(code(nu::shell::unsupported_config_value))]
UnsupportedConfigValue(String, String, #[label = "expected {0}, got {1}"] Span),
UnsupportedConfigValue {
expected: String,
value: String,
#[label("expected {expected}, got {value}")]
span: Span,
},
/// An expected configuration value is not present.
///
@ -1010,7 +1051,11 @@ pub enum ShellError {
/// Refer to the specific error message and add the configuration value to your config file as needed.
#[error("Missing config value")]
#[diagnostic(code(nu::shell::missing_config_value))]
MissingConfigValue(String, #[label = "missing {0}"] Span),
MissingConfigValue {
missing_value: String,
#[label("missing {missing_value}")]
span: Span,
},
/// Negative value passed when positive one is required.
///
@ -1019,7 +1064,10 @@ pub enum ShellError {
/// Guard against negative values or check your inputs.
#[error("Negative value passed when positive one is required")]
#[diagnostic(code(nu::shell::needs_positive_value))]
NeedsPositiveValue(#[label = "use a positive value"] Span),
NeedsPositiveValue {
#[label("use a positive value")]
span: Span,
},
/// This is a generic error type used for different situations.
#[error("{0}")]

View File

@ -91,7 +91,7 @@ impl FromValue for Spanned<usize> {
match v {
Value::Int { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(Spanned {
item: val as usize,
@ -101,7 +101,7 @@ impl FromValue for Spanned<usize> {
}
Value::Filesize { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(Spanned {
item: val as usize,
@ -111,7 +111,7 @@ impl FromValue for Spanned<usize> {
}
Value::Duration { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(Spanned {
item: val as usize,
@ -136,21 +136,21 @@ impl FromValue for usize {
match v {
Value::Int { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(val as usize)
}
}
Value::Filesize { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(val as usize)
}
}
Value::Duration { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(val as usize)
}
@ -300,7 +300,7 @@ impl FromValue for CellPath {
}),
Value::Int { val, .. } => {
if val.is_negative() {
Err(ShellError::NeedsPositiveValue(span))
Err(ShellError::NeedsPositiveValue { span })
} else {
Ok(CellPath {
members: vec![PathMember::Int {

View File

@ -1009,7 +1009,10 @@ impl Value {
} else if let Some(suggestion) =
did_you_mean(val.columns(), column_name)
{
return Err(ShellError::DidYouMean(suggestion, *origin_span));
return Err(ShellError::DidYouMean {
suggestion,
span: *origin_span,
});
} else {
return Err(ShellError::CantFindColumn {
col_name: column_name.clone(),
@ -1032,7 +1035,10 @@ impl Value {
} else if *optional {
return Ok(Value::nothing(*origin_span)); // short-circuit
} else if let Some(suggestion) = did_you_mean(&columns, column_name) {
return Err(ShellError::DidYouMean(suggestion, *origin_span));
return Err(ShellError::DidYouMean {
suggestion,
span: *origin_span,
});
} else {
return Err(ShellError::CantFindColumn {
col_name: column_name.clone(),
@ -1064,10 +1070,10 @@ impl Value {
} else if let Some(suggestion) =
did_you_mean(val.columns(), column_name)
{
Err(ShellError::DidYouMean(
Err(ShellError::DidYouMean {
suggestion,
*origin_span,
))
span: *origin_span,
})
} else {
Err(ShellError::CantFindColumn {
col_name: column_name.clone(),