1pub mod lints;
2
3use lints::{
4 no_arrow_in_names_lint::NoArrowInNamesLint, snake_case_names_lint::SnakeCaseNamesLint,
5};
6pub use lsp_types::{Diagnostic, DiagnosticSeverity, Range};
7use tan::{error::Error, expr::Expr};
8
9pub trait Lint {
10 fn name(&self) -> String;
12 fn run(&mut self, exprs: &[Expr]);
15}
16
17pub fn compute_parse_error_diagnostics(errors: &[Error]) -> Vec<Diagnostic> {
18 let mut diagnostics: Vec<Diagnostic> = Vec::new();
19
20 for error in errors {
21 if let Some(range) = error.range() {
22 let start = lsp_types::Position {
25 line: range.start.line as u32,
26 character: range.start.col as u32,
27 };
28 let end = lsp_types::Position {
29 line: range.end.line as u32,
30 character: range.end.col as u32,
31 };
32
33 diagnostics.push(Diagnostic {
34 range: Range { start, end },
35 severity: None,
36 code: None,
37 code_description: None,
38 source: None,
39 message: error.to_string(),
40 related_information: None,
41 tags: None,
42 data: None,
43 });
44 } else {
45 }
47 }
48
49 diagnostics
50}
51
52pub fn compute_diagnostics(parse_result: &Result<Vec<Expr>, Vec<Error>>) -> Vec<Diagnostic> {
53 match parse_result {
58 Ok(exprs) => {
59 let mut diagnostics = Vec::new();
60
61 let mut lint = SnakeCaseNamesLint::new();
65 lint.run(&exprs);
66 diagnostics.append(&mut lint.diagnostics);
67
68 let mut lint = NoArrowInNamesLint::new();
69 lint.run(&exprs);
70 diagnostics.append(&mut lint.diagnostics);
71
72 diagnostics
73 }
74 Err(errors) => compute_parse_error_diagnostics(errors),
75 }
76}