refactor(xatu): return structured reports

This commit was merged in pull request #73.
This commit is contained in:
2026-09-18 22:43:17 -04:00
parent 113018a62c
commit 1fa3962fed
4 changed files with 54 additions and 13 deletions

View File

@@ -16,6 +16,12 @@ pub struct SourceRange {
pub end: usize, pub end: usize,
} }
impl std::fmt::Display for SourceRange {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(formatter, "{}..{}", self.start, self.end)
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Node { pub struct Node {
pub range: SourceRange, pub range: SourceRange,

View File

@@ -4,17 +4,29 @@ use crate::rules::empty_inherit::EmptyInherit;
pub mod empty_inherit; pub mod empty_inherit;
#[derive(Debug)]
pub struct Finding { pub struct Finding {
pub rule_id: &'static str, pub rule_id: &'static str,
pub range: ast::SourceRange, pub range: ast::SourceRange,
pub message: &'static str, pub message: &'static str,
} }
#[derive(Debug)]
pub struct Diagnostic { pub struct Diagnostic {
pub file_id: FileId, pub file_id: FileId,
pub finding: Finding, pub finding: Finding,
} }
impl std::fmt::Display for Diagnostic {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
formatter,
"{}: {}: {}",
self.finding.range, self.finding.rule_id, self.finding.message,
)
}
}
pub trait NodeRule { pub trait NodeRule {
type Node; type Node;

View File

@@ -4,9 +4,35 @@ mod parser;
mod rules; mod rules;
pub use file_store::{FileId, FileStore, SourceFile}; pub use file_store::{FileId, FileStore, SourceFile};
pub use rules::{Diagnostic, Finding};
pub fn run(files: Vec<SourceFile>) -> status::Result<()> { #[derive(Debug)]
pub struct Report {
pub files: FileStore,
pub diagnostics: Vec<Diagnostic>,
}
impl Report {
pub fn is_clean(&self) -> bool {
self.diagnostics.is_empty()
}
}
impl std::fmt::Display for Report {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for diagnostic in &self.diagnostics {
let file = self.files.get(diagnostic.file_id);
writeln!(formatter, "{}:{diagnostic}", file.path.display())?;
}
Ok(())
}
}
/// Analyzes source files and returns the diagnostics Xatu finds.
pub fn future_sight(files: Vec<SourceFile>) -> status::Result<Report> {
let mut store = FileStore::default(); let mut store = FileStore::default();
let mut diagnostics = Vec::new();
for file in files { for file in files {
let file_id = store.add(file); let file_id = store.add(file);
@@ -20,17 +46,11 @@ pub fn run(files: Vec<SourceFile>) -> status::Result<()> {
))); )));
} }
for diagnostic in rules::run_rules(&parsed) { diagnostics.extend(rules::run_rules(&parsed));
println!(
"{}:{}..{}: {}: {}",
file.path.display(),
diagnostic.finding.range.start,
diagnostic.finding.range.end,
diagnostic.finding.rule_id,
diagnostic.finding.message,
);
}
} }
Ok(()) Ok(Report {
files: store,
diagnostics,
})
} }

View File

@@ -82,5 +82,8 @@ fn main() -> status::Result<()> {
.flatten() .flatten()
.collect(); .collect();
xatu::run(files) let report = xatu::future_sight(files)?;
print!("{report}");
Ok(())
} }