From a295bed5c0849d2659a014d1258b3246c523195f Mon Sep 17 00:00:00 2001 From: alexion Date: Sat, 26 Sep 2026 19:59:42 -0400 Subject: [PATCH] feat(xatu): report diagnostic line ranges --- src/xatu/rules.rs | 4 ++-- src/xatu/xatu.rs | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/xatu/rules.rs b/src/xatu/rules.rs index f84b1e4..589f580 100644 --- a/src/xatu/rules.rs +++ b/src/xatu/rules.rs @@ -27,8 +27,8 @@ 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, + "{}: {}", + self.finding.rule_id, self.finding.message ) } } diff --git a/src/xatu/xatu.rs b/src/xatu/xatu.rs index c8cb67a..79f7e85 100644 --- a/src/xatu/xatu.rs +++ b/src/xatu/xatu.rs @@ -25,13 +25,33 @@ 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())?; + let (start, end) = line_range(&file.source, diagnostic.finding.range); + writeln!( + formatter, + "{}:{start}..{end}:{diagnostic}", + file.path.display() + )?; } Ok(()) } } +fn line_range(source: &str, range: ast::SourceRange) -> (usize, usize) { + let line_at = |offset| { + source + .bytes() + .take(offset) + .filter(|byte| *byte == b'\n') + .count() + + 1 + }; + let start = line_at(range.start); + let end = line_at(range.end); + + (start, end) +} + /// Analyzes source files and returns the diagnostics Xatu finds. pub fn future_sight(files: Vec) -> status::Result { let mut store = FileStore::default();