rantlr_core/
diagnostic.rs1use 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}