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:
Ian Manske
2024-10-11 09:40:32 -07:00
committed by GitHub
parent 02313e6819
commit fce6146576
32 changed files with 1343 additions and 1487 deletions

View File

@ -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,
},