Skip to content

Commit d74d920

Browse files
committed
Prepare update_lints to work with multiple crates.
1 parent aa3a855 commit d74d920

File tree

2 files changed

+192
-129
lines changed

2 files changed

+192
-129
lines changed

clippy_dev/src/update_lints.rs

Lines changed: 192 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,43 @@ const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev u
1414

1515
const DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html";
1616

17+
macro_rules! declare_lint_crates {
18+
($($name:ident,)*) => {
19+
#[allow(non_camel_case_types)]
20+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21+
pub enum Crate {
22+
$($name),*
23+
}
24+
impl Crate {
25+
#[must_use]
26+
pub fn src_path(self) -> &'static str {
27+
match self {
28+
$(Self::$name => concat!(stringify!($name), "/src")),*
29+
}
30+
}
31+
32+
fn crate_root_path(self) -> &'static str {
33+
match self {
34+
$(Self::$name => concat!(stringify!($name), "/src/lib.rs")),*
35+
}
36+
}
37+
38+
fn declared_lints_path(self) -> &'static str {
39+
match self {
40+
$(Self::$name => concat!(stringify!($name), "/src/declared_lints.rs")),*
41+
}
42+
}
43+
44+
fn all() -> impl Iterator<Item = Crate> {
45+
[$(Self::$name),*].into_iter()
46+
}
47+
}
48+
}
49+
}
50+
declare_lint_crates! {
51+
clippy_lints,
52+
}
53+
1754
/// Runs the `update_lints` command.
1855
///
1956
/// This updates various generated values from the lint source code.
@@ -36,123 +73,159 @@ pub fn generate_lint_files(
3673
deprecated: &[DeprecatedLint],
3774
renamed: &[RenamedLint],
3875
) {
39-
FileUpdater::default().update_files_checked(
76+
let mut updater = FileUpdater::default();
77+
updater.update_file_checked(
4078
"cargo dev update_lints",
4179
update_mode,
42-
&mut [
43-
(
44-
"README.md",
45-
&mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
46-
write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
47-
}),
48-
),
49-
(
50-
"book/src/README.md",
51-
&mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
52-
write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
53-
}),
54-
),
55-
(
56-
"CHANGELOG.md",
57-
&mut update_text_region_fn(
58-
"<!-- begin autogenerated links to lint list -->\n",
59-
"<!-- end autogenerated links to lint list -->",
60-
|dst| {
61-
for lint in lints
62-
.iter()
63-
.map(|l| &*l.name)
64-
.chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
65-
.chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
66-
.sorted()
67-
{
68-
writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
69-
}
70-
},
71-
),
72-
),
73-
(
74-
"clippy_lints/src/lib.rs",
75-
&mut update_text_region_fn(
76-
"// begin lints modules, do not remove this comment, it’s used in `update_lints`\n",
77-
"// end lints modules, do not remove this comment, it’s used in `update_lints`",
78-
|dst| {
79-
for lint_mod in lints.iter().map(|l| &l.module).sorted().dedup() {
80-
writeln!(dst, "mod {lint_mod};").unwrap();
81-
}
82-
},
83-
),
84-
),
85-
("clippy_lints/src/declared_lints.rs", &mut |_, src, dst| {
86-
dst.push_str(GENERATED_FILE_COMMENT);
87-
dst.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
88-
for (module_name, lint_name) in lints.iter().map(|l| (&l.module, l.name.to_uppercase())).sorted() {
89-
writeln!(dst, " crate::{module_name}::{lint_name}_INFO,").unwrap();
90-
}
91-
dst.push_str("];\n");
92-
UpdateStatus::from_changed(src != dst)
93-
}),
94-
("clippy_lints/src/deprecated_lints.rs", &mut |_, src, dst| {
95-
let mut searcher = RustSearcher::new(src);
96-
assert!(
97-
searcher.find_token(Token::Ident("declare_with_version"))
98-
&& searcher.find_token(Token::Ident("declare_with_version")),
99-
"error reading deprecated lints"
100-
);
101-
dst.push_str(&src[..searcher.pos() as usize]);
102-
dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n");
103-
for lint in deprecated {
104-
write!(
105-
dst,
106-
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
107-
lint.version, lint.name, lint.reason,
108-
)
109-
.unwrap();
80+
"README.md",
81+
&mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
82+
write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
83+
}),
84+
);
85+
updater.update_file_checked(
86+
"cargo dev update_lints",
87+
update_mode,
88+
"book/src/README.md",
89+
&mut update_text_region_fn("[There are over ", " lints included in this crate!]", |dst| {
90+
write!(dst, "{}", round_to_fifty(lints.len())).unwrap();
91+
}),
92+
);
93+
updater.update_file_checked(
94+
"cargo dev update_lints",
95+
update_mode,
96+
"CHANGELOG.md",
97+
&mut update_text_region_fn(
98+
"<!-- begin autogenerated links to lint list -->\n",
99+
"<!-- end autogenerated links to lint list -->",
100+
|dst| {
101+
for lint in lints
102+
.iter()
103+
.map(|l| &*l.name)
104+
.chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
105+
.chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
106+
.sorted()
107+
{
108+
writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
110109
}
111-
dst.push_str(
112-
"]}\n\n\
110+
},
111+
),
112+
);
113+
updater.update_file_checked(
114+
"cargo dev update_lints",
115+
update_mode,
116+
"clippy_lints/src/deprecated_lints.rs",
117+
&mut |_, src, dst| {
118+
let mut searcher = RustSearcher::new(src);
119+
assert!(
120+
searcher.find_token(Token::Ident("declare_with_version"))
121+
&& searcher.find_token(Token::Ident("declare_with_version")),
122+
"error reading deprecated lints"
123+
);
124+
dst.push_str(&src[..searcher.pos() as usize]);
125+
dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n");
126+
for lint in deprecated {
127+
write!(
128+
dst,
129+
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
130+
lint.version, lint.name, lint.reason,
131+
)
132+
.unwrap();
133+
}
134+
dst.push_str(
135+
"]}\n\n\
113136
#[rustfmt::skip]\n\
114137
declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\
115138
",
116-
);
117-
for lint in renamed {
118-
write!(
119-
dst,
120-
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
121-
lint.version, lint.old_name, lint.new_name,
122-
)
123-
.unwrap();
124-
}
125-
dst.push_str("]}\n");
126-
UpdateStatus::from_changed(src != dst)
127-
}),
128-
("tests/ui/deprecated.rs", &mut |_, src, dst| {
129-
dst.push_str(GENERATED_FILE_COMMENT);
130-
for lint in deprecated {
131-
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
139+
);
140+
for lint in renamed {
141+
write!(
142+
dst,
143+
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
144+
lint.version, lint.old_name, lint.new_name,
145+
)
146+
.unwrap();
147+
}
148+
dst.push_str("]}\n");
149+
UpdateStatus::from_changed(src != dst)
150+
},
151+
);
152+
updater.update_file_checked(
153+
"cargo dev update_lints",
154+
update_mode,
155+
"tests/ui/deprecated.rs",
156+
&mut |_, src, dst| {
157+
dst.push_str(GENERATED_FILE_COMMENT);
158+
for lint in deprecated {
159+
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
160+
}
161+
dst.push_str("\nfn main() {}\n");
162+
UpdateStatus::from_changed(src != dst)
163+
},
164+
);
165+
updater.update_file_checked(
166+
"cargo dev update_lints",
167+
update_mode,
168+
"tests/ui/rename.rs",
169+
&mut move |_, src, dst| {
170+
let mut seen_lints = HashSet::new();
171+
dst.push_str(GENERATED_FILE_COMMENT);
172+
dst.push_str("#![allow(clippy::duplicated_attributes)]\n");
173+
for lint in renamed {
174+
if seen_lints.insert(&lint.new_name) {
175+
writeln!(dst, "#![allow({})]", lint.new_name).unwrap();
132176
}
133-
dst.push_str("\nfn main() {}\n");
134-
UpdateStatus::from_changed(src != dst)
135-
}),
136-
("tests/ui/rename.rs", &mut move |_, src, dst| {
137-
let mut seen_lints = HashSet::new();
138-
dst.push_str(GENERATED_FILE_COMMENT);
139-
dst.push_str("#![allow(clippy::duplicated_attributes)]\n");
140-
for lint in renamed {
141-
if seen_lints.insert(&lint.new_name) {
142-
writeln!(dst, "#![allow({})]", lint.new_name).unwrap();
143-
}
177+
}
178+
seen_lints.clear();
179+
for lint in renamed {
180+
if seen_lints.insert(&lint.old_name) {
181+
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
144182
}
145-
seen_lints.clear();
146-
for lint in renamed {
147-
if seen_lints.insert(&lint.old_name) {
148-
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
183+
}
184+
dst.push_str("\nfn main() {}\n");
185+
UpdateStatus::from_changed(src != dst)
186+
},
187+
);
188+
for c in Crate::all() {
189+
updater.update_file_checked(
190+
"cargo dev update_lints",
191+
update_mode,
192+
c.crate_root_path(),
193+
&mut update_text_region_fn(
194+
"// begin lints modules, do not remove this comment, it’s used in `update_lints`\n",
195+
"// end lints modules, do not remove this comment, it’s used in `update_lints`",
196+
|dst| {
197+
for lint_mod in lints
198+
.iter()
199+
.filter(|l| l.def_crate == c)
200+
.map(|l| l.module.split_once("::").map_or(&*l.module, |x| x.0))
201+
.sorted()
202+
.dedup()
203+
{
204+
writeln!(dst, "mod {lint_mod};").unwrap();
149205
}
206+
},
207+
),
208+
);
209+
updater.update_file_checked(
210+
"cargo dev update_lints",
211+
update_mode,
212+
c.declared_lints_path(),
213+
&mut |_, src, dst| {
214+
dst.push_str(GENERATED_FILE_COMMENT);
215+
dst.push_str("pub static LINTS: &[&crate::LintInfo] = &[\n");
216+
for (module_name, lint_name) in lints
217+
.iter()
218+
.filter(|l| l.def_crate == c)
219+
.map(|l| (&l.module, l.name.to_uppercase()))
220+
.sorted()
221+
{
222+
writeln!(dst, " crate::{module_name}::{lint_name}_INFO,").unwrap();
150223
}
151-
dst.push_str("\nfn main() {}\n");
224+
dst.push_str("];\n");
152225
UpdateStatus::from_changed(src != dst)
153-
}),
154-
],
155-
);
226+
},
227+
);
228+
}
156229
}
157230

