Skip to content

Commit 1995710

Browse files
committed
clippy_dev: Reuse buffers when updating files and don't write unchanged files in clippy_dev
1 parent 1516f35 commit 1995710

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

105108
pub fn print_lints() {
@@ -124,19 +127,6 @@ fn round_to_fifty(count: usize) -> usize {
124127
count / 50 * 50
125128
}
126129

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

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

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

0 commit comments

Comments
 (0)