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();