1pub mod lints;
2
3use lints::snake_case_names_lint::SnakeCaseNamesLint;
4pub use lsp_types::{Diagnostic, DiagnosticSeverity, Range};
5use tan::{ann::Ann, api::parse_string_all, error::Error, expr::Expr};
6
7pub trait Lint {
8 fn name(&self) -> String;
10 fn run(&mut self, exprs: &[Ann<Expr>]);
13}
14
15pub fn compute_parse_error_diagnostics(errors: Vec<Error>) -> Vec<Diagnostic> {
16 let mut diagnostics: Vec<Diagnostic> = Vec::new();
17
18 for error in errors {
19 if let Some(range) = error.range() {
20 let start = lsp_types::Position {
21 line: range.start.line as u32,
22 character: range.start.col as u32,
23 };
24 let end = lsp_types::Position {
25 line: range.end.line as u32,
26 character: range.end.col as u32,
27 };
28
29 diagnostics.push(Diagnostic {
30 range: Range { start, end },
31 severity: None,
32 code: None,
33 code_description: None,
34 source: None,
35 message: error.to_string(),
36 related_information: None,
37 tags: None,
38 data: None,
39 });
40 } else {
41 }
43 }
44
45 diagnostics
46}
47
48pub fn compute_diagnostics(input: &str) -> Vec<Diagnostic> {
49 let result = parse_string_all(input);
50
51 let diagnostics = match result {
54 Ok(exprs) => {
55 let mut diagnostics = Vec::new();
56
57 let mut lint = SnakeCaseNamesLint::new();
60 lint.run(&exprs);
61 diagnostics.append(&mut lint.diagnostics);
62
63 diagnostics
64 }
65 Err(errors) => compute_parse_error_diagnostics(errors),
66 };
67
68 diagnostics
69}