Lints and suggestions for the Nix programming language
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor out lint runner into lint module

Akshay e4c4a77d 33044d3f

+49 -48
+36
bin/src/lint.rs
··· 1 + use crate::err::LintErr; 2 + 3 + use lib::{LINTS, Report}; 4 + use rnix::WalkEvent; 5 + use vfs::{VfsEntry, FileId}; 6 + 7 + #[derive(Debug)] 8 + pub struct LintResult { 9 + pub file_id: FileId, 10 + pub reports: Vec<Report>, 11 + } 12 + 13 + pub fn lint(vfs_entry: VfsEntry) -> Result<LintResult, LintErr> { 14 + let source = vfs_entry.contents; 15 + let parsed = rnix::parse(source) 16 + .as_result() 17 + .map_err(|e| LintErr::Parse(vfs_entry.file_path.to_path_buf(), e))?; 18 + let reports = parsed 19 + .node() 20 + .preorder_with_tokens() 21 + .filter_map(|event| match event { 22 + WalkEvent::Enter(child) => LINTS.get(&child.kind()).map(|rules| { 23 + rules 24 + .iter() 25 + .filter_map(|rule| rule.validate(&child)) 26 + .collect::<Vec<_>>() 27 + }), 28 + _ => None, 29 + }) 30 + .flatten() 31 + .collect(); 32 + Ok(LintResult { 33 + file_id: vfs_entry.file_id, 34 + reports, 35 + }) 36 + }
+6 -37
bin/src/main.rs
··· 1 - #![feature(path_try_exists)] 2 - 3 1 mod config; 4 2 mod err; 3 + mod lint; 5 4 mod traits; 6 5 7 6 use std::io; 8 7 9 - use crate::{ 10 - err::{LintErr, StatixErr}, 11 - traits::{LintResult, WriteDiagnostic}, 12 - }; 8 + use crate::{err::StatixErr, traits::WriteDiagnostic}; 13 9 14 10 use clap::Clap; 15 11 use config::{LintConfig, Opts, SubCommand}; 16 - use lib::LINTS; 17 - use rnix::WalkEvent; 18 - use vfs::VfsEntry; 19 - 20 - fn 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 26 - .node() 27 - .preorder_with_tokens() 28 - .filter_map(|event| match event { 29 - WalkEvent::Enter(child) => LINTS.get(&child.kind()).map(|rules| { 30 - rules 31 - .iter() 32 - .filter_map(|rule| rule.validate(&child)) 33 - .collect::<Vec<_>>() 34 - }), 35 - _ => None, 36 - }) 37 - .flatten() 38 - .collect(); 39 - Ok(LintResult { 40 - file_id: vfs_entry.file_id, 41 - reports, 42 - }) 43 - } 44 12 45 13 fn _main() -> Result<(), StatixErr> { 46 - // TODO: accept cli args, construct a CLI config with a list of files to analyze 47 14 let opts = Opts::parse(); 48 15 match opts.subcmd { 49 - Some(SubCommand::Fix(_)) => {} 16 + Some(SubCommand::Fix(_)) => { 17 + eprintln!("`fix` not yet supported"); 18 + } 50 19 None => { 51 20 let lint_config = LintConfig::from_opts(opts)?; 52 21 let vfs = lint_config.vfs()?; 53 22 let (reports, errors): (Vec<_>, Vec<_>) = 54 - vfs.iter().map(analyze).partition(Result::is_ok); 23 + vfs.iter().map(lint::lint).partition(Result::is_ok); 55 24 let lint_results: Vec<_> = reports.into_iter().map(Result::unwrap).collect(); 56 25 let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect(); 57 26
+7 -11
bin/src/traits.rs
··· 3 3 str, 4 4 }; 5 5 6 + use crate::lint::LintResult; 7 + 6 8 use ariadne::{ 7 - CharSet, Color, Config as CliConfig, Label, LabelAttach, Report as CliReport, 8 - ReportKind as CliReportKind, Source, Fmt 9 + CharSet, Color, Config as CliConfig, Fmt, Label, LabelAttach, Report as CliReport, 10 + ReportKind as CliReportKind, Source, 9 11 }; 10 - use lib::Report; 11 12 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 - } 13 + use vfs::ReadOnlyVfs; 19 14 20 15 pub trait WriteDiagnostic { 21 16 fn write(&mut self, report: &LintResult, vfs: &ReadOnlyVfs) -> io::Result<()>; ··· 69 64 70 65 // everything within backticks is colorized, backticks are removed 71 66 fn colorize(message: &str) -> String { 72 - message.split('`') 67 + message 68 + .split('`') 73 69 .enumerate() 74 70 .map(|(idx, part)| { 75 71 if idx % 2 == 1 {