1use crate::location::SourceCoords;
5
6#[derive(Copy, Clone, PartialEq, Eq, Debug)]
8pub enum DiagKind {
9 Error,
10 Warning,
11 Note,
12}
13
14#[derive(Copy, Clone, PartialEq, Eq, Debug)]
16pub enum Subsystem {
17 Unspecified,
19 Lexer,
21 Parser,
23}
24
25#[derive(Copy, Clone, Debug)]
27pub struct OutputOptions {
28 pub show_colors: bool,
30 pub preferred_max_error_width: Option<usize>,
32}
33
34impl OutputOptions {
35 pub const TAB_STOP: usize = 8;
37 pub const MINIMUM_SOURCE_CONTEXT: usize = 16;
39}
40
41impl Default for OutputOptions {
42 fn default() -> Self {
43 OutputOptions {
44 show_colors: true,
45 preferred_max_error_width: None,
46 }
47 }
48}
49
50#[derive(Clone, Debug)]
53pub struct ResolvedDiagnostic {
54 pub kind: DiagKind,
55 pub file_name: String,
56 pub line: u32,
58 pub col: u32,
59 pub message: String,
60 pub source_line: Option<String>,
62 pub range_cols: Option<(u32, u32)>,
66}
67
68pub trait DiagHandler {
71 fn handle(&mut self, diag: &ResolvedDiagnostic);
72 fn as_any(&self) -> &dyn std::any::Any;
74}
75
76pub trait CoordTranslator {
79 fn translate(&self, coords: &mut SourceCoords);
80}
81
82pub struct CollectingHandler {
84 messages: Vec<ResolvedDiagnostic>,
85}
86
87impl CollectingHandler {
88 pub fn new() -> CollectingHandler {
89 CollectingHandler {
90 messages: Vec::new(),
91 }
92 }
93
94 pub fn messages(&self) -> &[ResolvedDiagnostic] {
95 &self.messages
96 }
97}
98
99impl Default for CollectingHandler {
100 fn default() -> Self {
101 Self::new()
102 }
103}
104
105impl DiagHandler for CollectingHandler {
106 fn handle(&mut self, diag: &ResolvedDiagnostic) {
107 self.messages.push(diag.clone());
108 }
109
110 fn as_any(&self) -> &dyn std::any::Any {
111 self
112 }
113}
114
115#[derive(Copy, Clone, PartialEq, Eq, Debug)]
118pub enum Warning {
119 NoWarning,
122 UndefinedVariable,
124 DirectEval,
126 EvalDisabled,
128 UnresolvedStaticRequire,
131 Misc,
133}
134
135impl Warning {
136 pub const COUNT: usize = 6;
138
139 pub fn index(self) -> usize {
141 self as usize
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn collecting_handler_records() {
151 let mut h = CollectingHandler::new();
152 h.handle(&ResolvedDiagnostic {
153 kind: DiagKind::Error,
154 line: 3,
155 col: 5,
156 file_name: "a.js".into(),
157 message: "boom".into(),
158 source_line: Some(" let x".into()),
159 range_cols: None,
160 });
161 assert_eq!(h.messages().len(), 1);
162 assert_eq!(h.messages()[0].kind, DiagKind::Error);
163 assert_eq!((h.messages()[0].line, h.messages()[0].col), (3, 5));
164 }
165
166 #[test]
167 fn output_options_defaults() {
168 let o = OutputOptions::default();
169 assert!(o.show_colors);
170 assert_eq!(OutputOptions::TAB_STOP, 8);
171 }
172
173 #[test]
174 fn warning_index_within_count() {
175 assert_eq!(Warning::NoWarning.index(), 0);
176 assert!(Warning::Misc.index() < Warning::COUNT);
177 assert_eq!(Warning::COUNT, 6);
178 }
179}