From c91c2ae1398e4f567ee5e4c50a1da35a9b65919b Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 15 Sep 2021 16:19:58 +0530 Subject: init cli entrypoint --- bin/Cargo.toml | 4 +++ bin/src/main.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/bin/Cargo.toml b/bin/Cargo.toml index 57cff11..979bd46 100644 --- a/bin/Cargo.toml +++ b/bin/Cargo.toml @@ -6,3 +6,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lib = { path = "../lib" } +ariadne = "0.1.3" +anyhow = "1.0" +rnix = "0.9.0" diff --git a/bin/src/main.rs b/bin/src/main.rs index e7a11a9..ae45bfe 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -1,3 +1,82 @@ +use std::{ + env, fs, + path::{Path, PathBuf}, +}; + +use anyhow::{Context, Result}; +use ariadne::{Color, Fmt, Label, Report as CliReport, ReportKind as CliReportKind, Source}; +use lib::{Report, LINTS}; +use rnix::WalkEvent; + +fn analyze(file: &str) -> Result> { + let parsed = rnix::parse(file).as_result()?; + + Ok(parsed + .node() + .preorder_with_tokens() + .filter_map(|event| match event { + WalkEvent::Enter(child) => LINTS.get(&child.kind()).map(|rules| { + rules + .iter() + .filter_map(|rule| rule.validate(&child)) + .collect::>() + }), + _ => None, + }) + .flatten() + .collect()) +} + +fn print_report(report: Report, file_src: &str, file_path: &Path) -> Result<()> { + 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), + |cli_report, diagnostic| { + let range = { + let at = diagnostic.at; + at.start().into()..at.end().into() + }; + cli_report.with_label( + Label::new((src_id, range)) + .with_message(diagnostic.message.as_str().fg(Color::Yellow)), + ) + }, + ) + .finish() + .print((src_id, Source::from(file_src))) + .context("failed to print report to stdout") +} + +fn _main() -> Result<()> { + let args = env::args(); + for (file_src, file_path, reports) in args + .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)? + } + } + Ok(()) +} fn main() { - println!("Hello, world!"); + match _main() { + Err(e) => eprintln!("{}", e), + _ => {} + } } -- cgit v1.2.3