Skip to content

Commit 3948a62

Browse files
committed
Prepare to split lints into multiple crates
* Move `declare_clippy_lint` to it's own crate * Move lint/group registration into the driver * Make `dev update_lints` handle multiple lint crates
1 parent 5dccb10 commit 3948a62

File tree

345 files changed

+809
-432
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

345 files changed

+809
-432
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ path = "src/driver.rs"
2424
clippy_config = { path = "clippy_config" }
2525
clippy_lints = { path = "clippy_lints" }
2626
clippy_utils = { path = "clippy_utils" }
27+
declare_clippy_lint = { path = "declare_clippy_lint" }
2728
rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" }
2829
clippy_lints_internal = { path = "clippy_lints_internal", optional = true }
2930
tempfile = { version = "3.20", optional = true }

clippy_dev/src/update_lints.rs

Lines changed: 172 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use crate::utils::{
44
use itertools::Itertools;
55
use std::collections::HashSet;
66
use std::fmt::Write;
7+
use std::fs;
78
use std::ops::Range;
8-
use std::path::{Path, PathBuf};
9+
use std::path::{self, Path, PathBuf};
910
use walkdir::{DirEntry, WalkDir};
1011

1112
const GENERATED_FILE_COMMENT: &str = "// This file was generated by `cargo dev update_lints`.\n\
@@ -36,123 +37,168 @@ pub fn generate_lint_files(
3637
deprecated: &[DeprecatedLint],
3738
renamed: &[RenamedLint],
3839
) {
39-
FileUpdater::default().update_files_checked(
40+
let mut updater = FileUpdater::default();
41+
updater.update_file_checked(
4042
"cargo dev update_lints",
4143
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();
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+
updater.update_file_checked(
50+
"cargo dev update_lints",
51+
update_mode,
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+
updater.update_file_checked(
58+
"cargo dev update_lints",
59+
update_mode,
60+
"CHANGELOG.md",
61+
&mut update_text_region_fn(
62+
"<!-- begin autogenerated links to lint list -->\n",
63+
"<!-- end autogenerated links to lint list -->",
64+
|dst| {
65+
for lint in lints
66+
.iter()
67+
.map(|l| &*l.name)
68+
.chain(deprecated.iter().filter_map(|l| l.name.strip_prefix("clippy::")))
69+
.chain(renamed.iter().filter_map(|l| l.old_name.strip_prefix("clippy::")))
70+
.sorted()
71+
{
72+
writeln!(dst, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
11073
}
111-
dst.push_str(
112-
"]}\n\n\
74+
},
75+
),
76+
);
77+
updater.update_file_checked(
78+
"cargo dev update_lints",
79+
update_mode,
80+
"clippy_lints/src/deprecated_lints.rs",
81+
&mut |_, src, dst| {
82+
let mut searcher = RustSearcher::new(src);
83+
assert!(
84+
searcher.find_token(Token::Ident("declare_with_version"))
85+
&& searcher.find_token(Token::Ident("declare_with_version")),
86+
"error reading deprecated lints"
87+
);
88+
dst.push_str(&src[..searcher.pos() as usize]);
89+
dst.push_str("! { DEPRECATED(DEPRECATED_VERSION) = [\n");
90+
for lint in deprecated {
91+
write!(
92+
dst,
93+
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
94+
lint.version, lint.name, lint.reason,
95+
)
96+
.unwrap();
97+
}
98+
dst.push_str(
99+
"]}\n\n\
113100
#[rustfmt::skip]\n\
114101
declare_with_version! { RENAMED(RENAMED_VERSION) = [\n\
115102
",
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();
103+
);
104+
for lint in renamed {
105+
write!(
106+
dst,
107+
" #[clippy::version = \"{}\"]\n (\"{}\", \"{}\"),\n",
108+
lint.version, lint.old_name, lint.new_name,
109+
)
110+
.unwrap();
111+
}
112+
dst.push_str("]}\n");
113+
UpdateStatus::from_changed(src != dst)
114+
},
115+
);
116+
updater.update_file_checked(
117+
"cargo dev update_lints",
118+
update_mode,
119+
"tests/ui/deprecated.rs",
120+
&mut |_, src, dst| {
121+
dst.push_str(GENERATED_FILE_COMMENT);
122+
for lint in deprecated {
123+
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.name, lint.name).unwrap();
124+
}
125+
dst.push_str("\nfn main() {}\n");
126+
UpdateStatus::from_changed(src != dst)
127+
},
128+
);
129+
updater.update_file_checked(
130+
"cargo dev update_lints",
131+
update_mode,
132+
"tests/ui/rename.rs",
133+
&mut move |_, src, dst| {
134+
let mut seen_lints = HashSet::new();
135+
dst.push_str(GENERATED_FILE_COMMENT);
136+
dst.push_str("#![allow(clippy::duplicated_attributes)]\n");
137+
for lint in renamed {
138+
if seen_lints.insert(&lint.new_name) {
139+
writeln!(dst, "#![allow({})]", lint.new_name).unwrap();
124140
}
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();
141+
}
142+
seen_lints.clear();
143+
for lint in renamed {
144+
if seen_lints.insert(&lint.old_name) {
145+
writeln!(dst, "#![warn({})] //~ ERROR: lint `{}`", lint.old_name, lint.old_name).unwrap();
132146
}
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();
147+
}
148+
dst.push_str("\nfn main() {}\n");
149+
UpdateStatus::from_changed(src != dst)
150+
},
151+
);
152+
for (crate_name, lints) in lints.iter().into_group_map_by(|&l| {
153+
let Some(path::Component::Normal(name)) = l.path.components().next() else {
154+
// All paths should start with `{crate_name}/src` when parsed from `find_lint_decls`
155+
panic!("internal error: can't read crate name from path `{}`", l.path.display());
156+
};
157+
name
158+
}) {
159+
updater.update_file_checked(
160+
"cargo dev update_lints",
161+
update_mode,
162+
Path::new(crate_name).join("src/lib.rs"),
163+
&mut update_text_region_fn(
164+
"// begin lints modules, do not remove this comment, it’s used in `update_lints`\n",
165+
"// end lints modules, do not remove this comment, it’s used in `update_lints`",
166+
|dst| {
167+
for lint_mod in lints
168+
.iter()
169+
.filter(|l| !l.module.is_empty())
170+
.map(|l| l.module.split_once("::").map_or(&*l.module, |x| x.0))
171+
.sorted()
172+
.dedup()
173+
{
174+
writeln!(dst, "mod {lint_mod};").unwrap();
143175
}
144-
}
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();
176+
},
177+
),
178+
);
179+
updater.update_file_checked(
180+
"cargo dev update_lints",
181+
update_mode,
182+
Path::new(crate_name).join("src/declared_lints.rs"),
183+
&mut |_, src, dst| {
184+
dst.push_str(GENERATED_FILE_COMMENT);
185+
dst.push_str("pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[\n");
186+
for (module_path, lint_name) in lints
187+
.iter()
188+
.map(|l| (&l.module, l.name.to_uppercase()))
189+
.sorted()
190+
{
191+
if module_path.is_empty() {
192+
writeln!(dst, " crate::{lint_name}_INFO,").unwrap();
193+
} else {
194+
writeln!(dst, " crate::{module_path}::{lint_name}_INFO,").unwrap();
149195
}
150196
}
151-
dst.push_str("\nfn main() {}\n");
197+
dst.push_str("];\n");
152198
UpdateStatus::from_changed(src != dst)
153-
}),
154-
],
155-
);
199+
},
200+
);
201+
}
156202
}
157203

158204
fn round_to_fifty(count: usize) -> usize {
@@ -186,13 +232,25 @@ pub struct RenamedLint {
186232
pub fn find_lint_decls() -> Vec<Lint> {
187233
let mut lints = Vec::with_capacity(1000);
188234
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-
);
235+
for e in expect_action(fs::read_dir("."), ErrAction::Read, ".") {
236+
let e = expect_action(e, ErrAction::Read, ".");
237+
if !expect_action(e.file_type(), ErrAction::Read, ".").is_dir() {
238+
continue;
239+
}
240+
let Ok(mut name) = e.file_name().into_string() else {
241+
continue;
242+
};
243+
if name.starts_with("clippy_lints") && name != "clippy_lints_internal" {
244+
name.push_str("/src");
245+
for (file, module) in read_src_with_module(name.as_ref()) {
246+
parse_clippy_lint_decls(
247+
file.path(),
248+
File::open_read_to_cleared_string(file.path(), &mut contents),
249+
&module,
250+
&mut lints,
251+
);
252+
}
253+
}
196254
}
197255
lints.sort_by(|lhs, rhs| lhs.name.cmp(&rhs.name));
198256
lints
@@ -204,7 +262,7 @@ fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator<Item = (DirE
204262
let e = expect_action(e, ErrAction::Read, src_root);
205263
let path = e.path().as_os_str().as_encoded_bytes();
206264
if let Some(path) = path.strip_suffix(b".rs")
207-
&& let Some(path) = path.get("clippy_lints/src/".len()..)
265+
&& let Some(path) = path.get(src_root.as_os_str().len() + 1..)
208266
{
209267
if path == b"lib" {
210268
Some((e, String::new()))

clippy_dev/src/utils.rs

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

386-
#[expect(clippy::type_complexity)]
387-
pub fn update_files_checked(
388-
&mut self,
389-
tool: &str,
390-
mode: UpdateMode,
391-
files: &mut [(
392-
impl AsRef<Path>,
393-
&mut dyn FnMut(&Path, &str, &mut String) -> UpdateStatus,
394-
)],
395-
) {
396-
for (path, update) in files {
397-
self.update_file_checked_inner(tool, mode, path.as_ref(), update);
398-
}
399-
}
400-
401386
pub fn update_file(
402387
&mut self,
403388
path: impl AsRef<Path>,

clippy_lints/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ arrayvec = { version = "0.7", default-features = false }
1313
cargo_metadata = "0.18"
1414
clippy_config = { path = "../clippy_config" }
1515
clippy_utils = { path = "../clippy_utils" }
16+
declare_clippy_lint = { path = "../declare_clippy_lint" }
1617
itertools = "0.12"
1718
quine-mc_cluskey = "0.2"
1819
regex-syntax = "0.8"

clippy_lints/src/absolute_paths.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clippy_config::Conf;
22
use clippy_utils::diagnostics::span_lint;
33
use clippy_utils::is_from_proc_macro;
4+
use declare_clippy_lint::declare_clippy_lint;
45
use rustc_data_structures::fx::FxHashSet;
56
use rustc_hir::def::{DefKind, Res};
67
use rustc_hir::def_id::{CRATE_DEF_INDEX, DefId};

clippy_lints/src/almost_complete_range.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use clippy_config::Conf;
22
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::msrvs::{self, MsrvStack};
44
use clippy_utils::source::{trim_span, walk_span_to_context};
5+
use declare_clippy_lint::declare_clippy_lint;
56
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
67
use rustc_errors::Applicability;
78
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};

clippy_lints/src/approx_const.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clippy_config::Conf;
22
use clippy_utils::diagnostics::span_lint_and_help;
33
use clippy_utils::msrvs::{self, Msrv};
4+
use declare_clippy_lint::declare_clippy_lint;
45
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
56
use rustc_attr_data_structures::RustcVersion;
67
use rustc_hir::{HirId, Lit};

clippy_lints/src/arbitrary_source_item_ordering.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use clippy_config::types::{
66
};
77
use clippy_utils::diagnostics::span_lint_and_note;
88
use clippy_utils::is_cfg_test;
9+
use declare_clippy_lint::declare_clippy_lint;
910
use rustc_attr_data_structures::AttributeKind;
1011
use rustc_hir::{
1112
AssocItemKind, Attribute, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind,

0 commit comments

Comments
 (0)