diff options
Diffstat (limited to 'bin/src/fix.rs')
-rw-r--r-- | bin/src/fix.rs | 87 |
1 files changed, 6 insertions, 81 deletions
diff --git a/bin/src/fix.rs b/bin/src/fix.rs index d9087fe..a7ddc4f 100644 --- a/bin/src/fix.rs +++ b/bin/src/fix.rs | |||
@@ -1,55 +1,14 @@ | |||
1 | use std::borrow::Cow; | 1 | use std::borrow::Cow; |
2 | 2 | ||
3 | use lib::{Report, LINTS}; | 3 | use rnix::TextRange; |
4 | use rnix::{parser::ParseError as RnixParseErr, TextRange, WalkEvent}; | ||
5 | 4 | ||
6 | type Source<'a> = Cow<'a, str>; | 5 | mod all; |
7 | 6 | pub use all::all; | |
8 | fn collect_fixes(source: &str) -> Result<Vec<Report>, RnixParseErr> { | ||
9 | let parsed = rnix::parse(source).as_result()?; | ||
10 | |||
11 | Ok(parsed | ||
12 | .node() | ||
13 | .preorder_with_tokens() | ||
14 | .filter_map(|event| match event { | ||
15 | WalkEvent::Enter(child) => LINTS.get(&child.kind()).map(|rules| { | ||
16 | rules | ||
17 | .iter() | ||
18 | .filter_map(|rule| rule.validate(&child)) | ||
19 | .filter(|report| report.total_suggestion_range().is_some()) | ||
20 | .collect::<Vec<_>>() | ||
21 | }), | ||
22 | _ => None, | ||
23 | }) | ||
24 | .flatten() | ||
25 | .collect()) | ||
26 | } | ||
27 | 7 | ||
28 | fn reorder(mut reports: Vec<Report>) -> Vec<Report> { | 8 | mod single; |
29 | use std::collections::VecDeque; | 9 | pub use single::single; |
30 | 10 | ||
31 | reports.sort_by(|a, b| { | 11 | type Source<'a> = Cow<'a, str>; |
32 | let a_range = a.range(); | ||
33 | let b_range = b.range(); | ||
34 | a_range.end().partial_cmp(&b_range.end()).unwrap() | ||
35 | }); | ||
36 | |||
37 | reports | ||
38 | .into_iter() | ||
39 | .fold(VecDeque::new(), |mut deque: VecDeque<Report>, new_elem| { | ||
40 | let front = deque.front(); | ||
41 | let new_range = new_elem.range(); | ||
42 | if let Some(front_range) = front.map(|f| f.range()) { | ||
43 | if new_range.start() > front_range.end() { | ||
44 | deque.push_front(new_elem); | ||
45 | } | ||
46 | } else { | ||
47 | deque.push_front(new_elem); | ||
48 | } | ||
49 | deque | ||
50 | }) | ||
51 | .into() | ||
52 | } | ||
53 | 12 | ||
54 | #[derive(Debug)] | 13 | #[derive(Debug)] |
55 | pub struct FixResult<'a> { | 14 | pub struct FixResult<'a> { |
@@ -68,37 +27,3 @@ impl<'a> FixResult<'a> { | |||
68 | Self { src, fixed: Vec::new() } | 27 | Self { src, fixed: Vec::new() } |
69 | } | 28 | } |
70 | } | 29 | } |
71 | |||
72 | impl<'a> Iterator for FixResult<'a> { | ||
73 | type Item = FixResult<'a>; | ||
74 | fn next(&mut self) -> Option<Self::Item> { | ||
75 | let all_reports = collect_fixes(&self.src).ok()?; | ||
76 | if all_reports.is_empty() { | ||
77 | return None; | ||
78 | } | ||
79 | |||
80 | let reordered = reorder(all_reports); | ||
81 | let fixed = reordered | ||
82 | .iter() | ||
83 | .map(|r| Fixed { | ||
84 | at: r.range(), | ||
85 | code: r.code, | ||
86 | }) | ||
87 | .collect::<Vec<_>>(); | ||
88 | for report in reordered { | ||
89 | report.apply(self.src.to_mut()); | ||
90 | } | ||
91 | |||
92 | Some(FixResult { | ||
93 | src: self.src.clone(), | ||
94 | fixed | ||
95 | }) | ||
96 | } | ||
97 | } | ||
98 | |||
99 | pub fn fix(src: &str) -> Option<FixResult> { | ||
100 | let src = Cow::from(src); | ||
101 | let _ = rnix::parse(&src).as_result().ok()?; | ||
102 | let initial = FixResult::empty(src); | ||
103 | initial.into_iter().last() | ||
104 | } | ||