-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathdiagnostics.rs
More file actions
122 lines (114 loc) · 4.6 KB
/
diagnostics.rs
File metadata and controls
122 lines (114 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use ariadne::{Color, Label, Report, ReportKind, Source};
use crate::errors::{CocError, ParseError, TypeError};
/// Enhanced error reporting with Ariadne
pub struct DiagnosticReporter<'a> {
filename: &'a str,
source: &'a str,
}
impl<'a> DiagnosticReporter<'a> {
pub fn new(filename: &'a str, source: &'a str) -> Self {
Self { filename, source }
}
/// Report a parsing error with nice formatting
pub fn report_parse_error(&self, error: &ParseError) {
match error {
ParseError::UnexpectedToken {
token,
expected,
location,
} => {
if let Some((start, end)) = location {
Report::build(ReportKind::Error, (self.filename, *start..*end))
.with_message(format!("Unexpected token '{}'", token))
.with_label(
Label::new((self.filename, *start..*end))
.with_message(format!("Expected one of: {}", expected.join(", ")))
.with_color(Color::Red),
)
.finish()
.print((self.filename, Source::from(self.source)))
.unwrap();
} else {
eprintln!(
"Parse error: Unexpected token '{}', expected: {}",
token,
expected.join(", ")
);
}
}
ParseError::UnexpectedEndOfInput { expected, location } => {
let loc = location.unwrap_or(self.source.len());
Report::build(ReportKind::Error, (self.filename, loc..loc))
.with_message("Unexpected end of input")
.with_label(
Label::new((self.filename, loc..loc))
.with_message(format!("Expected one of: {}", expected.join(", ")))
.with_color(Color::Red),
)
.finish()
.print((self.filename, Source::from(self.source)))
.unwrap();
}
ParseError::InvalidSyntax { message, location } => {
if let Some(loc) = location {
Report::build(ReportKind::Error, (self.filename, *loc..*loc + 1))
.with_message("Invalid syntax")
.with_label(
Label::new((self.filename, *loc..*loc + 1))
.with_message(message)
.with_color(Color::Red),
)
.finish()
.print((self.filename, Source::from(self.source)))
.unwrap();
} else {
eprintln!("Parse error: {}", message);
}
}
ParseError::LexicalError(err) => {
eprintln!("Lexical error: {}", err);
}
}
}
/// Report a type error with nice formatting
pub fn report_type_error(&self, error: &TypeError, location: Option<usize>) {
let loc = location.unwrap_or(0);
let message = format!("{}", error);
Report::build(ReportKind::Error, (self.filename, loc..loc + 1))
.with_message("Type error")
.with_label(
Label::new((self.filename, loc..loc + 1))
.with_message(message)
.with_color(Color::Red),
)
.finish()
.print((self.filename, Source::from(self.source)))
.unwrap();
}
/// Report a generic error
pub fn report_error(&self, error: &CocError) {
match error {
CocError::Parse(e) => self.report_parse_error(e),
CocError::Type(e) => self.report_type_error(e, None),
CocError::Lexical(e) => {
eprintln!("Lexical error: {}", e);
}
CocError::IO(e) => {
eprintln!("IO error: {}", e);
}
}
}
}
/// Create an error report with a specific location
pub fn create_error_at(filename: &str, source: &str, location: usize, message: &str) {
Report::build(ReportKind::Error, (filename, location..location + 1))
.with_message("Error")
.with_label(
Label::new((filename, location..location + 1))
.with_message(message)
.with_color(Color::Red),
)
.finish()
.print((filename, Source::from(source)))
.unwrap();
}