1use duck_diagnostic::*;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4enum LangError {
5 UnterminatedString,
6 InvalidCharacter,
7 UnexpectedToken,
8 MissingSemicolon,
9 ExpectedExpression,
10 UndeclaredVariable,
11 TypeMismatch,
12 UnusedVariable,
13 UnreachableCode,
14}
15
16impl DiagnosticCode for LangError {
17 fn code(&self) -> &str {
18 match self {
19 Self::UnterminatedString => "E0001",
20 Self::InvalidCharacter => "E0002",
21 Self::UnexpectedToken => "E0100",
22 Self::MissingSemicolon => "E0101",
23 Self::ExpectedExpression => "E0102",
24 Self::UndeclaredVariable => "E0200",
25 Self::TypeMismatch => "E0201",
26 Self::UnusedVariable => "W0001",
27 Self::UnreachableCode => "W0002",
28 }
29 }
30
31 fn severity(&self) -> Severity {
32 match self {
33 Self::UnusedVariable | Self::UnreachableCode => Severity::Warning,
34 _ => Severity::Error,
35 }
36 }
37}
38
39fn main() {
40 let source = r#"fn main() {
41 let name = "hello
42 let x = 42;
43 println(name);
44}"#;
45
46 let mut engine = DiagnosticEngine::<LangError>::new();
47
48 engine.emit(
49 Diagnostic::new(LangError::UnterminatedString, "unterminated string literal")
50 .with_label(Label::primary(
51 Span::new("main.lang", 2, 16, 6),
52 Some("string starts here but never closes".into()),
53 ))
54 .with_help("close the string with a matching `\"`"),
55 );
56
57 engine.emit(
58 Diagnostic::new(LangError::UnusedVariable, "unused variable `x`")
59 .with_label(Label::primary(
60 Span::new("main.lang", 3, 8, 1),
61 Some("declared here but never used".into()),
62 ))
63 .with_help("prefix with `_` to silence: `_x`"),
64 );
65
66 engine.print_all(source);
67}