Skip to main content

rantlr_core/
diagnostic.rs

1use std::fmt;
2
3use crate::fix_hint::FixHint;
4use crate::span::Span;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Severity {
8    Error,
9    Warning,
10    Hint,
11}
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum DiagnosticKind {
15    LexError,
16    ParseError,
17    Lint,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct Diagnostic {
22    pub severity: Severity,
23    pub kind: DiagnosticKind,
24    pub message: String,
25    pub span: Span,
26    pub help: Option<String>,
27    pub code: Option<String>,
28    pub fix: Option<FixHint>,
29}
30
31impl fmt::Display for Diagnostic {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        f.write_str(&self.message)
34    }
35}
36
37impl Diagnostic {
38    pub fn error(kind: DiagnosticKind, message: impl Into<String>, span: Span) -> Self {
39        Self {
40            severity: Severity::Error,
41            kind,
42            message: message.into(),
43            span,
44            help: None,
45            code: None,
46            fix: None,
47        }
48    }
49
50    pub fn with_help(mut self, help: impl Into<String>) -> Self {
51        self.help = Some(help.into());
52        self
53    }
54
55    pub fn with_code(mut self, code: impl Into<String>) -> Self {
56        self.code = Some(code.into());
57        self
58    }
59
60    pub fn with_fix(mut self, fix: FixHint) -> Self {
61        self.fix = Some(fix);
62        self
63    }
64
65    pub fn format(&self, source: &str, file: &str) -> String {
66        let (line, col) = self.span.line_col(source);
67        let mut out = format!(
68            "{file}:{line}:{col}: {:?}: {}",
69            self.severity, self.message
70        );
71        if let Some(help) = &self.help {
72            out.push_str("\n  help: ");
73            out.push_str(help);
74        }
75        out
76    }
77}