Skip to content

Commit a24fe90

Browse files
committed
feat: added typed errors
1 parent e306352 commit a24fe90

4 files changed

Lines changed: 266 additions & 57 deletions

File tree

cli/src/analyser/diagnostics.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use std::cmp::PartialEq;
2+
use std::path::Path;
3+
use std::process::exit;
4+
use code0_definition_reader::reader::ParsableDefinition;
5+
use crate::formatter::{error, warning};
6+
7+
#[derive(Default)]
8+
pub struct Reporter {
9+
diagnose: Vec<Diagnose>
10+
}
11+
12+
impl PartialEq for Severity {
13+
fn eq(&self, other: &Self) -> bool {
14+
match self {
15+
Severity::Error => {
16+
if let Severity::Error = other {
17+
return true;
18+
}
19+
false
20+
}
21+
Severity::Warning => {
22+
if let Severity::Warning = other {
23+
return true;
24+
}
25+
false
26+
}
27+
Severity::Debug => {
28+
if let Severity::Debug = other {
29+
return true;
30+
}
31+
false
32+
}
33+
}
34+
}
35+
}
36+
37+
impl Reporter {
38+
39+
pub fn add_report(&mut self, diagnose: Diagnose) {
40+
self.diagnose.push(diagnose);
41+
}
42+
43+
pub fn run_report(&self) {
44+
45+
for error in &self.get_errors() {
46+
println!("{}", error.print());
47+
}
48+
49+
for warning in &self.get_warnings() {
50+
println!("{}", warning.print());
51+
}
52+
53+
if !self.get_errors().is_empty() {
54+
exit(1)
55+
}
56+
57+
}
58+
59+
pub fn get_errors(&self) -> Vec<&Diagnose> {
60+
self.diagnose.iter().filter(|p| p.kind.severity() == Severity::Error).collect()
61+
}
62+
63+
pub fn get_warnings(&self) -> Vec<&Diagnose> {
64+
self.diagnose.iter().filter(|p| p.kind.severity() == Severity::Warning).collect()
65+
}
66+
67+
pub fn get_debug(&self) -> Vec<&Diagnose> {
68+
self.diagnose.iter().filter(|p| p.kind.severity() == Severity::Debug).collect()
69+
}
70+
71+
}
72+
73+
pub enum Severity {
74+
Error,
75+
Warning,
76+
Debug
77+
}
78+
79+
pub struct Diagnose {
80+
kind: DiagnosticKind,
81+
definition_name: String,
82+
definition: ParsableDefinition,
83+
}
84+
85+
pub enum DiagnosticKind {
86+
DeserializationError { description: String },
87+
DuplicateDataTypeIdentifier { identifier: String },
88+
UndefinedDataTypeIdentifier { identifier: String },
89+
NullField { field_name: String },
90+
ForbiddenVariant,
91+
UnusedGenericKey { key: String },
92+
UndefinedGenericKey { key: String },
93+
UndefinedTranslation { translation_field: String },
94+
}
95+
96+
impl DiagnosticKind {
97+
pub fn severity(&self) -> Severity {
98+
use DiagnosticKind::*;
99+
match self {
100+
DeserializationError { .. }
101+
| DuplicateDataTypeIdentifier { .. }
102+
| UndefinedDataTypeIdentifier { .. }
103+
| NullField { .. }
104+
| ForbiddenVariant { .. }
105+
| UnusedGenericKey { .. }
106+
| UndefinedGenericKey { .. } => Severity::Error,
107+
UndefinedTranslation { .. } => Severity::Warning,
108+
}
109+
}
110+
}
111+
112+
impl Diagnose {
113+
114+
pub fn new(definition_name: String, definition: ParsableDefinition, kind: DiagnosticKind) -> Self {
115+
Self {
116+
definition_name,
117+
definition,
118+
kind,
119+
}
120+
}
121+
122+
pub fn print(&self) -> String {
123+
124+
let path = format!(
125+
"{}:{}:{}",
126+
Path::new(&self.definition.path.clone().unwrap_or_default()).display(),
127+
&self.definition.starting_line,
128+
1
129+
);
130+
131+
use DiagnosticKind::*;
132+
match &self.kind {
133+
DeserializationError { description } =>
134+
error(format!("A JSON paring error occurred: `{}`", description), &path),
135+
DuplicateDataTypeIdentifier { identifier } =>
136+
error(format!("The data_type `{}` is already defined resulting in a duplicate!", identifier), &path),
137+
UndefinedDataTypeIdentifier { identifier } =>
138+
error(format!("`{}` uses an undefined data_type_identifier: `{}`!", self.definition_name, identifier), &path),
139+
NullField { field_name } =>
140+
error ( format!("`{}` has a field (`{}`) that is null!", self.definition_name, field_name), &path),
141+
ForbiddenVariant =>
142+
error(format!("The data_type variant of `{}` is 0 and thus incorrect!", self.definition_name), &path),
143+
UnusedGenericKey { key } =>
144+
error(format!("`{}` defined a generic_key (`{}`) that is never used!", self.definition_name, key), &path),
145+
UndefinedGenericKey { key } =>
146+
error(format!("`{}` uses a generic_key (`{}`) that's not defined!", self.definition_name, key), &path),
147+
UndefinedTranslation { translation_field } =>
148+
warning(format!("`{}` has an empty field (`{}`) of translations!", self.definition_name, translation_field), &path),
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)