KCL: Use named fields for KclError (#7321)
We've changed the unnamed field of `KclError` variants to a named called `details`. To clarify: previously KCL errors looked like this: ```rust pub enum KclError { Lexical(KclErrorDetails), Syntax(KclErrorDetails), ``` Now they look like this: ```rust pub enum KclError { Lexical { details: KclErrorDetails }, Syntax { details: KclErrorDetails }, } ``` This lets us more easily add fields to the errors. For example, in the UndefinedValue case, adding a field for what the undefined name was. This PR refactors the code to make my PR in https://github.com/KittyCAD/modeling-app/pull/7309 much easier. Pure refactor, should not change any behaviour.
This commit is contained in:
@ -91,30 +91,30 @@ pub enum ConnectionError {
|
||||
#[ts(export)]
|
||||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum KclError {
|
||||
#[error("lexical: {0:?}")]
|
||||
Lexical(KclErrorDetails),
|
||||
#[error("syntax: {0:?}")]
|
||||
Syntax(KclErrorDetails),
|
||||
#[error("semantic: {0:?}")]
|
||||
Semantic(KclErrorDetails),
|
||||
#[error("import cycle: {0:?}")]
|
||||
ImportCycle(KclErrorDetails),
|
||||
#[error("type: {0:?}")]
|
||||
Type(KclErrorDetails),
|
||||
#[error("i/o: {0:?}")]
|
||||
Io(KclErrorDetails),
|
||||
#[error("unexpected: {0:?}")]
|
||||
Unexpected(KclErrorDetails),
|
||||
#[error("value already defined: {0:?}")]
|
||||
ValueAlreadyDefined(KclErrorDetails),
|
||||
#[error("undefined value: {0:?}")]
|
||||
UndefinedValue(KclErrorDetails),
|
||||
#[error("invalid expression: {0:?}")]
|
||||
InvalidExpression(KclErrorDetails),
|
||||
#[error("engine: {0:?}")]
|
||||
Engine(KclErrorDetails),
|
||||
#[error("internal error, please report to KittyCAD team: {0:?}")]
|
||||
Internal(KclErrorDetails),
|
||||
#[error("lexical: {details:?}")]
|
||||
Lexical { details: KclErrorDetails },
|
||||
#[error("syntax: {details:?}")]
|
||||
Syntax { details: KclErrorDetails },
|
||||
#[error("semantic: {details:?}")]
|
||||
Semantic { details: KclErrorDetails },
|
||||
#[error("import cycle: {details:?}")]
|
||||
ImportCycle { details: KclErrorDetails },
|
||||
#[error("type: {details:?}")]
|
||||
Type { details: KclErrorDetails },
|
||||
#[error("i/o: {details:?}")]
|
||||
Io { details: KclErrorDetails },
|
||||
#[error("unexpected: {details:?}")]
|
||||
Unexpected { details: KclErrorDetails },
|
||||
#[error("value already defined: {details:?}")]
|
||||
ValueAlreadyDefined { details: KclErrorDetails },
|
||||
#[error("undefined value: {details:?}")]
|
||||
UndefinedValue { details: KclErrorDetails },
|
||||
#[error("invalid expression: {details:?}")]
|
||||
InvalidExpression { details: KclErrorDetails },
|
||||
#[error("engine: {details:?}")]
|
||||
Engine { details: KclErrorDetails },
|
||||
#[error("internal error, please report to KittyCAD team: {details:?}")]
|
||||
Internal { details: KclErrorDetails },
|
||||
}
|
||||
|
||||
impl From<KclErrorWithOutputs> for KclError {
|
||||
@ -296,18 +296,18 @@ pub struct ReportWithOutputs {
|
||||
impl miette::Diagnostic for ReportWithOutputs {
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
|
||||
let family = match self.error.error {
|
||||
KclError::Lexical(_) => "Lexical",
|
||||
KclError::Syntax(_) => "Syntax",
|
||||
KclError::Semantic(_) => "Semantic",
|
||||
KclError::ImportCycle(_) => "ImportCycle",
|
||||
KclError::Type(_) => "Type",
|
||||
KclError::Io(_) => "I/O",
|
||||
KclError::Unexpected(_) => "Unexpected",
|
||||
KclError::ValueAlreadyDefined(_) => "ValueAlreadyDefined",
|
||||
KclError::UndefinedValue(_) => "UndefinedValue",
|
||||
KclError::InvalidExpression(_) => "InvalidExpression",
|
||||
KclError::Engine(_) => "Engine",
|
||||
KclError::Internal(_) => "Internal",
|
||||
KclError::Lexical { .. } => "Lexical",
|
||||
KclError::Syntax { .. } => "Syntax",
|
||||
KclError::Semantic { .. } => "Semantic",
|
||||
KclError::ImportCycle { .. } => "ImportCycle",
|
||||
KclError::Type { .. } => "Type",
|
||||
KclError::Io { .. } => "I/O",
|
||||
KclError::Unexpected { .. } => "Unexpected",
|
||||
KclError::ValueAlreadyDefined { .. } => "ValueAlreadyDefined",
|
||||
KclError::UndefinedValue { .. } => "UndefinedValue",
|
||||
KclError::InvalidExpression { .. } => "InvalidExpression",
|
||||
KclError::Engine { .. } => "Engine",
|
||||
KclError::Internal { .. } => "Internal",
|
||||
};
|
||||
let error_string = format!("KCL {family} error");
|
||||
Some(Box::new(error_string))
|
||||
@ -346,18 +346,18 @@ pub struct Report {
|
||||
impl miette::Diagnostic for Report {
|
||||
fn code<'a>(&'a self) -> Option<Box<dyn std::fmt::Display + 'a>> {
|
||||
let family = match self.error {
|
||||
KclError::Lexical(_) => "Lexical",
|
||||
KclError::Syntax(_) => "Syntax",
|
||||
KclError::Semantic(_) => "Semantic",
|
||||
KclError::ImportCycle(_) => "ImportCycle",
|
||||
KclError::Type(_) => "Type",
|
||||
KclError::Io(_) => "I/O",
|
||||
KclError::Unexpected(_) => "Unexpected",
|
||||
KclError::ValueAlreadyDefined(_) => "ValueAlreadyDefined",
|
||||
KclError::UndefinedValue(_) => "UndefinedValue",
|
||||
KclError::InvalidExpression(_) => "InvalidExpression",
|
||||
KclError::Engine(_) => "Engine",
|
||||
KclError::Internal(_) => "Internal",
|
||||
KclError::Lexical { .. } => "Lexical",
|
||||
KclError::Syntax { .. } => "Syntax",
|
||||
KclError::Semantic { .. } => "Semantic",
|
||||
KclError::ImportCycle { .. } => "ImportCycle",
|
||||
KclError::Type { .. } => "Type",
|
||||
KclError::Io { .. } => "I/O",
|
||||
KclError::Unexpected { .. } => "Unexpected",
|
||||
KclError::ValueAlreadyDefined { .. } => "ValueAlreadyDefined",
|
||||
KclError::UndefinedValue { .. } => "UndefinedValue",
|
||||
KclError::InvalidExpression { .. } => "InvalidExpression",
|
||||
KclError::Engine { .. } => "Engine",
|
||||
KclError::Internal { .. } => "Internal",
|
||||
};
|
||||
let error_string = format!("KCL {family} error");
|
||||
Some(Box::new(error_string))
|
||||
@ -410,11 +410,53 @@ impl KclErrorDetails {
|
||||
|
||||
impl KclError {
|
||||
pub fn internal(message: String) -> KclError {
|
||||
KclError::Internal(KclErrorDetails {
|
||||
source_ranges: Default::default(),
|
||||
backtrace: Default::default(),
|
||||
message,
|
||||
})
|
||||
KclError::Internal {
|
||||
details: KclErrorDetails {
|
||||
source_ranges: Default::default(),
|
||||
backtrace: Default::default(),
|
||||
message,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_internal(details: KclErrorDetails) -> KclError {
|
||||
KclError::Internal { details }
|
||||
}
|
||||
|
||||
pub fn new_import_cycle(details: KclErrorDetails) -> KclError {
|
||||
KclError::ImportCycle { details }
|
||||
}
|
||||
|
||||
pub fn new_semantic(details: KclErrorDetails) -> KclError {
|
||||
KclError::Semantic { details }
|
||||
}
|
||||
|
||||
pub fn new_value_already_defined(details: KclErrorDetails) -> KclError {
|
||||
KclError::ValueAlreadyDefined { details }
|
||||
}
|
||||
|
||||
pub fn new_syntax(details: KclErrorDetails) -> KclError {
|
||||
KclError::Syntax { details }
|
||||
}
|
||||
|
||||
pub fn new_io(details: KclErrorDetails) -> KclError {
|
||||
KclError::Io { details }
|
||||
}
|
||||
|
||||
pub fn new_engine(details: KclErrorDetails) -> KclError {
|
||||
KclError::Engine { details }
|
||||
}
|
||||
|
||||
pub fn new_lexical(details: KclErrorDetails) -> KclError {
|
||||
KclError::Lexical { details }
|
||||
}
|
||||
|
||||
pub fn new_undefined_value(details: KclErrorDetails) -> KclError {
|
||||
KclError::UndefinedValue { details }
|
||||
}
|
||||
|
||||
pub fn new_type(details: KclErrorDetails) -> KclError {
|
||||
KclError::Type { details }
|
||||
}
|
||||
|
||||
/// Get the error message.
|
||||
@ -424,88 +466,88 @@ impl KclError {
|
||||
|
||||
pub fn error_type(&self) -> &'static str {
|
||||
match self {
|
||||
KclError::Lexical(_) => "lexical",
|
||||
KclError::Syntax(_) => "syntax",
|
||||
KclError::Semantic(_) => "semantic",
|
||||
KclError::ImportCycle(_) => "import cycle",
|
||||
KclError::Type(_) => "type",
|
||||
KclError::Io(_) => "i/o",
|
||||
KclError::Unexpected(_) => "unexpected",
|
||||
KclError::ValueAlreadyDefined(_) => "value already defined",
|
||||
KclError::UndefinedValue(_) => "undefined value",
|
||||
KclError::InvalidExpression(_) => "invalid expression",
|
||||
KclError::Engine(_) => "engine",
|
||||
KclError::Internal(_) => "internal",
|
||||
KclError::Lexical { .. } => "lexical",
|
||||
KclError::Syntax { .. } => "syntax",
|
||||
KclError::Semantic { .. } => "semantic",
|
||||
KclError::ImportCycle { .. } => "import cycle",
|
||||
KclError::Type { .. } => "type",
|
||||
KclError::Io { .. } => "i/o",
|
||||
KclError::Unexpected { .. } => "unexpected",
|
||||
KclError::ValueAlreadyDefined { .. } => "value already defined",
|
||||
KclError::UndefinedValue { .. } => "undefined value",
|
||||
KclError::InvalidExpression { .. } => "invalid expression",
|
||||
KclError::Engine { .. } => "engine",
|
||||
KclError::Internal { .. } => "internal",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source_ranges(&self) -> Vec<SourceRange> {
|
||||
match &self {
|
||||
KclError::Lexical(e) => e.source_ranges.clone(),
|
||||
KclError::Syntax(e) => e.source_ranges.clone(),
|
||||
KclError::Semantic(e) => e.source_ranges.clone(),
|
||||
KclError::ImportCycle(e) => e.source_ranges.clone(),
|
||||
KclError::Type(e) => e.source_ranges.clone(),
|
||||
KclError::Io(e) => e.source_ranges.clone(),
|
||||
KclError::Unexpected(e) => e.source_ranges.clone(),
|
||||
KclError::ValueAlreadyDefined(e) => e.source_ranges.clone(),
|
||||
KclError::UndefinedValue(e) => e.source_ranges.clone(),
|
||||
KclError::InvalidExpression(e) => e.source_ranges.clone(),
|
||||
KclError::Engine(e) => e.source_ranges.clone(),
|
||||
KclError::Internal(e) => e.source_ranges.clone(),
|
||||
KclError::Lexical { details: e } => e.source_ranges.clone(),
|
||||
KclError::Syntax { details: e } => e.source_ranges.clone(),
|
||||
KclError::Semantic { details: e } => e.source_ranges.clone(),
|
||||
KclError::ImportCycle { details: e } => e.source_ranges.clone(),
|
||||
KclError::Type { details: e } => e.source_ranges.clone(),
|
||||
KclError::Io { details: e } => e.source_ranges.clone(),
|
||||
KclError::Unexpected { details: e } => e.source_ranges.clone(),
|
||||
KclError::ValueAlreadyDefined { details: e } => e.source_ranges.clone(),
|
||||
KclError::UndefinedValue { details: e } => e.source_ranges.clone(),
|
||||
KclError::InvalidExpression { details: e } => e.source_ranges.clone(),
|
||||
KclError::Engine { details: e } => e.source_ranges.clone(),
|
||||
KclError::Internal { details: e } => e.source_ranges.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the inner error message.
|
||||
pub fn message(&self) -> &str {
|
||||
match &self {
|
||||
KclError::Lexical(e) => &e.message,
|
||||
KclError::Syntax(e) => &e.message,
|
||||
KclError::Semantic(e) => &e.message,
|
||||
KclError::ImportCycle(e) => &e.message,
|
||||
KclError::Type(e) => &e.message,
|
||||
KclError::Io(e) => &e.message,
|
||||
KclError::Unexpected(e) => &e.message,
|
||||
KclError::ValueAlreadyDefined(e) => &e.message,
|
||||
KclError::UndefinedValue(e) => &e.message,
|
||||
KclError::InvalidExpression(e) => &e.message,
|
||||
KclError::Engine(e) => &e.message,
|
||||
KclError::Internal(e) => &e.message,
|
||||
KclError::Lexical { details: e } => &e.message,
|
||||
KclError::Syntax { details: e } => &e.message,
|
||||
KclError::Semantic { details: e } => &e.message,
|
||||
KclError::ImportCycle { details: e } => &e.message,
|
||||
KclError::Type { details: e } => &e.message,
|
||||
KclError::Io { details: e } => &e.message,
|
||||
KclError::Unexpected { details: e } => &e.message,
|
||||
KclError::ValueAlreadyDefined { details: e } => &e.message,
|
||||
KclError::UndefinedValue { details: e } => &e.message,
|
||||
KclError::InvalidExpression { details: e } => &e.message,
|
||||
KclError::Engine { details: e } => &e.message,
|
||||
KclError::Internal { details: e } => &e.message,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backtrace(&self) -> Vec<BacktraceItem> {
|
||||
match self {
|
||||
KclError::Lexical(e)
|
||||
| KclError::Syntax(e)
|
||||
| KclError::Semantic(e)
|
||||
| KclError::ImportCycle(e)
|
||||
| KclError::Type(e)
|
||||
| KclError::Io(e)
|
||||
| KclError::Unexpected(e)
|
||||
| KclError::ValueAlreadyDefined(e)
|
||||
| KclError::UndefinedValue(e)
|
||||
| KclError::InvalidExpression(e)
|
||||
| KclError::Engine(e)
|
||||
| KclError::Internal(e) => e.backtrace.clone(),
|
||||
KclError::Lexical { details: e }
|
||||
| KclError::Syntax { details: e }
|
||||
| KclError::Semantic { details: e }
|
||||
| KclError::ImportCycle { details: e }
|
||||
| KclError::Type { details: e }
|
||||
| KclError::Io { details: e }
|
||||
| KclError::Unexpected { details: e }
|
||||
| KclError::ValueAlreadyDefined { details: e }
|
||||
| KclError::UndefinedValue { details: e }
|
||||
| KclError::InvalidExpression { details: e }
|
||||
| KclError::Engine { details: e }
|
||||
| KclError::Internal { details: e } => e.backtrace.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn override_source_ranges(&self, source_ranges: Vec<SourceRange>) -> Self {
|
||||
let mut new = self.clone();
|
||||
match &mut new {
|
||||
KclError::Lexical(e)
|
||||
| KclError::Syntax(e)
|
||||
| KclError::Semantic(e)
|
||||
| KclError::ImportCycle(e)
|
||||
| KclError::Type(e)
|
||||
| KclError::Io(e)
|
||||
| KclError::Unexpected(e)
|
||||
| KclError::ValueAlreadyDefined(e)
|
||||
| KclError::UndefinedValue(e)
|
||||
| KclError::InvalidExpression(e)
|
||||
| KclError::Engine(e)
|
||||
| KclError::Internal(e) => {
|
||||
KclError::Lexical { details: e }
|
||||
| KclError::Syntax { details: e }
|
||||
| KclError::Semantic { details: e }
|
||||
| KclError::ImportCycle { details: e }
|
||||
| KclError::Type { details: e }
|
||||
| KclError::Io { details: e }
|
||||
| KclError::Unexpected { details: e }
|
||||
| KclError::ValueAlreadyDefined { details: e }
|
||||
| KclError::UndefinedValue { details: e }
|
||||
| KclError::InvalidExpression { details: e }
|
||||
| KclError::Engine { details: e }
|
||||
| KclError::Internal { details: e } => {
|
||||
e.backtrace = source_ranges
|
||||
.iter()
|
||||
.map(|s| BacktraceItem {
|
||||
@ -523,18 +565,18 @@ impl KclError {
|
||||
pub(crate) fn set_last_backtrace_fn_name(&self, last_fn_name: Option<String>) -> Self {
|
||||
let mut new = self.clone();
|
||||
match &mut new {
|
||||
KclError::Lexical(e)
|
||||
| KclError::Syntax(e)
|
||||
| KclError::Semantic(e)
|
||||
| KclError::ImportCycle(e)
|
||||
| KclError::Type(e)
|
||||
| KclError::Io(e)
|
||||
| KclError::Unexpected(e)
|
||||
| KclError::ValueAlreadyDefined(e)
|
||||
| KclError::UndefinedValue(e)
|
||||
| KclError::InvalidExpression(e)
|
||||
| KclError::Engine(e)
|
||||
| KclError::Internal(e) => {
|
||||
KclError::Lexical { details: e }
|
||||
| KclError::Syntax { details: e }
|
||||
| KclError::Semantic { details: e }
|
||||
| KclError::ImportCycle { details: e }
|
||||
| KclError::Type { details: e }
|
||||
| KclError::Io { details: e }
|
||||
| KclError::Unexpected { details: e }
|
||||
| KclError::ValueAlreadyDefined { details: e }
|
||||
| KclError::UndefinedValue { details: e }
|
||||
| KclError::InvalidExpression { details: e }
|
||||
| KclError::Engine { details: e }
|
||||
| KclError::Internal { details: e } => {
|
||||
if let Some(item) = e.backtrace.last_mut() {
|
||||
item.fn_name = last_fn_name;
|
||||
}
|
||||
@ -547,18 +589,18 @@ impl KclError {
|
||||
pub(crate) fn add_unwind_location(&self, last_fn_name: Option<String>, source_range: SourceRange) -> Self {
|
||||
let mut new = self.clone();
|
||||
match &mut new {
|
||||
KclError::Lexical(e)
|
||||
| KclError::Syntax(e)
|
||||
| KclError::Semantic(e)
|
||||
| KclError::ImportCycle(e)
|
||||
| KclError::Type(e)
|
||||
| KclError::Io(e)
|
||||
| KclError::Unexpected(e)
|
||||
| KclError::ValueAlreadyDefined(e)
|
||||
| KclError::UndefinedValue(e)
|
||||
| KclError::InvalidExpression(e)
|
||||
| KclError::Engine(e)
|
||||
| KclError::Internal(e) => {
|
||||
KclError::Lexical { details: e }
|
||||
| KclError::Syntax { details: e }
|
||||
| KclError::Semantic { details: e }
|
||||
| KclError::ImportCycle { details: e }
|
||||
| KclError::Type { details: e }
|
||||
| KclError::Io { details: e }
|
||||
| KclError::Unexpected { details: e }
|
||||
| KclError::ValueAlreadyDefined { details: e }
|
||||
| KclError::UndefinedValue { details: e }
|
||||
| KclError::InvalidExpression { details: e }
|
||||
| KclError::Engine { details: e }
|
||||
| KclError::Internal { details: e } => {
|
||||
if let Some(item) = e.backtrace.last_mut() {
|
||||
item.fn_name = last_fn_name;
|
||||
}
|
||||
@ -645,7 +687,7 @@ impl From<String> for KclError {
|
||||
#[cfg(feature = "pyo3")]
|
||||
impl From<pyo3::PyErr> for KclError {
|
||||
fn from(error: pyo3::PyErr) -> Self {
|
||||
KclError::Internal(KclErrorDetails {
|
||||
KclError::new_internal(KclErrorDetails {
|
||||
source_ranges: vec![],
|
||||
backtrace: Default::default(),
|
||||
message: error.to_string(),
|
||||
|
Reference in New Issue
Block a user