diff options
Diffstat (limited to 'bin/src/traits.rs')
-rw-r--r-- | bin/src/traits.rs | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/bin/src/traits.rs b/bin/src/traits.rs new file mode 100644 index 0000000..1807ad0 --- /dev/null +++ b/bin/src/traits.rs | |||
@@ -0,0 +1,83 @@ | |||
1 | use std::{ | ||
2 | io::{self, Write}, | ||
3 | str, | ||
4 | }; | ||
5 | |||
6 | use ariadne::{ | ||
7 | CharSet, Color, Config as CliConfig, Label, LabelAttach, Report as CliReport, | ||
8 | ReportKind as CliReportKind, Source, Fmt | ||
9 | }; | ||
10 | use lib::Report; | ||
11 | use rnix::TextRange; | ||
12 | use vfs::{FileId, ReadOnlyVfs}; | ||
13 | |||
14 | #[derive(Debug)] | ||
15 | pub struct LintResult { | ||
16 | pub file_id: FileId, | ||
17 | pub reports: Vec<Report>, | ||
18 | } | ||
19 | |||
20 | pub trait WriteDiagnostic { | ||
21 | fn write(&mut self, report: &LintResult, vfs: &ReadOnlyVfs) -> io::Result<()>; | ||
22 | } | ||
23 | |||
24 | impl<T> WriteDiagnostic for T | ||
25 | where | ||
26 | T: Write, | ||
27 | { | ||
28 | fn write(&mut self, lint_result: &LintResult, vfs: &ReadOnlyVfs) -> io::Result<()> { | ||
29 | let file_id = lint_result.file_id; | ||
30 | let src = str::from_utf8(vfs.get(file_id)).unwrap(); | ||
31 | let path = vfs.file_path(file_id); | ||
32 | let range = |at: TextRange| at.start().into()..at.end().into(); | ||
33 | let src_id = path.to_str().unwrap_or("<unknown>"); | ||
34 | for report in lint_result.reports.iter() { | ||
35 | let offset = report | ||
36 | .diagnostics | ||
37 | .iter() | ||
38 | .map(|d| d.at.start().into()) | ||
39 | .min() | ||
40 | .unwrap_or(0usize); | ||
41 | report | ||
42 | .diagnostics | ||
43 | .iter() | ||
44 | .fold( | ||
45 | CliReport::build(CliReportKind::Warning, src_id, offset) | ||
46 | .with_config( | ||
47 | CliConfig::default() | ||
48 | .with_cross_gap(true) | ||
49 | .with_multiline_arrows(false) | ||
50 | .with_label_attach(LabelAttach::Middle) | ||
51 | .with_char_set(CharSet::Unicode), | ||
52 | ) | ||
53 | .with_message(report.note) | ||
54 | .with_code(report.code), | ||
55 | |cli_report, diagnostic| { | ||
56 | cli_report.with_label( | ||
57 | Label::new((src_id, range(diagnostic.at))) | ||
58 | .with_message(&colorize(&diagnostic.message)) | ||
59 | .with_color(Color::Magenta), | ||
60 | ) | ||
61 | }, | ||
62 | ) | ||
63 | .finish() | ||
64 | .write((src_id, Source::from(src)), &mut *self)?; | ||
65 | } | ||
66 | Ok(()) | ||
67 | } | ||
68 | } | ||
69 | |||
70 | // everything within backticks is colorized, backticks are removed | ||
71 | fn colorize(message: &str) -> String { | ||
72 | message.split('`') | ||
73 | .enumerate() | ||
74 | .map(|(idx, part)| { | ||
75 | if idx % 2 == 1 { | ||
76 | part.fg(Color::Cyan).to_string() | ||
77 | } else { | ||
78 | part.to_string() | ||
79 | } | ||
80 | }) | ||
81 | .collect::<Vec<_>>() | ||
82 | .join("") | ||
83 | } | ||