wave_compiler/diagnostics/
report.rs1use std::fmt::Write;
10
11use super::error::{CompileError, SourceLoc};
12use super::source_map::SourceMap;
13
14#[must_use]
16pub fn format_error(
17 error: &CompileError,
18 source_map: Option<&SourceMap>,
19 loc: Option<SourceLoc>,
20) -> String {
21 let mut out = String::new();
22
23 if let Some(loc) = loc {
24 let _ = write!(out, "error at {}:{}: ", loc.line, loc.col);
25 } else {
26 out.push_str("error: ");
27 }
28
29 out.push_str(&error.to_string());
30 out.push('\n');
31
32 if let (Some(map), Some(loc)) = (source_map, loc) {
33 if let Some(line) = map.get_line(loc.line) {
34 let _ = writeln!(out, " {} | {}", loc.line, line);
35 let padding = format!("{}", loc.line).len() + 3 + (loc.col as usize - 1);
36 let _ = writeln!(out, "{}^", " ".repeat(padding));
37 }
38 }
39
40 out
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_format_error_with_location() {
49 let err = CompileError::UndefinedVariable { name: "x".into() };
50 let src = "let y = x + 1".to_string();
51 let map = SourceMap::new(src);
52 let loc = SourceLoc { line: 1, col: 9 };
53 let output = format_error(&err, Some(&map), Some(loc));
54 assert!(output.contains("error at 1:9"));
55 assert!(output.contains("undefined variable: x"));
56 assert!(output.contains("let y = x + 1"));
57 }
58
59 #[test]
60 fn test_format_error_without_location() {
61 let err = CompileError::InternalError {
62 message: "something went wrong".into(),
63 };
64 let output = format_error(&err, None, None);
65 assert!(output.contains("error: internal error"));
66 assert!(output.contains("something went wrong"));
67 }
68}