pub mod analysis;
pub mod config;
pub mod diagnostic;
pub mod fix;
pub mod output;
pub mod project;
pub mod rules;
pub mod scanner;
use std::path::{Path, PathBuf};
use anyhow::Result;
use serde::Serialize;
pub use config::{Config, SeveritySetting};
pub use diagnostic::{Diagnostic, Severity, Span};
pub use rules::{RuleCategory, RuleDefinition};
#[derive(Debug, Clone, Default)]
pub struct LintOptions {
pub config_path: Option<PathBuf>,
pub extra_ignores: Vec<String>,
pub minimum_severity: Option<Severity>,
}
#[derive(Debug, Clone, Serialize)]
pub struct LintReport {
pub version: &'static str,
pub root: PathBuf,
pub files_scanned: usize,
pub estimated_total_tokens: usize,
pub estimated_duplicated_tokens: usize,
pub diagnostics: Vec<Diagnostic>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub fixed_files: Vec<PathBuf>,
}
impl LintReport {
pub fn error_count(&self) -> usize {
self.diagnostics
.iter()
.filter(|item| item.severity == Severity::Error)
.count()
}
pub fn warning_count(&self) -> usize {
self.diagnostics
.iter()
.filter(|item| item.severity == Severity::Warning)
.count()
}
}
pub fn lint(root: &Path, options: &LintOptions) -> Result<LintReport> {
let root = root.canonicalize()?;
let config = Config::load(&root, options.config_path.as_deref())?;
let project = project::ProjectFacts::inspect(&root)?;
let files = scanner::scan(&root, &config, &options.extra_ignores)?;
Ok(analysis::analyze(
&root,
&files,
&project,
&config,
options.minimum_severity,
))
}