mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 11:05:40 +02:00
Refactor config updates (#13802)
# Description This PR standardizes updates to the config through a new `UpdateFromValue` trait. For now, this trait is private in case we need to make changes to it. Note that this PR adds some additional `ShellError` cases to create standard error messages for config errors. A follow-up PR will move usages of the old error cases to these new ones. This PR also uses `Type::custom` in lots of places (e.g., for string enums). Not sure if this is something we want to encourage. # User-Facing Changes Should be none.
This commit is contained in:
@ -15,8 +15,8 @@ use thiserror::Error;
|
||||
/// forwards most methods, except for `.source_code()`, which we provide.
|
||||
#[derive(Error)]
|
||||
#[error("{0}")]
|
||||
pub struct CliError<'src>(
|
||||
pub &'src (dyn miette::Diagnostic + Send + Sync + 'static),
|
||||
struct CliError<'src>(
|
||||
pub &'src dyn miette::Diagnostic,
|
||||
pub &'src StateWorkingSet<'src>,
|
||||
);
|
||||
|
||||
@ -48,10 +48,7 @@ pub fn report_compile_error(working_set: &StateWorkingSet, error: &CompileError)
|
||||
report_error(working_set, error);
|
||||
}
|
||||
|
||||
fn report_error(
|
||||
working_set: &StateWorkingSet,
|
||||
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
|
||||
) {
|
||||
fn report_error(working_set: &StateWorkingSet, error: &dyn miette::Diagnostic) {
|
||||
eprintln!("Error: {:?}", CliError(error, working_set));
|
||||
// reset vt processing, aka ansi because illbehaved externals can break it
|
||||
#[cfg(windows)]
|
||||
@ -60,10 +57,7 @@ fn report_error(
|
||||
}
|
||||
}
|
||||
|
||||
fn report_warning(
|
||||
working_set: &StateWorkingSet,
|
||||
error: &(dyn miette::Diagnostic + Send + Sync + 'static),
|
||||
) {
|
||||
fn report_warning(working_set: &StateWorkingSet, error: &dyn miette::Diagnostic) {
|
||||
eprintln!("Warning: {:?}", CliError(error, working_set));
|
||||
// reset vt processing, aka ansi because illbehaved externals can break it
|
||||
#[cfg(windows)]
|
||||
|
56
crates/nu-protocol/src/errors/config_error.rs
Normal file
56
crates/nu-protocol/src/errors/config_error.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use crate::{ShellError, Span, Type};
|
||||
use miette::Diagnostic;
|
||||
use thiserror::Error;
|
||||
|
||||
/// The errors that may occur when updating the config
|
||||
#[derive(Clone, Debug, PartialEq, Error, Diagnostic)]
|
||||
pub enum ConfigError {
|
||||
#[error("Type mismatch at {path}")]
|
||||
#[diagnostic(code(nu::shell::type_mismatch))]
|
||||
TypeMismatch {
|
||||
path: String,
|
||||
expected: Type,
|
||||
actual: Type,
|
||||
#[label = "expected {expected}, but got {actual}"]
|
||||
span: Span,
|
||||
},
|
||||
#[error("Invalid value for {path}")]
|
||||
#[diagnostic(code(nu::shell::invalid_value))]
|
||||
InvalidValue {
|
||||
path: String,
|
||||
valid: String,
|
||||
actual: String,
|
||||
#[label = "expected {valid}, but got {actual}"]
|
||||
span: Span,
|
||||
},
|
||||
#[error("Unknown config option: {path}")]
|
||||
#[diagnostic(code(nu::shell::unknown_config_option))]
|
||||
UnknownOption {
|
||||
path: String,
|
||||
#[label("remove this")]
|
||||
span: Span,
|
||||
},
|
||||
#[error("{path} requires a '{column}' column")]
|
||||
#[diagnostic(code(nu::shell::missing_required_column))]
|
||||
MissingRequiredColumn {
|
||||
path: String,
|
||||
column: &'static str,
|
||||
#[label("has no '{column}' column")]
|
||||
span: Span,
|
||||
},
|
||||
#[error("{path} is deprecated")]
|
||||
#[diagnostic(
|
||||
code(nu::shell::deprecated_config_option),
|
||||
help("please {suggestion} instead")
|
||||
)]
|
||||
Deprecated {
|
||||
path: String,
|
||||
suggestion: &'static str,
|
||||
#[label("deprecated")]
|
||||
span: Span,
|
||||
},
|
||||
// TODO: remove this
|
||||
#[error(transparent)]
|
||||
#[diagnostic(transparent)]
|
||||
ShellError(#[from] ShellError),
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
pub mod cli_error;
|
||||
mod compile_error;
|
||||
mod config_error;
|
||||
mod labeled_error;
|
||||
mod parse_error;
|
||||
mod parse_warning;
|
||||
@ -10,6 +11,7 @@ pub use cli_error::{
|
||||
report_shell_warning,
|
||||
};
|
||||
pub use compile_error::CompileError;
|
||||
pub use config_error::ConfigError;
|
||||
pub use labeled_error::{ErrorLabel, LabeledError};
|
||||
pub use parse_error::{DidYouMean, ParseError};
|
||||
pub use parse_warning::ParseWarning;
|
||||
|
@ -1,13 +1,12 @@
|
||||
use crate::{
|
||||
ast::Operator, engine::StateWorkingSet, format_shell_error, record, ConfigError, LabeledError,
|
||||
ParseError, Span, Spanned, Type, Value,
|
||||
};
|
||||
use miette::Diagnostic;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{io, num::NonZeroI32};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
ast::Operator, engine::StateWorkingSet, format_shell_error, record, LabeledError, ParseError,
|
||||
Span, Spanned, Value,
|
||||
};
|
||||
|
||||
/// The fundamental error type for the evaluation engine. These cases represent different kinds of errors
|
||||
/// the evaluator might face, along with helpful spans to label. An error renderer will take this error value
|
||||
/// and pass it into an error viewer to display to the user.
|
||||
@ -108,6 +107,34 @@ pub enum ShellError {
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// A value's type did not match the expected type.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Convert the value to the correct type or provide a value of the correct type.
|
||||
#[error("Type mismatch")]
|
||||
#[diagnostic(code(nu::shell::type_mismatch))]
|
||||
RuntimeTypeMismatch {
|
||||
expected: Type,
|
||||
actual: Type,
|
||||
#[label = "expected {expected}, but got {actual}"]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// A value had the correct type but is otherwise invalid.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Ensure the value meets the criteria in the error message.
|
||||
#[error("Invalid value")]
|
||||
#[diagnostic(code(nu::shell::invalid_value))]
|
||||
InvalidValue {
|
||||
valid: String,
|
||||
actual: String,
|
||||
#[label = "expected {valid}, but got {actual}"]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// A command received an argument with correct type but incorrect value.
|
||||
///
|
||||
/// ## Resolution
|
||||
@ -1085,30 +1112,28 @@ pub enum ShellError {
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// The value given for this configuration is not supported.
|
||||
/// Failed to update the config due to one or more errors.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// 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 {
|
||||
expected: String,
|
||||
value: String,
|
||||
#[label("expected {expected}, got {value}")]
|
||||
span: Span,
|
||||
/// Refer to the error messages for specific details.
|
||||
#[error("Encountered {} error(s) when updating config", errors.len())]
|
||||
#[diagnostic(code(nu::shell::invalid_config))]
|
||||
InvalidConfig {
|
||||
#[related]
|
||||
errors: Vec<ConfigError>,
|
||||
},
|
||||
|
||||
/// An expected configuration value is not present.
|
||||
/// A value was missing a required column.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// 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 {
|
||||
missing_value: String,
|
||||
#[label("missing {missing_value}")]
|
||||
/// Make sure the value has the required column.
|
||||
#[error("Value is missing a required '{column}' column")]
|
||||
#[diagnostic(code(nu::shell::missing_required_column))]
|
||||
MissingRequiredColumn {
|
||||
column: &'static str,
|
||||
#[label("has no '{column}' column")]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
|
Reference in New Issue
Block a user