From 214e3bc4b675b08ce4df76b1373f4548949e67ee Mon Sep 17 00:00:00 2001 From: Akshay Date: Tue, 19 Oct 2021 15:58:46 +0530 Subject: fully flesh out CLI --- bin/src/main.rs | 112 +++++++++++++++++++++++--------------------------------- 1 file changed, 46 insertions(+), 66 deletions(-) (limited to 'bin/src/main.rs') 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 @@ -use std::{ - env, fs, - path::{Path, PathBuf}, -}; +#![feature(path_try_exists)] + +mod config; +mod err; +mod traits; -use anyhow::{Context, Result}; -use ariadne::{ - CharSet, Color, Config as CliConfig, Label, LabelAttach, Report as CliReport, - ReportKind as CliReportKind, Source, +use std::io; + +use crate::{ + err::{LintErr, StatixErr}, + traits::{LintResult, WriteDiagnostic}, }; -use lib::{Report, LINTS}; -use rnix::{TextRange, WalkEvent}; -fn analyze(source: &str) -> Result> { - let parsed = rnix::parse(source).as_result()?; +use clap::Clap; +use config::{LintConfig, Opts, SubCommand}; +use lib::LINTS; +use rnix::WalkEvent; +use vfs::VfsEntry; - Ok(parsed +fn analyze<'ρ>(vfs_entry: VfsEntry<'ρ>) -> Result { + let source = vfs_entry.contents; + let parsed = rnix::parse(source) + .as_result() + .map_err(|e| LintErr::Parse(vfs_entry.file_path.to_path_buf(), e))?; + let reports = parsed .node() .preorder_with_tokens() .filter_map(|event| match event { @@ -27,61 +35,33 @@ fn analyze(source: &str) -> Result> { _ => None, }) .flatten() - .collect()) + .collect(); + Ok(LintResult { + file_id: vfs_entry.file_id, + reports, + }) } -fn print_report(report: Report, file_src: &str, file_path: &Path) -> Result<()> { - let range = |at: TextRange| at.start().into()..at.end().into(); - let src_id = file_path.to_str().unwrap_or(""); - let offset = report - .diagnostics - .iter() - .map(|d| d.at.start().into()) - .min() - .unwrap_or(0usize); - report - .diagnostics - .iter() - .fold( - CliReport::build(CliReportKind::Warning, src_id, offset) - .with_config( - CliConfig::default() - .with_cross_gap(true) - .with_multiline_arrows(false) - .with_label_attach(LabelAttach::Middle) - .with_char_set(CharSet::Unicode), - ) - .with_message(report.note) - .with_code(report.code), - |cli_report, diagnostic| { - cli_report.with_label( - Label::new((src_id, range(diagnostic.at))) - .with_message(&diagnostic.message) - .with_color(Color::Magenta), - ) - }, - ) - .finish() - .eprint((src_id, Source::from(file_src))) - .context("failed to print report to stdout") -} - -fn _main() -> Result<()> { +fn _main() -> Result<(), StatixErr> { // TODO: accept cli args, construct a CLI config with a list of files to analyze - let args = env::args(); - for (file_src, file_path, reports) in args - .skip(1) - .map(|s| PathBuf::from(&s)) - .filter(|p| p.is_file()) - .filter_map(|path| { - let s = fs::read_to_string(&path).ok()?; - analyze(&s) - .map(|analysis_result| (s, path, analysis_result)) - .ok() - }) - { - for r in reports { - print_report(r, &file_src, &file_path)? + let opts = Opts::parse(); + match opts.subcmd { + Some(SubCommand::Fix(_)) => {} + None => { + let lint_config = LintConfig::from_opts(opts)?; + let vfs = lint_config.vfs()?; + let (reports, errors): (Vec<_>, Vec<_>) = + vfs.iter().map(analyze).partition(Result::is_ok); + let lint_results: Vec<_> = reports.into_iter().map(Result::unwrap).collect(); + let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect(); + + let mut stderr = io::stderr(); + lint_results.into_iter().for_each(|r| { + stderr.write(&r, &vfs).unwrap(); + }); + errors.into_iter().for_each(|e| { + eprintln!("{}", e); + }); } } Ok(()) @@ -90,6 +70,6 @@ fn _main() -> Result<()> { fn main() { match _main() { Err(e) => eprintln!("{}", e), - _ => {} + _ => (), } } -- cgit v1.2.3