aboutsummaryrefslogtreecommitdiff
path: root/bin/src/main.rs
diff options
context:
space:
mode:
authorAkshay <[email protected]>2021-10-19 11:28:46 +0100
committerAkshay <[email protected]>2021-10-19 11:28:46 +0100
commit214e3bc4b675b08ce4df76b1373f4548949e67ee (patch)
treedb6584a360d69bc9759e2b8059a013ba9e8db5e1 /bin/src/main.rs
parent0076b3a37dcca0e11afd05dc98174f646cdb8fa9 (diff)
fully flesh out CLI
Diffstat (limited to 'bin/src/main.rs')
-rw-r--r--bin/src/main.rs112
1 files changed, 46 insertions, 66 deletions
diff --git a/bin/src/main.rs b/bin/src/main.rs
index ab99aee..b26151d 100644
--- a/bin/src/main.rs
+++ b/bin/src/main.rs
@@ -1,20 +1,28 @@
1use std::{ 1#![feature(path_try_exists)]
2 env, fs, 2
3 path::{Path, PathBuf}, 3mod config;
4}; 4mod err;
5mod traits;
5 6
6use anyhow::{Context, Result}; 7use std::io;
7use ariadne::{ 8
8 CharSet, Color, Config as CliConfig, Label, LabelAttach, Report as CliReport, 9use crate::{
9 ReportKind as CliReportKind, Source, 10 err::{LintErr, StatixErr},
11 traits::{LintResult, WriteDiagnostic},
10}; 12};
11use lib::{Report, LINTS};
12use rnix::{TextRange, WalkEvent};
13 13
14fn analyze(source: &str) -> Result<Vec<Report>> { 14use clap::Clap;
15 let parsed = rnix::parse(source).as_result()?; 15use config::{LintConfig, Opts, SubCommand};
16use lib::LINTS;
17use rnix::WalkEvent;
18use vfs::VfsEntry;
16 19
17 Ok(parsed 20fn analyze<'ρ>(vfs_entry: VfsEntry<'ρ>) -> Result<LintResult, LintErr> {
21 let source = vfs_entry.contents;
22 let parsed = rnix::parse(source)
23 .as_result()
24 .map_err(|e| LintErr::Parse(vfs_entry.file_path.to_path_buf(), e))?;
25 let reports = parsed
18 .node() 26 .node()
19 .preorder_with_tokens() 27 .preorder_with_tokens()
20 .filter_map(|event| match event { 28 .filter_map(|event| match event {
@@ -27,61 +35,33 @@ fn analyze(source: &str) -> Result<Vec<Report>> {
27 _ => None, 35 _ => None,
28 }) 36 })
29 .flatten() 37 .flatten()
30 .collect()) 38 .collect();
39 Ok(LintResult {
40 file_id: vfs_entry.file_id,
41 reports,
42 })
31} 43}
32 44
33fn print_report(report: Report, file_src: &str, file_path: &Path) -> Result<()> { 45fn _main() -> Result<(), StatixErr> {
34 let range = |at: TextRange| at.start().into()..at.end().into();
35 let src_id = file_path.to_str().unwrap_or("<unknown>");
36 let offset = report
37 .diagnostics
38 .iter()
39 .map(|d| d.at.start().into())
40 .min()
41 .unwrap_or(0usize);
42 report
43 .diagnostics
44 .iter()
45 .fold(
46 CliReport::build(CliReportKind::Warning, src_id, offset)
47 .with_config(
48 CliConfig::default()
49 .with_cross_gap(true)
50 .with_multiline_arrows(false)
51 .with_label_attach(LabelAttach::Middle)
52 .with_char_set(CharSet::Unicode),
53 )
54 .with_message(report.note)
55 .with_code(report.code),
56 |cli_report, diagnostic| {
57 cli_report.with_label(
58 Label::new((src_id, range(diagnostic.at)))
59 .with_message(&diagnostic.message)
60 .with_color(Color::Magenta),
61 )
62 },
63 )
64 .finish()
65 .eprint((src_id, Source::from(file_src)))
66 .context("failed to print report to stdout")
67}
68
69fn _main() -> Result<()> {
70 // TODO: accept cli args, construct a CLI config with a list of files to analyze 46 // TODO: accept cli args, construct a CLI config with a list of files to analyze
71 let args = env::args(); 47 let opts = Opts::parse();
72 for (file_src, file_path, reports) in args 48 match opts.subcmd {
73 .skip(1) 49 Some(SubCommand::Fix(_)) => {}
74 .map(|s| PathBuf::from(&s)) 50 None => {
75 .filter(|p| p.is_file()) 51 let lint_config = LintConfig::from_opts(opts)?;
76 .filter_map(|path| { 52 let vfs = lint_config.vfs()?;
77 let s = fs::read_to_string(&path).ok()?; 53 let (reports, errors): (Vec<_>, Vec<_>) =
78 analyze(&s) 54 vfs.iter().map(analyze).partition(Result::is_ok);
79 .map(|analysis_result| (s, path, analysis_result)) 55 let lint_results: Vec<_> = reports.into_iter().map(Result::unwrap).collect();
80 .ok() 56 let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
81 }) 57
82 { 58 let mut stderr = io::stderr();
83 for r in reports { 59 lint_results.into_iter().for_each(|r| {
84 print_report(r, &file_src, &file_path)? 60 stderr.write(&r, &vfs).unwrap();
61 });
62 errors.into_iter().for_each(|e| {
63 eprintln!("{}", e);
64 });
85 } 65 }
86 } 66 }
87 Ok(()) 67 Ok(())
@@ -90,6 +70,6 @@ fn _main() -> Result<()> {
90fn main() { 70fn main() {
91 match _main() { 71 match _main() {
92 Err(e) => eprintln!("{}", e), 72 Err(e) => eprintln!("{}", e),
93 _ => {} 73 _ => (),
94 } 74 }
95} 75}