From 5f0a1e67c64082c848418daa2b51020eb42c5c12 Mon Sep 17 00:00:00 2001 From: Akshay Date: Mon, 25 Oct 2021 22:08:52 +0530 Subject: rework cli, use subcommands instead --- bin/src/fix/all.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 bin/src/fix/all.rs (limited to 'bin/src/fix/all.rs') diff --git a/bin/src/fix/all.rs b/bin/src/fix/all.rs new file mode 100644 index 0000000..8c0770d --- /dev/null +++ b/bin/src/fix/all.rs @@ -0,0 +1,86 @@ +use std::borrow::Cow; + +use lib::{Report, LINTS}; +use rnix::{parser::ParseError as RnixParseErr, WalkEvent}; + +use crate::fix::{Fixed, FixResult}; + +fn collect_fixes(source: &str) -> Result, RnixParseErr> { + let parsed = rnix::parse(source).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)) + .filter(|report| report.total_suggestion_range().is_some()) + .collect::>() + }), + _ => None, + }) + .flatten() + .collect()) +} + +fn reorder(mut reports: Vec) -> Vec { + use std::collections::VecDeque; + + reports.sort_by(|a, b| { + let a_range = a.range(); + let b_range = b.range(); + a_range.end().partial_cmp(&b_range.end()).unwrap() + }); + + reports + .into_iter() + .fold(VecDeque::new(), |mut deque: VecDeque, new_elem| { + let front = deque.front(); + let new_range = new_elem.range(); + if let Some(front_range) = front.map(|f| f.range()) { + if new_range.start() > front_range.end() { + deque.push_front(new_elem); + } + } else { + deque.push_front(new_elem); + } + deque + }) + .into() +} + +impl<'a> Iterator for FixResult<'a> { + type Item = FixResult<'a>; + fn next(&mut self) -> Option { + let all_reports = collect_fixes(&self.src).ok()?; + if all_reports.is_empty() { + return None; + } + + let reordered = reorder(all_reports); + let fixed = reordered + .iter() + .map(|r| Fixed { + at: r.range(), + code: r.code, + }) + .collect::>(); + for report in reordered { + report.apply(self.src.to_mut()); + } + + Some(FixResult { + src: self.src.clone(), + fixed + }) + } +} + +pub fn all(src: &str) -> Option { + let src = Cow::from(src); + let _ = rnix::parse(&src).as_result().ok()?; + let initial = FixResult::empty(src); + initial.into_iter().last() +} -- cgit v1.2.3