Skip to main content

kcl_error/
lib.rs

1pub use error::BacktraceItem;
2pub use error::BacktraceItemKind;
3pub use error::IsRetryable;
4pub use error::KclError;
5pub use error::KclErrorDetails;
6use schemars::JsonSchema;
7use serde::Deserialize;
8use serde::Serialize;
9pub use source_range::ModuleId;
10pub use source_range::SourceRange;
11
12mod error;
13mod source_range;
14
15/// An issue which occurred during parsing, etc. The severity determines whether
16/// it's an error, warning, or other kind of issue.
17#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS, PartialEq, Eq, JsonSchema)]
18#[ts(export)]
19pub struct CompilationIssue {
20    #[serde(rename = "sourceRange")]
21    pub source_range: SourceRange,
22    pub message: String,
23    pub suggestion: Option<Suggestion>,
24    pub severity: Severity,
25    pub tag: Tag,
26}
27
28impl CompilationIssue {
29    pub fn err(source_range: SourceRange, message: impl ToString) -> CompilationIssue {
30        CompilationIssue {
31            source_range,
32            message: message.to_string(),
33            suggestion: None,
34            severity: Severity::Error,
35            tag: Tag::None,
36        }
37    }
38
39    pub fn fatal(source_range: SourceRange, message: impl ToString) -> CompilationIssue {
40        CompilationIssue {
41            source_range,
42            message: message.to_string(),
43            suggestion: None,
44            severity: Severity::Fatal,
45            tag: Tag::None,
46        }
47    }
48
49    pub fn with_suggestion(
50        self,
51        suggestion_title: impl ToString,
52        suggestion_insert: impl ToString,
53        // Will use the error source range if none is supplied
54        source_range: Option<SourceRange>,
55        tag: Tag,
56    ) -> CompilationIssue {
57        CompilationIssue {
58            suggestion: Some(Suggestion {
59                title: suggestion_title.to_string(),
60                insert: suggestion_insert.to_string(),
61                source_range: source_range.unwrap_or(self.source_range),
62            }),
63            tag,
64            ..self
65        }
66    }
67
68    #[cfg(test)]
69    pub fn apply_suggestion(&self, src: &str) -> Option<String> {
70        let suggestion = self.suggestion.as_ref()?;
71        Some(format!(
72            "{}{}{}",
73            &src[0..suggestion.source_range.start()],
74            suggestion.insert,
75            &src[suggestion.source_range.end()..]
76        ))
77    }
78
79    pub fn is_err(&self) -> bool {
80        self.severity.is_err()
81    }
82}
83
84#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, ts_rs::TS, JsonSchema)]
85#[ts(export)]
86pub enum Severity {
87    Warning,
88    Error,
89    Fatal,
90}
91
92impl Severity {
93    pub fn is_warning(self) -> bool {
94        match self {
95            Severity::Warning => true,
96            Severity::Error => false,
97            Severity::Fatal => false,
98        }
99    }
100
101    pub fn is_err(self) -> bool {
102        match self {
103            Severity::Warning => false,
104            Severity::Error | Severity::Fatal => true,
105        }
106    }
107
108    pub fn is_fatal(self) -> bool {
109        match self {
110            Severity::Warning => false,
111            Severity::Error => false,
112            Severity::Fatal => true,
113        }
114    }
115}
116
117#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, ts_rs::TS, JsonSchema)]
118#[ts(export)]
119pub enum Tag {
120    Deprecated,
121    Unnecessary,
122    UnknownNumericUnits,
123    None,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize, ts_rs::TS, PartialEq, Eq, JsonSchema)]
127#[ts(export)]
128pub struct Suggestion {
129    pub title: String,
130    pub insert: String,
131    pub source_range: SourceRange,
132}
133
134impl Suggestion {
135    /// Apply the suggestion to the source code.
136    pub fn apply(&self, src: &str) -> String {
137        format!(
138            "{}{}{}",
139            &src[0..self.source_range.start()],
140            self.insert,
141            &src[self.source_range.end()..]
142        )
143    }
144}