diff options
| author | Jason Newcomb <jsnewcomb@pm.me> | 2025-04-14 14:14:03 -0400 |
|---|---|---|
| committer | Jason Newcomb <jsnewcomb@pm.me> | 2025-05-12 17:07:52 -0400 |
| commit | 2c85cb0371ca0e8980a4225714ed3407f1670e12 (patch) | |
| tree | 8f8eccb5a9f7c79a36925f814964e26315a8b56a | |
| parent | 98cb92f3235c4c963d1c17e8a833f37091b5b487 (diff) | |
| download | rust-2c85cb0371ca0e8980a4225714ed3407f1670e12.tar.gz rust-2c85cb0371ca0e8980a4225714ed3407f1670e12.zip | |
clippy_dev: Only build `AhoCorasick` searcher once for multiple files.
| -rw-r--r-- | clippy_dev/src/rename_lint.rs | 15 | ||||
| -rw-r--r-- | clippy_dev/src/utils.rs | 59 |
2 files changed, 42 insertions, 32 deletions
diff --git a/clippy_dev/src/rename_lint.rs b/clippy_dev/src/rename_lint.rs index 25db95a4489..c78ec98c1aa 100644 --- a/clippy_dev/src/rename_lint.rs +++ b/clippy_dev/src/rename_lint.rs @@ -1,9 +1,7 @@ use crate::update_lints::{ RenamedLint, clippy_lints_src_files, gather_all, gen_renamed_lints_test_fn, generate_lint_files, }; -use crate::utils::{ - FileUpdater, UpdateMode, Version, insert_at_marker, replace_ident_like, rewrite_file, try_rename_file, -}; +use crate::utils::{FileUpdater, StringReplacer, UpdateMode, Version, insert_at_marker, rewrite_file, try_rename_file}; use std::ffi::OsStr; use std::path::Path; use walkdir::WalkDir; @@ -66,6 +64,8 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b ); // Update all lint level attributes. (`clippy::lint_name`) + let replacements = &[(&*lint.old_name, &*lint.new_name)]; + let replacer = StringReplacer::new(replacements); for file in WalkDir::new(".").into_iter().map(Result::unwrap).filter(|f| { let name = f.path().file_name(); let ext = f.path().extension(); @@ -73,9 +73,7 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b && name != Some(OsStr::new("rename.rs")) && name != Some(OsStr::new("deprecated_lints.rs")) }) { - updater.update_file(file.path(), &mut |_, src, dst| { - replace_ident_like(&[(&lint.old_name, &lint.new_name)], src, dst) - }); + updater.update_file(file.path(), &mut replacer.replace_ident_fn()); } rewrite_file(Path::new("clippy_lints/src/deprecated_lints.rs"), |s| { @@ -167,6 +165,7 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b // Don't change `clippy_utils/src/renamed_lints.rs` here as it would try to edit the lint being // renamed. + let replacer = StringReplacer::new(replacements); for file in clippy_lints_src_files() { if file .path() @@ -174,9 +173,7 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b .to_str() .is_none_or(|x| x["clippy_lints/src/".len()..] != *"deprecated_lints.rs") { - updater.update_file(file.path(), &mut |_, src, dst| { - replace_ident_like(replacements, src, dst) - }); + updater.update_file(file.path(), &mut replacer.replace_ident_fn()); } } diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs index aaacdcf65c1..9f48832af00 100644 --- a/clippy_dev/src/utils.rs +++ b/clippy_dev/src/utils.rs @@ -1,4 +1,4 @@ -use aho_corasick::AhoCorasickBuilder; +use aho_corasick::{AhoCorasick, AhoCorasickBuilder}; use core::fmt::{self, Display}; use core::str::FromStr; use std::env; @@ -344,33 +344,46 @@ pub fn update_text_region_fn( move |path, src, dst| update_text_region(path, start, end, src, dst, &mut insert) } -/// Replace substrings if they aren't bordered by identifier characters. Returns `None` if there -/// were no replacements. #[must_use] -pub fn replace_ident_like(replacements: &[(&str, &str)], src: &str, dst: &mut String) -> UpdateStatus { - fn is_ident_char(c: u8) -> bool { - matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') - } +pub fn is_ident_char(c: u8) -> bool { + matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_') +} - let searcher = AhoCorasickBuilder::new() - .match_kind(aho_corasick::MatchKind::LeftmostLongest) - .build(replacements.iter().map(|&(x, _)| x.as_bytes())) - .unwrap(); +pub struct StringReplacer<'a> { + searcher: AhoCorasick, + replacements: &'a [(&'a str, &'a str)], +} +impl<'a> StringReplacer<'a> { + #[must_use] + pub fn new(replacements: &'a [(&'a str, &'a str)]) -> Self { + Self { + searcher: AhoCorasickBuilder::new() + .match_kind(aho_corasick::MatchKind::LeftmostLongest) + .build(replacements.iter().map(|&(x, _)| x)) + .unwrap(), + replacements, + } + } - let mut pos = 0; - let mut changed = false; - for m in searcher.find_iter(src) { - if !is_ident_char(src.as_bytes().get(m.start().wrapping_sub(1)).copied().unwrap_or(0)) - && !is_ident_char(src.as_bytes().get(m.end()).copied().unwrap_or(0)) - { - dst.push_str(&src[pos..m.start()]); - dst.push_str(replacements[m.pattern()].1); - pos = m.end(); - changed = true; + /// Replace substrings if they aren't bordered by identifier characters. + pub fn replace_ident_fn(&self) -> impl Fn(&Path, &str, &mut String) -> UpdateStatus { + move |_, src, dst| { + let mut pos = 0; + let mut changed = false; + for m in self.searcher.find_iter(src) { + if !is_ident_char(src.as_bytes().get(m.start().wrapping_sub(1)).copied().unwrap_or(0)) + && !is_ident_char(src.as_bytes().get(m.end()).copied().unwrap_or(0)) + { + changed = true; + dst.push_str(&src[pos..m.start()]); + dst.push_str(self.replacements[m.pattern()].1); + pos = m.end(); + } + } + dst.push_str(&src[pos..]); + UpdateStatus::from_changed(changed) } } - dst.push_str(&src[pos..]); - UpdateStatus::from_changed(changed) } #[expect(clippy::must_use_candidate)] |
