gitql_cli/
diagnostic_reporter.rs

1use gitql_parser::diagnostic::Diagnostic;
2
3use termcolor::Color;
4
5use crate::colored_stream::ColoredStream;
6
7#[derive(Default)]
8pub struct DiagnosticReporter {
9    stdout: ColoredStream,
10}
11
12impl DiagnosticReporter {
13    pub fn report_diagnostic(&mut self, query: &str, diagnostic: Diagnostic) {
14        self.stdout.set_color(Some(Color::Red));
15        println!("[{}]: {}", diagnostic.label(), diagnostic.message());
16
17        if let Some(location) = diagnostic.location() {
18            println!(
19                "  --> Location {}:{}",
20                location.line_start, location.column_start
21            );
22        }
23
24        if !query.is_empty() {
25            println!("   |");
26            if let Some(location) = diagnostic.location() {
27                let lines: Vec<&str> = query.split('\n').collect();
28                let end = u32::min(location.line_end, lines.len() as u32);
29                for zero_based_line_number in location.line_start - 1..end {
30                    println!("-> | {}", lines[zero_based_line_number as usize]);
31                }
32
33                println!("   | ");
34                let column_s = location.column_start.saturating_sub(1) as usize;
35                print!("   | {}", &"-".repeat(column_s));
36
37                let diagnostic_length =
38                    u32::max(1, location.column_end.saturating_sub(location.column_start)) as usize;
39
40                self.stdout.set_color(Some(Color::Yellow));
41                println!("{}", &"^".repeat(diagnostic_length));
42
43                self.stdout.set_color(Some(Color::Red));
44            }
45            println!("   |");
46        }
47
48        self.stdout.set_color(Some(Color::Cyan));
49        for help in diagnostic.helps() {
50            println!(" = Help: {help}");
51        }
52
53        self.stdout.set_color(Some(Color::Yellow));
54        for note in diagnostic.notes() {
55            println!(" = Note: {note}");
56        }
57
58        self.stdout.set_color(Some(Color::Blue));
59        if let Some(docs) = diagnostic.docs() {
60            println!(" = Docs: {docs}");
61        }
62
63        self.stdout.reset();
64    }
65}