1#[derive(Debug, Clone, PartialEq, Eq)]
2pub struct Diagnostic {
3 pub severity: Severity,
4 pub code: &'static str,
5 pub message: String,
6 pub span: Span,
7 pub spec_reference: Option<SpecReference>,
8 pub recovery_note: Option<RecoveryNote>,
9}
10
11impl Diagnostic {
12 pub fn new(
13 severity: Severity,
14 code: &'static str,
15 message: impl Into<String>,
16 span: Span,
17 ) -> Self {
18 Self {
19 severity,
20 code,
21 message: message.into(),
22 span,
23 spec_reference: None,
24 recovery_note: None,
25 }
26 }
27
28 pub fn with_spec_reference(mut self, spec_reference: SpecReference) -> Self {
29 self.spec_reference = Some(spec_reference);
30 self
31 }
32
33 pub fn with_recovery_note(mut self, recovery_note: RecoveryNote) -> Self {
34 self.recovery_note = Some(recovery_note);
35 self
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct SpecReference {
41 pub label: String,
42 pub url: Option<String>,
43}
44
45impl SpecReference {
46 pub fn new(label: impl Into<String>) -> Self {
47 Self {
48 label: label.into(),
49 url: None,
50 }
51 }
52
53 pub fn with_url(mut self, url: impl Into<String>) -> Self {
54 self.url = Some(url.into());
55 self
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
60pub struct RecoveryNote {
61 pub message: String,
62}
63
64impl RecoveryNote {
65 pub fn new(message: impl Into<String>) -> Self {
66 Self {
67 message: message.into(),
68 }
69 }
70}
71
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum Severity {
74 Error,
75 Warning,
76 Info,
77}
78
79#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
80pub struct Span {
81 pub start: usize,
82 pub end: usize,
83}
84
85impl Span {
86 pub fn new(start: usize, end: usize) -> Self {
87 Self { start, end }
88 }
89
90 pub fn len(self) -> usize {
91 self.end.saturating_sub(self.start)
92 }
93
94 pub fn is_empty(self) -> bool {
95 self.start == self.end
96 }
97
98 pub fn contains(self, offset: usize) -> bool {
99 self.start <= offset && offset < self.end
100 }
101
102 pub fn contains_span(self, span: Span) -> bool {
103 self.start <= span.start && span.end <= self.end
104 }
105}
106
107#[cfg(test)]
108#[path = "diagnostic_tests.rs"]
109mod tests;