tan_lints/
lib.rs

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    /// A unique name for the lint.
11    fn name(&self) -> String;
12    // #todo needs return type.
13    /// Runs after the parsing pass.
14    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            // #todo use lsp_range_from_tan_range helper
23            // #todo move that helper to tan-analysis.
24            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            // #todo how to handle errors without range?
46        }
47    }
48
49    diagnostics
50}
51
52pub fn compute_diagnostics(parse_result: &Result<Vec<Expr>, Vec<Error>>) -> Vec<Diagnostic> {
53    // let result = parse_string_all(input);
54
55    // #todo should run all lints.
56
57    match parse_result {
58        Ok(exprs) => {
59            let mut diagnostics = Vec::new();
60
61            // #todo some Lints may need the input!
62            // #todo how to loop over lints?
63
64            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}