aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/src/config.rs4
-rw-r--r--bin/src/fix/single.rs35
-rw-r--r--bin/src/main.rs17
3 files changed, 40 insertions, 16 deletions
diff --git a/bin/src/config.rs b/bin/src/config.rs
index fc4057a..8ddfb4a 100644
--- a/bin/src/config.rs
+++ b/bin/src/config.rs
@@ -83,6 +83,10 @@ pub struct Single {
83 /// Position to attempt a fix at 83 /// Position to attempt a fix at
84 #[clap(short, long, parse(try_from_str = parse_line_col))] 84 #[clap(short, long, parse(try_from_str = parse_line_col))]
85 pub position: (usize, usize), 85 pub position: (usize, usize),
86
87 /// Do not fix files in place, display a diff instead
88 #[clap(short, long = "dry-run")]
89 pub diff_only: bool,
86} 90}
87 91
88mod dirs { 92mod dirs {
diff --git a/bin/src/fix/single.rs b/bin/src/fix/single.rs
index d430693..24b5c51 100644
--- a/bin/src/fix/single.rs
+++ b/bin/src/fix/single.rs
@@ -1,7 +1,7 @@
1use std::{borrow::Cow, convert::TryFrom}; 1use std::{borrow::Cow, convert::TryFrom};
2 2
3use lib::{Report, LINTS}; 3use lib::{Report, LINTS};
4use rnix::{TextRange, TextSize}; 4use rnix::{TextSize, WalkEvent};
5 5
6use crate::err::SingleFixErr; 6use crate::err::SingleFixErr;
7use crate::fix::Source; 7use crate::fix::Source;
@@ -12,7 +12,7 @@ pub struct SingleFixResult<'δ> {
12 12
13fn pos_to_byte(line: usize, col: usize, src: &str) -> Result<TextSize, SingleFixErr> { 13fn pos_to_byte(line: usize, col: usize, src: &str) -> Result<TextSize, SingleFixErr> {
14 let mut byte: TextSize = TextSize::of(""); 14 let mut byte: TextSize = TextSize::of("");
15 for (_, l) in src.lines().enumerate().take_while(|(i, _)| i <= &line) { 15 for (l, _) in src.split_inclusive('\n').zip(1..).take_while(|(_, i)| i < &line) {
16 byte += TextSize::of(l); 16 byte += TextSize::of(l);
17 } 17 }
18 byte += TextSize::try_from(col).map_err(|_| SingleFixErr::Conversion(col))?; 18 byte += TextSize::try_from(col).map_err(|_| SingleFixErr::Conversion(col))?;
@@ -25,24 +25,31 @@ fn pos_to_byte(line: usize, col: usize, src: &str) -> Result<TextSize, SingleFix
25} 25}
26 26
27fn find(offset: TextSize, src: &str) -> Result<Report, SingleFixErr> { 27fn find(offset: TextSize, src: &str) -> Result<Report, SingleFixErr> {
28 let offset = offset - TextSize::from(1u32);
28 // we don't really need the source to form a completely parsed tree 29 // we don't really need the source to form a completely parsed tree
29 let parsed = rnix::parse(src); 30 let parsed = rnix::parse(src);
30 31
31 let elem_at = parsed 32 parsed
32 .node() 33 .node()
33 .child_or_token_at_range(TextRange::empty(offset)) 34 .preorder_with_tokens()
34 .ok_or(SingleFixErr::NoOp)?; 35 .filter_map(|event| match event {
35 36 WalkEvent::Enter(child) => {
36 LINTS 37 if child.text_range().start() == offset {
37 .get(&elem_at.kind()) 38 LINTS.get(&child.kind()).map(|rules| {
38 .map(|rules| { 39 rules
39 rules 40 .iter()
40 .iter() 41 .filter_map(|rule| rule.validate(&child))
41 .filter_map(|rule| rule.validate(&elem_at)) 42 .filter(|report| report.total_suggestion_range().is_some())
42 .filter(|report| report.total_suggestion_range().is_some()) 43 .next()
43 .next() 44 })
45 } else {
46 None
47 }
48 },
49 _ => None
44 }) 50 })
45 .flatten() 51 .flatten()
52 .next()
46 .ok_or(SingleFixErr::NoOp) 53 .ok_or(SingleFixErr::NoOp)
47} 54}
48 55
diff --git a/bin/src/main.rs b/bin/src/main.rs
index 9c57d91..cbf2601 100644
--- a/bin/src/main.rs
+++ b/bin/src/main.rs
@@ -55,8 +55,21 @@ fn _main() -> Result<(), StatixErr> {
55 let path = single_config.target; 55 let path = single_config.target;
56 let src = std::fs::read_to_string(&path).map_err(SingleFixErr::InvalidPath)?; 56 let src = std::fs::read_to_string(&path).map_err(SingleFixErr::InvalidPath)?;
57 let (line, col) = single_config.position; 57 let (line, col) = single_config.position;
58 let single_result = fix::single(line, col, &src)?; 58 let single_fix_result = fix::single(line, col, &src)?;
59 std::fs::write(&path, &*single_result.src).map_err(SingleFixErr::InvalidPath)?; 59 if single_config.diff_only {
60 let text_diff = TextDiff::from_lines(src.as_str(), &single_fix_result.src);
61 let old_file = format!("{}", path.display());
62 let new_file = format!("{} [fixed]", path.display());
63 println!(
64 "{}",
65 text_diff
66 .unified_diff()
67 .context_radius(4)
68 .header(&old_file, &new_file)
69 );
70 } else {
71 std::fs::write(&path, &*single_fix_result.src).map_err(SingleFixErr::InvalidPath)?;
72 }
60 } 73 }
61 } 74 }
62 Ok(()) 75 Ok(())