Lints and suggestions for the Nix programming language
1
fork

Configure Feed

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

fix single fix command

Akshay 393c2856 cd527e84

+40 -16
+4
bin/src/config.rs
··· 83 83 /// Position to attempt a fix at 84 84 #[clap(short, long, parse(try_from_str = parse_line_col))] 85 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 88 92 mod dirs {
+21 -14
bin/src/fix/single.rs
··· 1 1 use std::{borrow::Cow, convert::TryFrom}; 2 2 3 3 use lib::{Report, LINTS}; 4 - use rnix::{TextRange, TextSize}; 4 + use rnix::{TextSize, WalkEvent}; 5 5 6 6 use crate::err::SingleFixErr; 7 7 use crate::fix::Source; ··· 12 12 13 13 fn pos_to_byte(line: usize, col: usize, src: &str) -> Result<TextSize, SingleFixErr> { 14 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 16 byte += TextSize::of(l); 17 17 } 18 18 byte += TextSize::try_from(col).map_err(|_| SingleFixErr::Conversion(col))?; ··· 25 25 } 26 26 27 27 fn find(offset: TextSize, src: &str) -> Result<Report, SingleFixErr> { 28 + let offset = offset - TextSize::from(1u32); 28 29 // we don't really need the source to form a completely parsed tree 29 30 let parsed = rnix::parse(src); 30 31 31 - let elem_at = parsed 32 + parsed 32 33 .node() 33 - .child_or_token_at_range(TextRange::empty(offset)) 34 - .ok_or(SingleFixErr::NoOp)?; 35 - 36 - LINTS 37 - .get(&elem_at.kind()) 38 - .map(|rules| { 39 - rules 40 - .iter() 41 - .filter_map(|rule| rule.validate(&elem_at)) 42 - .filter(|report| report.total_suggestion_range().is_some()) 43 - .next() 34 + .preorder_with_tokens() 35 + .filter_map(|event| match event { 36 + WalkEvent::Enter(child) => { 37 + if child.text_range().start() == offset { 38 + LINTS.get(&child.kind()).map(|rules| { 39 + rules 40 + .iter() 41 + .filter_map(|rule| rule.validate(&child)) 42 + .filter(|report| report.total_suggestion_range().is_some()) 43 + .next() 44 + }) 45 + } else { 46 + None 47 + } 48 + }, 49 + _ => None 44 50 }) 45 51 .flatten() 52 + .next() 46 53 .ok_or(SingleFixErr::NoOp) 47 54 } 48 55
+15 -2
bin/src/main.rs
··· 55 55 let path = single_config.target; 56 56 let src = std::fs::read_to_string(&path).map_err(SingleFixErr::InvalidPath)?; 57 57 let (line, col) = single_config.position; 58 - let single_result = fix::single(line, col, &src)?; 59 - std::fs::write(&path, &*single_result.src).map_err(SingleFixErr::InvalidPath)?; 58 + let single_fix_result = fix::single(line, col, &src)?; 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 75 Ok(())