sqruff_lib/cli/
github_annotation_native_formatter.rs1use crate::core::config::FluffConfig;
2use crate::core::linter::linted_file::LintedFile;
3use std::io::{Stderr, Write};
4use std::sync::atomic::{AtomicBool, Ordering};
5
6use super::formatters::Formatter;
7
8#[derive(Debug)]
9pub struct GithubAnnotationNativeFormatter {
10 output_stream: Stderr,
11 pub has_fail: AtomicBool,
12}
13
14impl GithubAnnotationNativeFormatter {
15 pub fn new(stderr: Stderr) -> Self {
16 Self {
17 output_stream: stderr,
18 has_fail: AtomicBool::new(false),
19 }
20 }
21
22 fn dispatch(&self, s: &str) {
23 let mut output_stream = self.output_stream.lock();
24 output_stream
25 .write_all(s.as_bytes())
26 .and_then(|_| output_stream.flush())
27 .unwrap_or_else(|e| panic!("failed to emit error: {e}"));
28 }
29}
30
31impl Formatter for GithubAnnotationNativeFormatter {
32 fn dispatch_template_header(
33 &self,
34 _f_name: String,
35 _linter_config: FluffConfig,
36 _file_config: FluffConfig,
37 ) {
38 }
40
41 fn dispatch_parse_header(&self, _f_name: String) {
42 }
44
45 fn dispatch_file_violations(&self, linted_file: &LintedFile, _only_fixable: bool) {
46 let mut violations = linted_file.get_violations(None);
47
48 violations.sort_by(|a, b| {
49 a.line_no
50 .cmp(&b.line_no)
51 .then_with(|| a.line_pos.cmp(&b.line_pos))
52 .then_with(|| {
53 let b = b.rule.as_ref().unwrap().code;
54 a.rule.as_ref().unwrap().code.cmp(b)
55 })
56 });
57
58 for violation in violations {
59 let message = format!(
60 "::error title=sqruff,file={},line={},col={}::{}: {}\n",
61 linted_file.path,
62 violation.line_no,
63 violation.line_pos,
64 violation.rule.as_ref().unwrap().code,
65 violation.description
66 );
67
68 self.dispatch(&message);
69 self.has_fail.store(true, Ordering::SeqCst);
70 }
71 }
72
73 fn completion_message(&self) {
74 }
76}