1use crate::diagnostic::{Diagnostic, DiagnosticSeverity};
2use serde::Serialize;
3
4pub trait AnniLinter<T> {
5 fn add(&mut self, msg: Diagnostic<T>);
6 fn flush(&self) -> bool;
7}
8
9#[derive(Default)]
10pub struct AnniLinterReviewDogJsonLineFormat(bool);
11
12impl AnniLinterReviewDogJsonLineFormat {
13 pub fn new() -> Self {
14 AnniLinterReviewDogJsonLineFormat(false)
15 }
16}
17
18impl<T: Serialize> AnniLinter<T> for AnniLinterReviewDogJsonLineFormat {
19 fn add(&mut self, msg: Diagnostic<T>) {
20 if let DiagnosticSeverity::Error = msg.severity {
21 self.0 = true;
22 }
23 println!("{}", serde_json::to_string(&msg).unwrap());
24 }
25
26 fn flush(&self) -> bool {
27 !self.0
28 }
29}
30
31pub struct AnniLinterTextFormat<T> {
32 errors: Vec<Diagnostic<T>>,
33 warnings: Vec<Diagnostic<T>>,
34}
35
36impl<T> Default for AnniLinterTextFormat<T> {
37 fn default() -> Self {
38 Self {
39 errors: Vec::new(),
40 warnings: Vec::new(),
41 }
42 }
43}
44
45impl<T> AnniLinter<T> for AnniLinterTextFormat<T> {
46 fn add(&mut self, msg: Diagnostic<T>) {
47 match msg.severity {
48 DiagnosticSeverity::Error => self.errors.push(msg),
49 DiagnosticSeverity::Warning => self.warnings.push(msg),
50 _ => {}
51 }
52 }
53
54 fn flush(&self) -> bool {
55 println!(
56 "{} errors, {} warnings",
57 self.errors.len(),
58 self.warnings.len()
59 );
60 println!();
61 for error in self.errors.iter() {
62 println!(
63 "[ERROR][{}] {}:{}: {}",
64 error.location.path,
65 error.location.start_line(),
66 error.location.start_column().unwrap_or(0),
67 error.message.message
68 );
69 }
70 println!();
71 for warn in self.warnings.iter() {
72 println!(
73 "[WARN][{}] {}:{}: {}",
74 warn.location.path,
75 warn.location.start_line(),
76 warn.location.start_column().unwrap_or(0),
77 warn.message.message
78 );
79 }
80
81 self.errors.is_empty()
82 }
83}