Skip to content

Commit

Permalink
feat: add --write-changes to apply automatically the lint suggestion
Browse files Browse the repository at this point in the history
  • Loading branch information
ronnychevalier committed Aug 23, 2024
1 parent 7f67a2d commit eaf4819
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ rayon = "1.10.0"
regex = "1.10.5"
serde = { version = "1.0.204", features = ["derive"] }
serde_regex = "1.1.0"
tempfile = "3.10.1"
thiserror = "1.0.61"
toml = "0.8.14"
tree-sitter = "0.22.6"
Expand Down
8 changes: 8 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ pub(crate) struct Args {
#[arg(long, group = "mode", help_heading = "Mode")]
files: bool,

/// Write fixes out
#[arg(long, short, group = "mode", help_heading = "Mode")]
write_changes: bool,

/// Write the current configuration to file with `-` for stdout
#[arg(long, value_name = "OUTPUT", group = "mode", help_heading = "Mode")]
dump_config: Option<PathBuf>,
Expand Down Expand Up @@ -104,6 +108,10 @@ impl Args {
linter
.iter()
.map(|typo| {
if self.write_changes {
let _ = typo.fix().apply(file.path());
}

let typo: miette::Report = typo.into();
let _ = writeln!(stderr, "{typo:?}");
})
Expand Down
4 changes: 2 additions & 2 deletions src/lang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ impl Parsed for ParsedQuery {
/// A string that can be checked with its offset within its source
#[derive(PartialEq, Eq, Debug)]
pub struct LintableString {
pub(crate) offset: usize,
pub(crate) value: String,
offset: usize,
value: String,
}

impl LintableString {
Expand Down
57 changes: 56 additions & 1 deletion src/lint.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::io::Write;
use std::path::Path;

use miette::{SourceCode, SourceSpan};
Expand All @@ -15,13 +16,51 @@ pub trait Rule {
fn check(&self, bytes: &[u8]) -> Vec<Box<dyn Typo>>;
}

/// The kind of action to perform to fix the lint suggestion
pub enum Fix {
/// Unclear how to fix the typo, nothing is done
Unknown,

/// Removes some characters
Remove { span: SourceSpan },
}

impl Fix {
/// Applies the action on the given file and location
pub fn apply(&self, path: impl AsRef<Path>) -> anyhow::Result<()> {
match self {
Self::Unknown => Ok(()),
Self::Remove { span } => {
let path = path.as_ref();
let mut content = std::fs::read(path)?;
content.drain(span.offset()..(span.offset() + span.len()));

let mut file = if let Some(parent) = path.parent() {
tempfile::NamedTempFile::new_in(parent)?
} else {
tempfile::NamedTempFile::new()?
};
file.write_all(&content)?;
file.persist(path)?;

Ok(())
}
}
}
}

/// Type that represents a typo found
pub trait Typo: miette::Diagnostic + std::error::Error + Sync + Send {
/// Span that identify where the typo is located
fn span(&self) -> SourceSpan;

/// Specify within which source the typo has been found
fn with_source(&mut self, src: SharedSource, offset: usize);

/// Returns the action to perform to fix the typo
fn fix(&self) -> Fix {
Fix::Unknown
}
}

/// Detects typos in a file
Expand Down Expand Up @@ -192,9 +231,11 @@ impl miette::Diagnostic for Box<dyn Typo> {

#[cfg(test)]
mod tests {
use std::{fs::File, io::Write};

use crate::lint::Language;

use super::Linter;
use super::{Fix, Linter};

#[test]
fn from_path_unknown_extension() {
Expand Down Expand Up @@ -354,4 +395,18 @@ Hello mate `this should not trigger the rule : foobar` abc
let typos = linter.iter().count();
assert_eq!(typos, 0);
}

#[test]
fn write_changes() {
let fix = Fix::Remove {
span: (1, 2).into(),
};
let dir = tempfile::tempdir().unwrap();
let file_path = dir.path().join("file.txt");
let mut file = File::create(&file_path).unwrap();
file.write_all(b"123456").unwrap();
drop(file);
fix.apply(&file_path).unwrap();
assert_eq!(b"1456", std::fs::read(file_path).unwrap().as_slice());
}
}
6 changes: 5 additions & 1 deletion src/lint/punctuation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use winnow::error::InputError;
use winnow::token::{none_of, one_of, take};
use winnow::{Located, PResult, Parser};

use super::SharedSource;
use super::{Fix, SharedSource};
use super::{Rule, Typo};

/// A space *before* a punctuation mark has been detected.
Expand Down Expand Up @@ -61,6 +61,10 @@ impl Typo for TypoSpaceBeforePunctuationMarks {
self.src = Some(src);
self.span = (self.span.offset() + offset, self.span.len()).into();
}

fn fix(&self) -> Fix {
Fix::Remove { span: self.span }
}
}

/// A rule that detects typographical mistakes related to punctuation.
Expand Down

0 comments on commit eaf4819

Please sign in to comment.