esl_compiler/
diagnostics.rs

1//! Reportable diagnostics for the Elephant Specification Language (ESL).
2use lsp_types::{
3    Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, NumberOrString, Range,
4};
5use strum::EnumMessage;
6
7/// Collected diagnostics.
8pub type Diagnostics = Vec<Diagnostic>;
9
10/// Reportable error diagnostics.
11#[derive(Clone, Debug, Default, PartialEq, strum::EnumMessage, strum::Display)]
12pub enum DiagnosticError {
13    /// An internal error occurred.
14    #[strum(message = "E000")]
15    #[default]
16    Internal,
17    /// Not an Elephant Specification Language file.
18    #[strum(message = "E001")]
19    NotAnElephantFile,
20    /// Syntax error. Please check this line, the section, or the continued (...) lines!
21    #[strum(message = "E002")]
22    Syntax,
23    /// Duplicate definition. Name already in use.
24    #[strum(message = "E003")]
25    DuplicateDefinition,
26    /// Missing when clause in a behavior requirement.
27    #[strum(message = "E004")]
28    MissingWhenClause,
29    /// Missing then clause in a behavior requirement.
30    #[strum(message = "E005")]
31    MissingThenClause,
32    /// At most one requiring section in a relation definition or instantiation.
33    #[strum(message = "E006")]
34    AtMostOneRequiring,
35    /// At most one relating section in a relation definition or instantiation.
36    #[strum(message = "E007")]
37    AtMostOneRelating,
38    /// At most one returning section in a relation definition or instantiation.
39    #[strum(message = "E008")]
40    AtMostOneReturning,
41    /// At most one unbounded ("one or more") parameter per parameter section is allowed.
42    #[strum(message = "E009")]
43    AtMostOneUnbounded,
44}
45impl DiagnosticError {
46    /// Create default diagnostic. Location at the start of the input.
47    pub fn diagnostic(
48        &self,
49        range: Range,
50        related_information: Option<Vec<DiagnosticRelatedInformation>>,
51    ) -> Diagnostic {
52        Diagnostic {
53            range,
54            severity: Some(DiagnosticSeverity::ERROR),
55            code: self.get_message().map(|m| NumberOrString::String(m.into())),
56            source: Some("ESL".into()),
57            message: self
58                .get_documentation()
59                .map(|d| d.into())
60                .unwrap_or_else(|| self.to_string()),
61            related_information,
62            ..Default::default()
63        }
64    }
65}
66
67/// Reportable error diagnostics.
68#[derive(Clone, Debug, Default, PartialEq, strum::EnumMessage, strum::Display)]
69pub enum DiagnosticWarning {
70    /// Generic unspecified warning.
71    #[strum(message = "W000")]
72    #[default]
73    Generic,
74    /// Documentation comment can't be attached to a proper subject.
75    #[strum(message = "W001")]
76    DanglingDocumentation,
77    /// Redefinition of content. Consider removing this instance.
78    #[strum(message = "W002")]
79    Redefinition,
80    /// Non-explicit empty definition. Please insert "empty" for a deliberately empty definition.
81    #[strum(message = "W003")]
82    EmptyDefinition,
83    /// Failed to parse value as a "real" number.
84    #[strum(message = "W004")]
85    NotARealNumber,
86    /// No valid content found for this definition. Add 'empty' on a separate line if it is
87    /// intentionally empty.
88    #[strum(message = "W005")]
89    ImplicitEmpty,
90}
91impl DiagnosticWarning {
92    pub fn diagnostic(
93        &self,
94        range: Range,
95        related_information: Option<Vec<DiagnosticRelatedInformation>>,
96    ) -> Diagnostic {
97        Diagnostic {
98            range,
99            severity: Some(DiagnosticSeverity::WARNING),
100            code: self.get_message().map(|m| NumberOrString::String(m.into())),
101            source: Some("ESL".into()),
102            message: self
103                .get_documentation()
104                .map(|d| d.into())
105                .unwrap_or_else(|| self.to_string()),
106            related_information,
107            ..Default::default()
108        }
109    }
110}