Skip to main content

kcl_error/
lib.rs

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