From d1ff222bcf94152cd657233cffd8c14a45788c26 Mon Sep 17 00:00:00 2001 From: Akshay Date: Wed, 29 Dec 2021 10:53:38 +0530 Subject: allow for version based lints --- bin/src/fix.rs | 30 +++++++++++++++++++++++++++--- bin/src/fix/all.rs | 21 +++++++++++++++------ bin/src/fix/single.rs | 15 ++++++++++----- bin/src/lib.rs | 1 + bin/src/lint.rs | 23 ++++++++++++++++------- bin/src/session.rs | 0 bin/src/utils.rs | 11 +++++++++++ 7 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 bin/src/session.rs (limited to 'bin/src') diff --git a/bin/src/fix.rs b/bin/src/fix.rs index a035379..4b2ce0c 100644 --- a/bin/src/fix.rs +++ b/bin/src/fix.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use crate::LintMap; +use lib::session::SessionInfo; use rnix::TextRange; mod all; @@ -16,6 +17,7 @@ pub struct FixResult<'a> { pub src: Source<'a>, pub fixed: Vec, pub lints: &'a LintMap, + pub sess: &'a SessionInfo, } #[derive(Debug, Clone)] @@ -25,11 +27,12 @@ pub struct Fixed { } impl<'a> FixResult<'a> { - fn empty(src: Source<'a>, lints: &'a LintMap) -> Self { + fn empty(src: Source<'a>, lints: &'a LintMap, sess: &'a SessionInfo) -> Self { Self { src, fixed: Vec::new(), lints, + sess, } } } @@ -40,15 +43,27 @@ pub mod main { use crate::{ config::{Fix as FixConfig, FixOut, Single as SingleConfig}, err::{FixErr, StatixErr}, + utils, }; + use lib::session::{SessionInfo, Version}; use similar::TextDiff; pub fn all(fix_config: FixConfig) -> Result<(), StatixErr> { let vfs = fix_config.vfs()?; let lints = fix_config.lints()?; + + let version = utils::get_version_info() + .unwrap() + .parse::() + .unwrap(); + let session = SessionInfo::from_version(version); + for entry in vfs.iter() { - match (fix_config.out(), super::all_with(entry.contents, &lints)) { + match ( + fix_config.out(), + super::all_with(entry.contents, &lints, &session), + ) { (FixOut::Diff, fix_result) => { let src = fix_result .map(|r| r.src) @@ -87,7 +102,16 @@ pub mod main { let original_src = entry.contents; let (line, col) = single_config.position; - match (single_config.out(), super::single(line, col, original_src)) { + let version = utils::get_version_info() + .unwrap() + .parse::() + .unwrap(); + let session = SessionInfo::from_version(version); + + match ( + single_config.out(), + super::single(line, col, original_src, &session), + ) { (FixOut::Diff, single_result) => { let fixed_src = single_result .map(|r| r.src) diff --git a/bin/src/fix/all.rs b/bin/src/fix/all.rs index 7e51d16..d7f7fff 100644 --- a/bin/src/fix/all.rs +++ b/bin/src/fix/all.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use lib::Report; +use lib::{session::SessionInfo, Report}; use rnix::{parser::ParseError as RnixParseErr, WalkEvent}; use crate::{ @@ -8,7 +8,11 @@ use crate::{ LintMap, }; -fn collect_fixes(source: &str, lints: &LintMap) -> Result, RnixParseErr> { +fn collect_fixes( + source: &str, + lints: &LintMap, + sess: &SessionInfo, +) -> Result, RnixParseErr> { let parsed = rnix::parse(source).as_result()?; Ok(parsed @@ -18,7 +22,7 @@ fn collect_fixes(source: &str, lints: &LintMap) -> Result, RnixParse WalkEvent::Enter(child) => lints.get(&child.kind()).map(|rules| { rules .iter() - .filter_map(|rule| rule.validate(&child)) + .filter_map(|rule| rule.validate(&child, sess)) .filter(|report| report.total_suggestion_range().is_some()) .collect::>() }), @@ -57,7 +61,7 @@ fn reorder(mut reports: Vec) -> Vec { impl<'a> Iterator for FixResult<'a> { type Item = FixResult<'a>; fn next(&mut self) -> Option { - let all_reports = collect_fixes(&self.src, self.lints).ok()?; + let all_reports = collect_fixes(&self.src, self.lints, &self.sess).ok()?; if all_reports.is_empty() { return None; } @@ -78,13 +82,18 @@ impl<'a> Iterator for FixResult<'a> { src: self.src.clone(), fixed, lints: self.lints, + sess: self.sess, }) } } -pub fn all_with<'a>(src: &'a str, lints: &'a LintMap) -> Option> { +pub fn all_with<'a>( + src: &'a str, + lints: &'a LintMap, + sess: &'a SessionInfo, +) -> Option> { let src = Cow::from(src); let _ = rnix::parse(&src).as_result().ok()?; - let initial = FixResult::empty(src, lints); + let initial = FixResult::empty(src, lints, sess); initial.into_iter().last() } diff --git a/bin/src/fix/single.rs b/bin/src/fix/single.rs index d95cfda..67b6b8f 100644 --- a/bin/src/fix/single.rs +++ b/bin/src/fix/single.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, convert::TryFrom}; -use lib::Report; +use lib::{session::SessionInfo, Report}; use rnix::{TextSize, WalkEvent}; use crate::{err::SingleFixErr, fix::Source, utils}; @@ -27,7 +27,7 @@ fn pos_to_byte(line: usize, col: usize, src: &str) -> Result Result { +fn find(offset: TextSize, src: &str, sess: &SessionInfo) -> Result { // we don't really need the source to form a completely parsed tree let parsed = rnix::parse(src); let lints = utils::lint_map(); @@ -39,7 +39,7 @@ fn find(offset: TextSize, src: &str) -> Result { WalkEvent::Enter(child) => lints.get(&child.kind()).map(|rules| { rules .iter() - .filter_map(|rule| rule.validate(&child)) + .filter_map(|rule| rule.validate(&child, sess)) .find(|report| report.total_suggestion_range().is_some()) }), _ => None, @@ -49,10 +49,15 @@ fn find(offset: TextSize, src: &str) -> Result { .ok_or(SingleFixErr::NoOp) } -pub fn single(line: usize, col: usize, src: &str) -> Result { +pub fn single<'a, 'b>( + line: usize, + col: usize, + src: &'a str, + sess: &'b SessionInfo, +) -> Result, SingleFixErr> { let mut src = Cow::from(src); let offset = pos_to_byte(line, col, &*src)?; - let report = find(offset, &*src)?; + let report = find(offset, &*src, &sess)?; report.apply(src.to_mut()); diff --git a/bin/src/lib.rs b/bin/src/lib.rs index 0105334..01d3ea7 100644 --- a/bin/src/lib.rs +++ b/bin/src/lib.rs @@ -4,6 +4,7 @@ pub mod err; pub mod explain; pub mod fix; pub mod lint; +pub mod session; pub mod traits; mod utils; diff --git a/bin/src/lint.rs b/bin/src/lint.rs index 3482d46..c385007 100644 --- a/bin/src/lint.rs +++ b/bin/src/lint.rs @@ -1,6 +1,6 @@ use crate::{utils, LintMap}; -use lib::Report; +use lib::{session::SessionInfo, Report}; use rnix::WalkEvent; use vfs::{FileId, VfsEntry}; @@ -10,7 +10,7 @@ pub struct LintResult { pub reports: Vec, } -pub fn lint_with(vfs_entry: VfsEntry, lints: &LintMap) -> LintResult { +pub fn lint_with(vfs_entry: VfsEntry, lints: &LintMap, sess: &SessionInfo) -> LintResult { let file_id = vfs_entry.file_id; let source = vfs_entry.contents; let parsed = rnix::parse(source); @@ -23,7 +23,7 @@ pub fn lint_with(vfs_entry: VfsEntry, lints: &LintMap) -> LintResult { WalkEvent::Enter(child) => lints.get(&child.kind()).map(|rules| { rules .iter() - .filter_map(|rule| rule.validate(&child)) + .filter_map(|rule| rule.validate(&child, sess)) .collect::>() }), _ => None, @@ -35,21 +35,30 @@ pub fn lint_with(vfs_entry: VfsEntry, lints: &LintMap) -> LintResult { LintResult { file_id, reports } } -pub fn lint(vfs_entry: VfsEntry) -> LintResult { - lint_with(vfs_entry, &utils::lint_map()) +pub fn lint(vfs_entry: VfsEntry, sess: &SessionInfo) -> LintResult { + lint_with(vfs_entry, &utils::lint_map(), &sess) } pub mod main { use std::io; use super::lint_with; - use crate::{config::Check as CheckConfig, err::StatixErr, traits::WriteDiagnostic}; + use crate::{config::Check as CheckConfig, err::StatixErr, traits::WriteDiagnostic, utils}; + + use lib::session::{SessionInfo, Version}; pub fn main(check_config: CheckConfig) -> Result<(), StatixErr> { let vfs = check_config.vfs()?; let mut stdout = io::stdout(); let lints = check_config.lints()?; - let lint = |vfs_entry| lint_with(vfs_entry, &lints); + + let version = utils::get_version_info() + .unwrap() + .parse::() + .unwrap(); + let session = SessionInfo::from_version(version); + + let lint = |vfs_entry| lint_with(vfs_entry, &lints, &session); vfs.iter().map(lint).for_each(|r| { stdout.write(&r, &vfs, check_config.format).unwrap(); }); diff --git a/bin/src/session.rs b/bin/src/session.rs new file mode 100644 index 0000000..e69de29 diff --git a/bin/src/utils.rs b/bin/src/utils.rs index 747a761..d374b4b 100644 --- a/bin/src/utils.rs +++ b/bin/src/utils.rs @@ -22,3 +22,14 @@ pub fn lint_map_of( pub fn lint_map() -> HashMap>> { lint_map_of(&*LINTS) } + +pub fn get_version_info() -> Option { + use std::process::Command; + let program = Command::new("nix") + .arg("--version") + .output() + .expect("failed to execute"); + std::str::from_utf8(&program.stdout) + .ok() + .map(ToOwned::to_owned) +} -- cgit v1.2.3