158231
fn round_to_fifty(count: usize) -> usize {
@@ -167,6 +240,7 @@ pub struct Lint {
167240
pub module: String,
168241
pub path: PathBuf,
169242
pub declaration_range: Range<usize>,
243+
pub def_crate: Crate,
170244
}
171245

172246
pub struct DeprecatedLint {
@@ -186,13 +260,16 @@ pub struct RenamedLint {
186260
pub fn find_lint_decls() -> Vec<Lint> {
187261
let mut lints = Vec::with_capacity(1000);
188262
let mut contents = String::new();
189-
for (file, module) in read_src_with_module("clippy_lints/src".as_ref()) {
190-
parse_clippy_lint_decls(
191-
file.path(),
192-
File::open_read_to_cleared_string(file.path(), &mut contents),
193-
&module,
194-
&mut lints,
195-
);
263+
for c in Crate::all() {
264+
for (file, module) in read_src_with_module(c.src_path().as_ref()) {
265+
parse_clippy_lint_decls(
266+
file.path(),
267+
File::open_read_to_cleared_string(file.path(), &mut contents),
268+
c,
269+
&module,
270+
&mut lints,
271+
);
272+
}
196273
}
197274
lints.sort_by(|lhs, rhs| lhs.name.cmp(&rhs.name));
198275
lints
@@ -233,7 +310,7 @@ fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirE
233310
}
234311

235312
/// Parse a source file looking for `declare_clippy_lint` macro invocations.
236-
fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mut Vec<Lint>) {
313+
fn parse_clippy_lint_decls(path: &Path, contents: &str, def_crate: Crate, module: &str, lints: &mut Vec<Lint>) {
237314
#[allow(clippy::enum_glob_use)]
238315
use Token::*;
239316
#[rustfmt::skip]
@@ -257,6 +334,7 @@ fn parse_clippy_lint_decls(path: &Path, contents: &str, module: &str, lints: &mu
257334
module: module.into(),
258335
path: path.into(),
259336
declaration_range: start..searcher.pos() as usize,
337+
def_crate,
260338
});
261339
}
262340
}

clippy_dev/src/utils.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -309,21 +309,6 @@ impl FileUpdater {
309309
self.update_file_checked_inner(tool, mode, path.as_ref(), update);
310310
}
311311

312-
#[expect(clippy::type_complexity)]
313-
pub fn update_files_checked(
314-
&mut self,
315-
tool: &str,
316-
mode: UpdateMode,
317-
files: &mut [(
318-
impl AsRef<Path>,
319-
&mut dyn FnMut(&Path, &str, &mut String) -> UpdateStatus,
320-
)],
321-
) {
322-
for (path, update) in files {
323-
self.update_file_checked_inner(tool, mode, path.as_ref(), update);
324-
}
325-
}
326-
327312
pub fn update_file(
328313
&mut self,
329314
path: impl AsRef<Path>,

0 commit comments

Comments
 (0)