Skip to content

Commit 2c85cb0

Browse files
committed
clippy_dev: Only build AhoCorasick searcher once for multiple files.
1 parent 98cb92f commit 2c85cb0

File tree

2 files changed

+42
-32
lines changed

2 files changed

+42
-32
lines changed

clippy_dev/src/rename_lint.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
use crate::update_lints::{
22
RenamedLint, clippy_lints_src_files, gather_all, gen_renamed_lints_test_fn, generate_lint_files,
33
};
4-
use crate::utils::{
5-
FileUpdater, UpdateMode, Version, insert_at_marker, replace_ident_like, rewrite_file, try_rename_file,
6-
};
4+
use crate::utils::{FileUpdater, StringReplacer, UpdateMode, Version, insert_at_marker, rewrite_file, try_rename_file};
75
use std::ffi::OsStr;
86
use std::path::Path;
97
use walkdir::WalkDir;
@@ -66,16 +64,16 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
6664
);
6765

6866
// Update all lint level attributes. (`clippy::lint_name`)
67+
let replacements = &[(&*lint.old_name, &*lint.new_name)];
68+
let replacer = StringReplacer::new(replacements);
6969
for file in WalkDir::new(".").into_iter().map(Result::unwrap).filter(|f| {
7070
let name = f.path().file_name();
7171
let ext = f.path().extension();
7272
(ext == Some(OsStr::new("rs")) || ext == Some(OsStr::new("fixed")))
7373
&& name != Some(OsStr::new("rename.rs"))
7474
&& name != Some(OsStr::new("deprecated_lints.rs"))
7575
}) {
76-
updater.update_file(file.path(), &mut |_, src, dst| {
77-
replace_ident_like(&[(&lint.old_name, &lint.new_name)], src, dst)
78-
});
76+
updater.update_file(file.path(), &mut replacer.replace_ident_fn());
7977
}
8078

8179
rewrite_file(Path::new("clippy_lints/src/deprecated_lints.rs"), |s| {
@@ -167,16 +165,15 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
167165

168166
// Don't change `clippy_utils/src/renamed_lints.rs` here as it would try to edit the lint being
169167
// renamed.
168+
let replacer = StringReplacer::new(replacements);
170169
for file in clippy_lints_src_files() {
171170
if file
172171
.path()
173172
.as_os_str()
174173
.to_str()
175174
.is_none_or(|x| x["clippy_lints/src/".len()..] != *"deprecated_lints.rs")
176175
{
177-
updater.update_file(file.path(), &mut |_, src, dst| {
178-
replace_ident_like(replacements, src, dst)
179-
});
176+
updater.update_file(file.path(), &mut replacer.replace_ident_fn());
180177
}
181178
}
182179

clippy_dev/src/utils.rs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use aho_corasick::AhoCorasickBuilder;
1+
use aho_corasick::{AhoCorasick, AhoCorasickBuilder};
22
use core::fmt::{self, Display};
33
use core::str::FromStr;
44
use std::env;
@@ -344,33 +344,46 @@ pub fn update_text_region_fn(
344344
move |path, src, dst| update_text_region(path, start, end, src, dst, &mut insert)
345345
}
346346

347-
/// Replace substrings if they aren't bordered by identifier characters. Returns `None` if there
348-
/// were no replacements.
349347
#[must_use]
350-
pub fn replace_ident_like(replacements: &[(&str, &str)], src: &str, dst: &mut String) -> UpdateStatus {
351-
fn is_ident_char(c: u8) -> bool {
352-
matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_')
353-
}
348+
pub fn is_ident_char(c: u8) -> bool {
349+
matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_')
350+
}
354351

355-
let searcher = AhoCorasickBuilder::new()
356-
.match_kind(aho_corasick::MatchKind::LeftmostLongest)
357-
.build(replacements.iter().map(|&(x, _)| x.as_bytes()))
358-
.unwrap();
352+
pub struct StringReplacer<'a> {
353+
searcher: AhoCorasick,
354+
replacements: &'a [(&'a str, &'a str)],
355+
}
356+
impl<'a> StringReplacer<'a> {
357+
#[must_use]
358+
pub fn new(replacements: &'a [(&'a str, &'a str)]) -> Self {
359+
Self {
360+
searcher: AhoCorasickBuilder::new()
361+
.match_kind(aho_corasick::MatchKind::LeftmostLongest)
362+
.build(replacements.iter().map(|&(x, _)| x))
363+
.unwrap(),
364+
replacements,
365+
}
366+
}
359367

360-
let mut pos = 0;
361-
let mut changed = false;
362-
for m in searcher.find_iter(src) {
363-
if !is_ident_char(src.as_bytes().get(m.start().wrapping_sub(1)).copied().unwrap_or(0))
364-
&& !is_ident_char(src.as_bytes().get(m.end()).copied().unwrap_or(0))
365-
{
366-
dst.push_str(&src[pos..m.start()]);
367-
dst.push_str(replacements[m.pattern()].1);
368-
pos = m.end();
369-
changed = true;
368+
/// Replace substrings if they aren't bordered by identifier characters.
369+
pub fn replace_ident_fn(&self) -> impl Fn(&Path, &str, &mut String) -> UpdateStatus {
370+
move |_, src, dst| {
371+
let mut pos = 0;
372+
let mut changed = false;
373+
for m in self.searcher.find_iter(src) {
374+
if !is_ident_char(src.as_bytes().get(m.start().wrapping_sub(1)).copied().unwrap_or(0))
375+
&& !is_ident_char(src.as_bytes().get(m.end()).copied().unwrap_or(0))
376+
{
377+
changed = true;
378+
dst.push_str(&src[pos..m.start()]);
379+
dst.push_str(self.replacements[m.pattern()].1);
380+
pos = m.end();
381+
}
382+
}
383+
dst.push_str(&src[pos..]);
384+
UpdateStatus::from_changed(changed)
370385
}
371386
}
372-
dst.push_str(&src[pos..]);
373-
UpdateStatus::from_changed(changed)
374387
}
375388

376389
#[expect(clippy::must_use_candidate)]

0 commit comments

Comments
 (0)