diff options
author | Akshay <[email protected]> | 2021-10-29 13:50:54 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2021-10-29 14:14:14 +0100 |
commit | 1a97cce01f8e49b33bf28cbcdfeb3c8aefd809a5 (patch) | |
tree | 62613f193d84ea8b0c0aa94d09758fee19a6042d /bin | |
parent | d510714ed5a1eae0f6e5e435e4cff4875b06751d (diff) |
report syntax errors as statix errors
- statix now reports errors also, not just warnings
- all diagnostics are available on stderr stream
- non-utf8 files are skipped, does not eject early
Diffstat (limited to 'bin')
-rw-r--r-- | bin/src/config.rs | 9 | ||||
-rw-r--r-- | bin/src/err.rs | 22 | ||||
-rw-r--r-- | bin/src/lint.rs | 22 | ||||
-rw-r--r-- | bin/src/main.rs | 14 | ||||
-rw-r--r-- | bin/src/traits.rs | 18 |
5 files changed, 48 insertions, 37 deletions
diff --git a/bin/src/config.rs b/bin/src/config.rs index cbb1f66..ef3a29d 100644 --- a/bin/src/config.rs +++ b/bin/src/config.rs | |||
@@ -190,9 +190,12 @@ fn walk_with_ignores<P: AsRef<Path>>( | |||
190 | fn vfs(files: Vec<PathBuf>) -> Result<ReadOnlyVfs, ConfigErr> { | 190 | fn vfs(files: Vec<PathBuf>) -> Result<ReadOnlyVfs, ConfigErr> { |
191 | let mut vfs = ReadOnlyVfs::default(); | 191 | let mut vfs = ReadOnlyVfs::default(); |
192 | for file in files.iter() { | 192 | for file in files.iter() { |
193 | let _id = vfs.alloc_file_id(&file); | 193 | if let Ok(data) = fs::read_to_string(&file) { |
194 | let data = fs::read_to_string(&file).map_err(ConfigErr::InvalidPath)?; | 194 | let _id = vfs.alloc_file_id(&file); |
195 | vfs.set_file_contents(&file, data.as_bytes()); | 195 | vfs.set_file_contents(&file, data.as_bytes()); |
196 | } else { | ||
197 | println!("{} contains non-utf8 content", file.display()); | ||
198 | }; | ||
196 | } | 199 | } |
197 | Ok(vfs) | 200 | Ok(vfs) |
198 | } | 201 | } |
diff --git a/bin/src/err.rs b/bin/src/err.rs index 53c3222..4c16d69 100644 --- a/bin/src/err.rs +++ b/bin/src/err.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use std::{io, path::PathBuf}; | 1 | use std::io; |
2 | 2 | ||
3 | use globset::ErrorKind; | 3 | use globset::ErrorKind; |
4 | use rnix::parser::ParseError; | 4 | // use rnix::parser::ParseError; |
5 | use thiserror::Error; | 5 | use thiserror::Error; |
6 | 6 | ||
7 | #[derive(Error, Debug)] | 7 | #[derive(Error, Debug)] |
@@ -14,16 +14,16 @@ pub enum ConfigErr { | |||
14 | InvalidPosition(String), | 14 | InvalidPosition(String), |
15 | } | 15 | } |
16 | 16 | ||
17 | #[derive(Error, Debug)] | 17 | // #[derive(Error, Debug)] |
18 | pub enum LintErr { | 18 | // pub enum LintErr { |
19 | #[error("[{0}] syntax error: {1}")] | 19 | // #[error("[{0}] syntax error: {1}")] |
20 | Parse(PathBuf, ParseError), | 20 | // Parse(PathBuf, ParseError), |
21 | } | 21 | // } |
22 | 22 | ||
23 | #[derive(Error, Debug)] | 23 | #[derive(Error, Debug)] |
24 | pub enum FixErr { | 24 | pub enum FixErr { |
25 | #[error("[{0}] syntax error: {1}")] | 25 | // #[error("[{0}] syntax error: {1}")] |
26 | Parse(PathBuf, ParseError), | 26 | // Parse(PathBuf, ParseError), |
27 | #[error("path error: {0}")] | 27 | #[error("path error: {0}")] |
28 | InvalidPath(#[from] io::Error), | 28 | InvalidPath(#[from] io::Error), |
29 | } | 29 | } |
@@ -42,8 +42,8 @@ pub enum SingleFixErr { | |||
42 | 42 | ||
43 | #[derive(Error, Debug)] | 43 | #[derive(Error, Debug)] |
44 | pub enum StatixErr { | 44 | pub enum StatixErr { |
45 | #[error("linter error: {0}")] | 45 | // #[error("linter error: {0}")] |
46 | Lint(#[from] LintErr), | 46 | // Lint(#[from] LintErr), |
47 | #[error("fixer error: {0}")] | 47 | #[error("fixer error: {0}")] |
48 | Fix(#[from] FixErr), | 48 | Fix(#[from] FixErr), |
49 | #[error("single fix error: {0}")] | 49 | #[error("single fix error: {0}")] |
diff --git a/bin/src/lint.rs b/bin/src/lint.rs index 65ae824..e889d31 100644 --- a/bin/src/lint.rs +++ b/bin/src/lint.rs | |||
@@ -1,5 +1,3 @@ | |||
1 | use crate::err::LintErr; | ||
2 | |||
3 | use lib::{Report, LINTS}; | 1 | use lib::{Report, LINTS}; |
4 | use rnix::WalkEvent; | 2 | use rnix::WalkEvent; |
5 | use vfs::{FileId, VfsEntry}; | 3 | use vfs::{FileId, VfsEntry}; |
@@ -10,11 +8,16 @@ pub struct LintResult { | |||
10 | pub reports: Vec<Report>, | 8 | pub reports: Vec<Report>, |
11 | } | 9 | } |
12 | 10 | ||
13 | pub fn lint(vfs_entry: VfsEntry) -> Result<LintResult, LintErr> { | 11 | pub fn lint(vfs_entry: VfsEntry) -> LintResult { |
12 | let file_id = vfs_entry.file_id; | ||
14 | let source = vfs_entry.contents; | 13 | let source = vfs_entry.contents; |
15 | let parsed = rnix::parse(source) | 14 | let parsed = rnix::parse(source); |
16 | .as_result() | 15 | |
17 | .map_err(|e| LintErr::Parse(vfs_entry.file_path.to_path_buf(), e))?; | 16 | let error_reports = parsed |
17 | .errors() | ||
18 | .into_iter() | ||
19 | .map(|e| Report::from_parse_err(e)); | ||
20 | |||
18 | let reports = parsed | 21 | let reports = parsed |
19 | .node() | 22 | .node() |
20 | .preorder_with_tokens() | 23 | .preorder_with_tokens() |
@@ -28,9 +31,8 @@ pub fn lint(vfs_entry: VfsEntry) -> Result<LintResult, LintErr> { | |||
28 | _ => None, | 31 | _ => None, |
29 | }) | 32 | }) |
30 | .flatten() | 33 | .flatten() |
34 | .chain(error_reports) | ||
31 | .collect(); | 35 | .collect(); |
32 | Ok(LintResult { | 36 | |
33 | file_id: vfs_entry.file_id, | 37 | LintResult { file_id, reports } |
34 | reports, | ||
35 | }) | ||
36 | } | 38 | } |
diff --git a/bin/src/main.rs b/bin/src/main.rs index c5d0626..90b79ce 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs | |||
@@ -20,17 +20,9 @@ fn _main() -> Result<(), StatixErr> { | |||
20 | match opts.cmd { | 20 | match opts.cmd { |
21 | SubCommand::Check(check_config) => { | 21 | SubCommand::Check(check_config) => { |
22 | let vfs = check_config.vfs()?; | 22 | let vfs = check_config.vfs()?; |
23 | let (lints, errors): (Vec<_>, Vec<_>) = | 23 | let mut stderr = io::stderr(); |
24 | vfs.iter().map(lint::lint).partition(Result::is_ok); | 24 | vfs.iter().map(lint::lint).for_each(|r| { |
25 | let lint_results = lints.into_iter().map(Result::unwrap); | 25 | stderr.write(&r, &vfs, check_config.format).unwrap(); |
26 | let errors = errors.into_iter().map(Result::unwrap_err); | ||
27 | |||
28 | let mut stdout = io::stdout(); | ||
29 | lint_results.for_each(|r| { | ||
30 | stdout.write(&r, &vfs, check_config.format).unwrap(); | ||
31 | }); | ||
32 | errors.for_each(|e| { | ||
33 | eprintln!("{}", e); | ||
34 | }); | 26 | }); |
35 | } | 27 | } |
36 | SubCommand::Fix(fix_config) => { | 28 | SubCommand::Fix(fix_config) => { |
diff --git a/bin/src/traits.rs b/bin/src/traits.rs index 465abe4..a8ec70f 100644 --- a/bin/src/traits.rs +++ b/bin/src/traits.rs | |||
@@ -9,6 +9,7 @@ use ariadne::{ | |||
9 | CharSet, Color, Config as CliConfig, Fmt, Label, LabelAttach, Report as CliReport, | 9 | CharSet, Color, Config as CliConfig, Fmt, Label, LabelAttach, Report as CliReport, |
10 | ReportKind as CliReportKind, Source, | 10 | ReportKind as CliReportKind, Source, |
11 | }; | 11 | }; |
12 | use lib::Severity; | ||
12 | use rnix::{TextRange, TextSize}; | 13 | use rnix::{TextRange, TextSize}; |
13 | use vfs::ReadOnlyVfs; | 14 | use vfs::ReadOnlyVfs; |
14 | 15 | ||
@@ -57,11 +58,16 @@ fn write_stderr<T: Write>( | |||
57 | .map(|d| d.at.start().into()) | 58 | .map(|d| d.at.start().into()) |
58 | .min() | 59 | .min() |
59 | .unwrap_or(0usize); | 60 | .unwrap_or(0usize); |
61 | let report_kind = match report.severity { | ||
62 | Severity::Warn => CliReportKind::Warning, | ||
63 | Severity::Error => CliReportKind::Error, | ||
64 | Severity::Hint => CliReportKind::Advice, | ||
65 | }; | ||
60 | report | 66 | report |
61 | .diagnostics | 67 | .diagnostics |
62 | .iter() | 68 | .iter() |
63 | .fold( | 69 | .fold( |
64 | CliReport::build(CliReportKind::Warning, src_id, offset) | 70 | CliReport::build(report_kind, src_id, offset) |
65 | .with_config( | 71 | .with_config( |
66 | CliConfig::default() | 72 | CliConfig::default() |
67 | .with_cross_gap(true) | 73 | .with_cross_gap(true) |
@@ -103,7 +109,11 @@ fn write_errfmt<T: Write>( | |||
103 | filename = path.to_str().unwrap_or("<unknown>"), | 109 | filename = path.to_str().unwrap_or("<unknown>"), |
104 | linenumber = line, | 110 | linenumber = line, |
105 | columnnumber = col, | 111 | columnnumber = col, |
106 | errortype = "W", | 112 | errortype = match report.severity { |
113 | Severity::Warn => "W", | ||
114 | Severity::Error => "E", | ||
115 | Severity::Hint => "I", /* "info" message */ | ||
116 | }, | ||
107 | errornumber = report.code, | 117 | errornumber = report.code, |
108 | errormessage = diagnostic.message | 118 | errormessage = diagnostic.message |
109 | )?; | 119 | )?; |
@@ -118,6 +128,7 @@ mod json { | |||
118 | 128 | ||
119 | use std::io::{self, Write}; | 129 | use std::io::{self, Write}; |
120 | 130 | ||
131 | use lib::Severity; | ||
121 | use rnix::TextRange; | 132 | use rnix::TextRange; |
122 | use serde::Serialize; | 133 | use serde::Serialize; |
123 | use serde_json; | 134 | use serde_json; |
@@ -134,6 +145,7 @@ mod json { | |||
134 | struct JsonReport<'μ> { | 145 | struct JsonReport<'μ> { |
135 | note: &'static str, | 146 | note: &'static str, |
136 | code: u32, | 147 | code: u32, |
148 | severity: &'μ Severity, | ||
137 | diagnostics: Vec<JsonDiagnostic<'μ>>, | 149 | diagnostics: Vec<JsonDiagnostic<'μ>>, |
138 | } | 150 | } |
139 | 151 | ||
@@ -192,6 +204,7 @@ mod json { | |||
192 | .map(|r| { | 204 | .map(|r| { |
193 | let note = r.note; | 205 | let note = r.note; |
194 | let code = r.code; | 206 | let code = r.code; |
207 | let severity = &r.severity; | ||
195 | let diagnostics = r | 208 | let diagnostics = r |
196 | .diagnostics | 209 | .diagnostics |
197 | .iter() | 210 | .iter() |
@@ -207,6 +220,7 @@ mod json { | |||
207 | JsonReport { | 220 | JsonReport { |
208 | note, | 221 | note, |
209 | code, | 222 | code, |
223 | severity, | ||
210 | diagnostics, | 224 | diagnostics, |
211 | } | 225 | } |
212 | }) | 226 | }) |