This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/crates/el-lint/src/linter.rs
T

77 lines
2.2 KiB
Rust

//! Core linter — orchestrates arch rules, style rules, and format check.
use el_arch::{ArchChecker, Severity as ArchSeverity};
use crate::{
error::LintError,
report::{LintDiagnostic, LintReport, LintSeverity},
rules,
};
pub struct Linter {
arch_checker: ArchChecker,
}
impl Linter {
pub fn new() -> Self {
Self {
arch_checker: ArchChecker::new(),
}
}
pub fn lint(&self, source: &str) -> Result<LintReport, LintError> {
let tokens = el_lexer::tokenize(source)
.map_err(|e| LintError::Lex(e.to_string()))?;
let program = el_parser::parse(tokens, source.to_string())
.map_err(|e| LintError::Parse(e.to_string()))?;
let mut diagnostics = Vec::new();
// 1. Run el-arch architectural rules.
let arch_diags = self.arch_checker.check(&program);
for d in arch_diags {
diagnostics.push(LintDiagnostic {
severity: match d.severity {
ArchSeverity::Error => LintSeverity::Error,
ArchSeverity::Warning => LintSeverity::Warning,
},
code: d.rule,
message: d.message,
location: d.location.unwrap_or_else(|| "unknown".into()),
suggestion: None,
});
}
// 2. Run style rules.
let style_diags = rules::check_style(&program);
diagnostics.extend(style_diags);
// 3. Check whether the source is in canonical format.
match el_fmt::is_canonical(source) {
Ok(false) => {
diagnostics.push(LintDiagnostic {
severity: LintSeverity::Info,
code: "I001".into(),
message: "source is not in canonical format — run `el fmt` to fix".into(),
location: "file".into(),
suggestion: Some("el fmt --in-place <file.el>".into()),
});
}
_ => {}
}
let source_lines = source.lines().count();
Ok(LintReport {
diagnostics,
file_path: None,
source_lines,
})
}
}
impl Default for Linter {
fn default() -> Self {
Self::new()
}
}