Skip to content

Commit 98cb92f

Browse files
committed
clippy_dev: Reuse buffers when updating files and don't write unchanged files in clippy_dev
1 parent 3fe5fb2 commit 98cb92f

File tree

6 files changed

+252
-239
lines changed

6 files changed

+252
-239
lines changed

clippy_dev/src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ fn main() {
3030
DevCommand::UpdateLints { print_only, check } => {
3131
if print_only {
3232
update_lints::print_lints();
33-
} else if check {
34-
update_lints::update(utils::UpdateMode::Check);
3533
} else {
36-
update_lints::update(utils::UpdateMode::Change);
34+
update_lints::update(utils::UpdateMode::from_check(check));
3735
}
3836
},
3937
DevCommand::NewLint {

clippy_dev/src/release.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
use crate::utils::{FileUpdater, Version, update_text_region_fn};
12
use std::fmt::Write;
23

3-
use crate::utils::{UpdateMode, Version, replace_region_in_file};
4-
5-
const CARGO_TOML_FILES: [&str; 4] = [
4+
static CARGO_TOML_FILES: &[&str] = &[
65
"clippy_config/Cargo.toml",
76
"clippy_lints/Cargo.toml",
87
"clippy_utils/Cargo.toml",
@@ -11,15 +10,18 @@ const CARGO_TOML_FILES: [&str; 4] = [
1110

1211
pub fn bump_version(mut version: Version) {
1312
version.minor += 1;
14-
for &file in &CARGO_TOML_FILES {
15-
replace_region_in_file(
16-
UpdateMode::Change,
17-
file.as_ref(),
18-
"# begin autogenerated version\n",
19-
"# end autogenerated version",
20-
|res| {
21-
writeln!(res, "version = \"{}\"", version.toml_display()).unwrap();
22-
},
13+
14+
let mut updater = FileUpdater::default();
15+
for file in CARGO_TOML_FILES {
16+
updater.update_file(
17+
file,
18+
&mut update_text_region_fn(
19+
"# begin autogenerated version\n",
20+
"# end autogenerated version",
21+
|dst| {
22+
writeln!(dst, "version = \"{}\"", version.toml_display()).unwrap();
23+
},
24+
),
2325
);
2426
}
2527
}

clippy_dev/src/rename_lint.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::update_lints::{
2-
RenamedLint, clippy_lints_src_files, gather_all, gen_renamed_lints_test, generate_lint_files,
2+
RenamedLint, clippy_lints_src_files, gather_all, gen_renamed_lints_test_fn, generate_lint_files,
33
};
44
use crate::utils::{
5-
UpdateMode, Version, insert_at_marker, replace_ident_like, rewrite_file, try_rename_file, write_file,
5+
FileUpdater, UpdateMode, Version, insert_at_marker, replace_ident_like, rewrite_file, try_rename_file,
66
};
77
use std::ffi::OsStr;
88
use std::path::Path;
@@ -32,6 +32,7 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
3232
panic!("`{new_name}` should not contain the `{prefix}` prefix");
3333
}
3434

35+
let mut updater = FileUpdater::default();
3536
let (mut lints, deprecated_lints, mut renamed_lints) = gather_all();
3637
let mut old_lint_index = None;
3738
let mut found_new_name = false;
@@ -72,8 +73,8 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
7273
&& name != Some(OsStr::new("rename.rs"))
7374
&& name != Some(OsStr::new("deprecated_lints.rs"))
7475
}) {
75-
rewrite_file(file.path(), |s| {
76-
replace_ident_like(s, &[(&lint.old_name, &lint.new_name)])
76+
updater.update_file(file.path(), &mut |_, src, dst| {
77+
replace_ident_like(&[(&lint.old_name, &lint.new_name)], src, dst)
7778
});
7879
}
7980

@@ -101,12 +102,12 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
101102
});
102103

103104
if uplift {
104-
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
105+
updater.update_file("tests/ui/rename.rs", &mut gen_renamed_lints_test_fn(&renamed_lints));
105106
println!(
106107
"`{old_name}` has be uplifted. All the code inside `clippy_lints` related to it needs to be removed manually."
107108
);
108109
} else if found_new_name {
109-
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
110+
updater.update_file("tests/ui/rename.rs", &mut gen_renamed_lints_test_fn(&renamed_lints));
110111
println!(
111112
"`{new_name}` is already defined. The old linting code inside `clippy_lints` needs to be updated/removed manually."
112113
);
@@ -173,7 +174,9 @@ pub fn rename(clippy_version: Version, old_name: &str, new_name: &str, uplift: b
173174
.to_str()
174175
.is_none_or(|x| x["clippy_lints/src/".len()..] != *"deprecated_lints.rs")
175176
{
176-
rewrite_file(file.path(), |s| replace_ident_like(s, replacements));
177+
updater.update_file(file.path(), &mut |_, src, dst| {
178+
replace_ident_like(replacements, src, dst)
179+
});
177180
}
178181
}
179182

clippy_dev/src/sync.rs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,18 @@
1-
use std::fmt::Write;
2-
use std::path::Path;
3-
1+
use crate::utils::{FileUpdater, update_text_region_fn};
42
use chrono::offset::Utc;
5-
6-
use crate::utils::{UpdateMode, replace_region_in_file};
3+
use std::fmt::Write;
74

85
pub fn update_nightly() {
9-
// Update rust-toolchain nightly version
106
let date = Utc::now().format("%Y-%m-%d").to_string();
11-
replace_region_in_file(
12-
UpdateMode::Change,
13-
Path::new("rust-toolchain.toml"),
7+
let update = &mut update_text_region_fn(
148
"# begin autogenerated nightly\n",
159
"# end autogenerated nightly",
16-
|res| {
17-
writeln!(res, "channel = \"nightly-{date}\"").unwrap();
10+
|dst| {
11+
writeln!(dst, "channel = \"nightly-{date}\"").unwrap();
1812
},
1913
);
2014

21-
// Update clippy_utils nightly version
22-
replace_region_in_file(
23-
UpdateMode::Change,
24-
Path::new("clippy_utils/README.md"),
25-
"<!-- begin autogenerated nightly -->\n",
26-
"<!-- end autogenerated nightly -->",
27-
|res| {
28-
writeln!(res, "```").unwrap();
29-
writeln!(res, "nightly-{date}").unwrap();
30-
writeln!(res, "```").unwrap();
31-
},
32-
);
15+
let mut updater = FileUpdater::default();
16+
updater.update_file("rust-toolchain.toml", update);
17+
updater.update_file("clippy_utils/README.md", update);
3318
}

clippy_dev/src/update_lints.rs

Lines changed: 85 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use crate::utils::{UpdateMode, exit_with_failure, replace_region_in_file};
1+
use crate::utils::{FileUpdater, UpdateMode, UpdateStatus, update_text_region_fn};
22
use itertools::Itertools;
33
use rustc_lexer::{LiteralKind, TokenKind, tokenize};
44
use rustc_literal_escaper::{Mode, unescape_unicode};
55
use std::collections::{HashMap, HashSet};
66
use std::ffi::OsStr;
7-
use std::fmt::{self, Write};
7+
use std::fmt::Write;
88
use std::fs;
99
use std::ops::Range;
1010
use std::path::Path;
@@ -33,74 +33,77 @@ pub fn update(update_mode: UpdateMode) {
3333
pub fn generate_lint_files(
3434
update_mode: UpdateMode,
3535
lints: &[Lint],
36-
deprecated_lints: &[DeprecatedLint],
37-
renamed_lints: &[RenamedLint],
36+
deprecated: &[DeprecatedLint],
37+
renamed: &[RenamedLint],
3838
) {
3939
let mut lints = lints.to_owned();
40-
lints.sort_by_key(|lint| lint.name.clone());
41-
42-
replace_region_in_file(
43-
update_mode,
44-
Path::new("README.md"),
45-
"[There are over ",
46-
" lints included in this crate!]",
47-
|res| {
48-
write!(res, "{}", round_to_fifty(lints.len())).unwrap();
49-
},
50-
);
51-
52-
replace_region_in_file(
53-
update_mode,
54-
Path::new("book/src/README.md"),
55-
"[There are over ",
56-
" lints included in this crate!]",
57-
|res| {
58-
write!(res, "{}", round_to_fifty(lints.len())).unwrap();
59-
},
60-
);
61-
62-
replace_region_in_file(
63-
update_mode,
64-
Path::new("CHANGELOG.md"),
65-
"<!-- begin autogenerated links to lint list -->\n",
66-
"<!-- end autogenerated links to lint list -->",
67-
|res| {
68-
for lint in lints
69-
.iter()
70-
.map(|l| &*l.name)
71-
.chain(deprecated_lints.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
72-
.chain(renamed_lints.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
73-
.sorted()
74-
{
75-
writeln!(res, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
76-
}
77-
},
78-
);
79-
80-
// This has to be in lib.rs, otherwise rustfmt doesn't work
81-
replace_region_in_file(
82-
update_mode,
83-
Path::new("clippy_lints/src/lib.rs"),
84-
"// begin lints modules, do not remove this comment, it’s used in `update_lints`\n",
85-
"// end lints modules, do not remove this comment, it’s used in `update_lints`",
86-
|res| {
87-
for lint_mod in lints.iter().map(|l| &l.module).unique().sorted() {
88-
writeln!(res, "mod {lint_mod};").unwrap();
89-
}
90-
},
91-
);
92-
93-
process_file(
94-
"clippy_lints/src/declared_lints.rs",
40+
lints.sort_by(|lhs, rhs| lhs.name.cmp(&rhs.name));
41+
FileUpdater::default().update_files_checked(
42+
"cargo dev update_lints",
9543
update_mode,
96-
&gen_declared_lints(lints.iter()),
44+
&mut [
45+
(
46+
"README.md",
47+
&mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
48+
write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
49+
}),
50+
),
51+
(
52+
"book/src/README.md",
53+
&mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
54+
write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
55+
}),
56+
),
57+
(
58+
"CHANGELOG.md",
59+
&mut update_text_region_fn(
60+
"<!-- begin autogenerated links to lint list -->\n",
61+
"<!-- end autogenerated links to lint list -->",
62+
|dst| {
63+
for lint in lints
64+
.iter()
65+
.map(|l| &*l.name)
66+
.chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
67+
.chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
68+
.sorted()
69+
{
70+
writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
71+
}
72+
},
73+
),
74+
),
75+
(
76+
"clippy_lints/src/lib.rs",
77+
&mut update_text_region_fn(
78+
"// begin lints modules, do not remove this comment, it’s used in `update_lints`\n",
79+
"// end lints modules, do not remove this comment, it’s used in `update_lints`",
80+
|dst| {
81+
for lint_mod in lints.iter().map(|l| &l.module).sorted().dedup() {
82+
writeln!(dst, "mod {lint_mod};").unwrap();
83+
}
84+
},
85+
),
86+
),
87+
("clippy_lints/src/declared_lints.rs", &mut |_, src, dst| {
88+
dst.push_str(GENERATED_FILE_COMMENT);
89+
dst.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
90+
for (module_name, lint_name) in lints.iter().map(|l| (&l.module, l.name.to_uppercase())).sorted() {
91+
writeln!(dst, " crate::{module_name}::{lint_name}_INFO,").unwrap();
92+
}
93+
dst.push_str("];\n");
94+
UpdateStatus::from_changed(src != dst)
95+
}),
96+
("tests/ui/deprecated.rs", &mut |_, src, dst| {
97+
dst.push_str(GENERATED_FILE_COMMENT);
98+
for lint in deprecated {
99+
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
100+
}
101+
dst.push_str("\nfn main() {}\n");
102+
UpdateStatus::from_changed(src != dst)
103+
}),
104+
("tests/ui/rename.rs", &mut gen_renamed_lints_test_fn(renamed)),
105+
],
97106
);
98-
99-
let content = gen_deprecated_lints_test(deprecated_lints);
100-
process_file("tests/ui/deprecated.rs", update_mode, &content);
101-
102-
let content = gen_renamed_lints_test(renamed_lints);
103-
process_file("tests/ui/rename.rs", update_mode, &content);
104107
}
105108

106109
pub fn print_lints() {
@@ -125,19 +128,6 @@ fn round_to_fifty(count: usize) -> usize {
125128
count / 50 * 50
126129
}
127130

128-
fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str) {
129-
if update_mode == UpdateMode::Check {
130-
let old_content =
131-
fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {e}", path.as_ref().display()));
132-
if content != old_content {
133-
exit_with_failure();
134-
}
135-
} else {
136-
fs::write(&path, content.as_bytes())
137-
.unwrap_or_else(|e| panic!("Cannot write to {}: {e}", path.as_ref().display()));
138-
}
139-
}
140-
141131
/// Lint data parsed from the Clippy source code.
142132
#[derive(Clone, PartialEq, Eq, Debug)]
143133
pub struct Lint {
@@ -194,51 +184,25 @@ impl RenamedLint {
194184
}
195185
}
196186

197-
/// Generates the code for registering lints
198-
#[must_use]
199-
fn gen_declared_lints<'a>(lints: impl Iterator<Item = &'a Lint>) -> String {
200-
let mut details: Vec<_> = lints.map(|l| (&l.module, l.name.to_uppercase())).collect();
201-
details.sort_unstable();
202-
203-
let mut output = GENERATED_FILE_COMMENT.to_string();
204-
output.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
205-
206-
for (module_name, lint_name) in details {
207-
let _: fmt::Result = writeln!(output, " crate::{module_name}::{lint_name}_INFO,");
208-
}
209-
output.push_str("];\n");
210-
211-
output
212-
}
213-
214-
fn gen_deprecated_lints_test(lints: &[DeprecatedLint]) -> String {
215-
let mut res: String = GENERATED_FILE_COMMENT.into();
216-
for lint in lints {
217-
writeln!(res, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
218-
}
219-
res.push_str("\nfn main() {}\n");
220-
res
221-
}
222-
223-
#[must_use]
224-
pub fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
225-
let mut seen_lints = HashSet::new();
226-
let mut res: String = GENERATED_FILE_COMMENT.into();
227-
228-
res.push_str("#![allow(clippy::duplicated_attributes)]\n");
229-
for lint in lints {
230-
if seen_lints.insert(&lint.new_name) {
231-
writeln!(res, "#![allow({})]", lint.new_name).unwrap();
187+
pub fn gen_renamed_lints_test_fn(lints: &[RenamedLint]) -> impl Fn(&Path, &str, &mut String) -> UpdateStatus {
188+
move |_, src, dst| {
189+
let mut seen_lints = HashSet::new();
190+
dst.push_str(GENERATED_FILE_COMMENT);
191+
dst.push_str("#![allow(clippy::duplicated_attributes)]\n");
192+
for lint in lints {
193+
if seen_lints.insert(&lint.new_name) {
194+
writeln!(dst, "#![allow({})]", lint.new_name).unwrap();
195+
}
232196
}
233-
}
234-
seen_lints.clear();
235-
for lint in lints {
236-
if seen_lints.insert(&lint.old_name) {
237-
writeln!(res, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
197+
seen_lints.clear();
198+
for lint in lints {
199+
if seen_lints.insert(&lint.old_name) {
200+
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
201+
}
238202
}
203+
dst.push_str("\nfn main() {}\n");
204+
UpdateStatus::from_changed(src != dst)
239205
}
240-
res.push_str("\nfn main() {}\n");
241-
res
242206
}
243207

244208
/// Gathers all lints defined in `clippy_lints/src`

0 commit comments

Comments
 (0)