Skip to content

Commit b282bd7

Browse files
committed
Add rename_lint command
1 parent 9fe1aff commit b282bd7

File tree

6 files changed

+372
-217
lines changed

6 files changed

+372
-217
lines changed

clippy_dev/src/main.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ fn main() {
1818
if matches.is_present("print-only") {
1919
update_lints::print_lints();
2020
} else if matches.is_present("check") {
21-
update_lints::run(update_lints::UpdateMode::Check);
21+
update_lints::update(update_lints::UpdateMode::Check);
2222
} else {
23-
update_lints::run(update_lints::UpdateMode::Change);
23+
update_lints::update(update_lints::UpdateMode::Change);
2424
}
2525
},
2626
("new_lint", Some(matches)) => {
@@ -30,7 +30,7 @@ fn main() {
3030
matches.value_of("category"),
3131
matches.is_present("msrv"),
3232
) {
33-
Ok(_) => update_lints::run(update_lints::UpdateMode::Change),
33+
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
3434
Err(e) => eprintln!("Unable to create lint: {}", e),
3535
}
3636
},
@@ -59,6 +59,12 @@ fn main() {
5959
let filename = matches.value_of("filename").unwrap();
6060
lint::run(filename);
6161
},
62+
("rename_lint", Some(matches)) => {
63+
let old_name = matches.value_of("old_name").unwrap();
64+
let new_name = matches.value_of("new_name").unwrap();
65+
let uplift = matches.is_present("uplift");
66+
update_lints::rename(old_name, new_name, uplift);
67+
},
6268
_ => {},
6369
}
6470
}
@@ -232,5 +238,26 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
232238
.help("The path to a file to lint"),
233239
),
234240
)
241+
.subcommand(
242+
SubCommand::with_name("rename_lint")
243+
.about("Renames the given lint")
244+
.arg(
245+
Arg::with_name("old_name")
246+
.index(1)
247+
.required(true)
248+
.help("The name of the lint to rename"),
249+
)
250+
.arg(
251+
Arg::with_name("new_name")
252+
.index(2)
253+
.required(true)
254+
.help("The new name of the lint"),
255+
)
256+
.arg(
257+
Arg::with_name("uplift")
258+
.long("uplift")
259+
.help("This lint was uplifted into rustc"),
260+
),
261+
)
235262
.get_matches()
236263
}

clippy_dev/src/update_lints.rs

Lines changed: 145 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
44
use std::collections::{HashMap, HashSet};
55
use std::ffi::OsStr;
66
use std::fs;
7-
use std::path::Path;
8-
use walkdir::WalkDir;
7+
use std::path::{Path, PathBuf};
8+
use walkdir::{DirEntry, WalkDir};
99

1010
use crate::clippy_project_root;
1111

@@ -30,12 +30,19 @@ pub enum UpdateMode {
3030
/// # Panics
3131
///
3232
/// Panics if a file path could not read from or then written to
33-
#[allow(clippy::too_many_lines)]
34-
pub fn run(update_mode: UpdateMode) {
33+
pub fn update(update_mode: UpdateMode) {
3534
let (lints, deprecated_lints, renamed_lints) = gather_all();
35+
generate_lint_files(update_mode, &lints, &deprecated_lints, &renamed_lints);
36+
}
3637

37-
let internal_lints = Lint::internal_lints(&lints);
38-
let usable_lints = Lint::usable_lints(&lints);
38+
fn generate_lint_files(
39+
update_mode: UpdateMode,
40+
lints: &[Lint],
41+
deprecated_lints: &[DeprecatedLint],
42+
renamed_lints: &[RenamedLint],
43+
) {
44+
let internal_lints = Lint::internal_lints(lints);
45+
let usable_lints = Lint::usable_lints(lints);
3946
let mut sorted_usable_lints = usable_lints.clone();
4047
sorted_usable_lints.sort_by_key(|lint| lint.name.clone());
4148

@@ -87,7 +94,7 @@ pub fn run(update_mode: UpdateMode) {
8794
process_file(
8895
"clippy_lints/src/lib.deprecated.rs",
8996
update_mode,
90-
&gen_deprecated(&deprecated_lints),
97+
&gen_deprecated(deprecated_lints),
9198
);
9299

93100
let all_group_lints = usable_lints.iter().filter(|l| {
@@ -108,10 +115,10 @@ pub fn run(update_mode: UpdateMode) {
108115
);
109116
}
110117

111-
let content = gen_deprecated_lints_test(&deprecated_lints);
118+
let content = gen_deprecated_lints_test(deprecated_lints);
112119
process_file("tests/ui/deprecated.rs", update_mode, &content);
113120

114-
let content = gen_renamed_lints_test(&renamed_lints);
121+
let content = gen_renamed_lints_test(renamed_lints);
115122
process_file("tests/ui/rename.rs", update_mode, &content);
116123
}
117124

@@ -134,6 +141,117 @@ pub fn print_lints() {
134141
println!("there are {} lints", usable_lint_count);
135142
}
136143

144+
/// Runs the `rename_lint` command.
145+
///
146+
/// # Panics
147+
/// Panics for the following conditions:
148+
/// * If a file path could not read from or then written to
149+
/// * If either lint name has a prefix
150+
/// * If `old_name` doesn't name an existing lint.
151+
/// * If `old_name` names a deprecated or renamed lint.
152+
pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
153+
if let Some((prefix, _)) = old_name.split_once("::") {
154+
panic!("`{}` should not contain the `{}` prefix", old_name, prefix);
155+
}
156+
if let Some((prefix, _)) = new_name.split_once("::") {
157+
panic!("`{}` should not contain the `{}` prefix", new_name, prefix);
158+
}
159+
160+
let (mut lints, deprecated_lints, mut renamed_lints) = gather_all();
161+
let mut old_lint_index = None;
162+
let mut found_new_name = false;
163+
for (i, lint) in lints.iter().enumerate() {
164+
if lint.name == old_name {
165+
old_lint_index = Some(i);
166+
} else if lint.name == new_name {
167+
found_new_name = true;
168+
}
169+
}
170+
let old_lint_index = old_lint_index.unwrap_or_else(|| panic!("could not find lint `{}`", old_name));
171+
172+
let lint = RenamedLint {
173+
old_name: format!("clippy::{}", old_name),
174+
new_name: if uplift {
175+
new_name.into()
176+
} else {
177+
format!("clippy::{}", new_name)
178+
},
179+
};
180+
181+
// Renamed lints and deprecated lints shouldn't have been found in the lint list, but check just in
182+
// case.)
183+
assert!(
184+
renamed_lints.iter().any(|l| lint.old_name == l.old_name),
185+
"`{}` has already been renamed",
186+
old_name
187+
);
188+
assert!(
189+
deprecated_lints.iter().any(|l| lint.old_name == l.name),
190+
"`{}` has already been deprecated",
191+
old_name
192+
);
193+
194+
// Update all lint level attributes.
195+
for file in WalkDir::new(clippy_project_root())
196+
.into_iter()
197+
.map(Result::unwrap)
198+
.filter(|f| {
199+
let name = f.path().file_name();
200+
f.path().extension() == Some(OsStr::new("rs"))
201+
&& name != Some(OsStr::new("rename.rs"))
202+
&& name != Some(OsStr::new("renamed_lints.rs"))
203+
})
204+
{
205+
let path = file.path();
206+
let contents =
207+
fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e));
208+
if contents.contains(&lint.old_name) {
209+
fs::write(path, contents.replace(&lint.old_name, &lint.new_name).as_bytes())
210+
.unwrap_or_else(|e| panic!("Cannot write to `{}`: {}", path.display(), e));
211+
}
212+
}
213+
214+
renamed_lints.push(lint);
215+
renamed_lints.sort_by(|lhs, rhs| {
216+
lhs.new_name
217+
.starts_with("clippy::")
218+
.cmp(&rhs.new_name.starts_with("clippy::"))
219+
.reverse()
220+
.then_with(|| lhs.old_name.cmp(&rhs.old_name))
221+
});
222+
223+
if found_new_name {
224+
println!(
225+
"`{}` is already defined. Removal the old lint code in `clippy_lints` will have to be done manually",
226+
new_name
227+
);
228+
let contents = gen_renamed_lints_test(&renamed_lints);
229+
fs::write("tests/ui/rename.rs", contents.as_bytes())
230+
.unwrap_or_else(|e| panic!("error writing file `tests/ui/rename.rs`: {}", e));
231+
} else {
232+
// Update the lint struct name
233+
lints[old_lint_index].name = new_name.into();
234+
let old_name = old_name.to_uppercase();
235+
let new_name = new_name.to_uppercase();
236+
237+
for (_, file) in clippy_lints_src_files() {
238+
let path = file.path();
239+
let contents =
240+
fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e));
241+
if contents.contains(&old_name) {
242+
fs::write(path, contents.replace(&old_name, &new_name).as_bytes())
243+
.unwrap_or_else(|e| panic!("Cannot write to `{}`: {}", path.display(), e));
244+
}
245+
}
246+
247+
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
248+
}
249+
250+
let contents = gen_renamed_lints_list(&renamed_lints);
251+
fs::write("clippy_lints/src/renamed_lints.rs", contents.as_bytes())
252+
.unwrap_or_else(|e| panic!("error writing file `clippy_lints/src/renamed_lints.rs`: {}", e));
253+
}
254+
137255
fn round_to_fifty(count: usize) -> usize {
138256
count / 50 * 50
139257
}
@@ -324,19 +442,22 @@ fn gen_renamed_lints_test(lints: &[RenamedLint]) -> String {
324442
res
325443
}
326444

445+
fn gen_renamed_lints_list(lints: &[RenamedLint]) -> String {
446+
let mut res = String::from("pub static RENAMED_LINTS: &[(&str, &str)] = &[\n");
447+
for lint in lints {
448+
writeln!(res, " (\"{}\", \"{}\"),", lint.old_name, lint.new_name).unwrap();
449+
}
450+
res.push_str("];\n");
451+
res
452+
}
453+
327454
/// Gathers all lints defined in `clippy_lints/src`
328455
fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
329456
let mut lints = Vec::with_capacity(1000);
330457
let mut deprecated_lints = Vec::with_capacity(50);
331458
let mut renamed_lints = Vec::with_capacity(50);
332-
let root_path = clippy_project_root().join("clippy_lints/src");
333459

334-
for (rel_path, file) in WalkDir::new(&root_path)
335-
.into_iter()
336-
.map(Result::unwrap)
337-
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
338-
.map(|f| (f.path().strip_prefix(&root_path).unwrap().to_path_buf(), f))
339-
{
460+
for (rel_path, file) in clippy_lints_src_files() {
340461
let path = file.path();
341462
let contents =
342463
fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e));
@@ -363,6 +484,14 @@ fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
363484
(lints, deprecated_lints, renamed_lints)
364485
}
365486

487+
fn clippy_lints_src_files() -> impl Iterator<Item = (PathBuf, DirEntry)> {
488+
let root_path = clippy_project_root().join("clippy_lints/src");
489+
let iter = WalkDir::new(&root_path).into_iter();
490+
iter.map(Result::unwrap)
491+
.filter(|f| f.path().extension() == Some(OsStr::new("rs")))
492+
.map(move |f| (f.path().strip_prefix(&root_path).unwrap().to_path_buf(), f))
493+
}
494+
366495
macro_rules! match_tokens {
367496
($iter:ident, $($token:ident $({$($fields:tt)*})? $(($capture:ident))?)*) => {
368497
{

clippy_lints/src/renamed_lints.rs

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
11
pub static RENAMED_LINTS: &[(&str, &str)] = &[
2-
("clippy::stutter", "clippy::module_name_repetitions"),
3-
("clippy::new_without_default_derive", "clippy::new_without_default"),
4-
("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
5-
("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
6-
("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
7-
("clippy::box_vec", "clippy::box_collection"),
82
("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions"),
93
("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions"),
10-
("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"),
11-
("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"),
12-
("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"),
13-
("clippy::option_unwrap_used", "clippy::unwrap_used"),
14-
("clippy::result_unwrap_used", "clippy::unwrap_used"),
15-
("clippy::option_expect_used", "clippy::expect_used"),
16-
("clippy::result_expect_used", "clippy::expect_used"),
4+
("clippy::box_vec", "clippy::box_collection"),
5+
("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"),
6+
("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"),
7+
("clippy::disallowed_method", "clippy::disallowed_methods"),
8+
("clippy::disallowed_type", "clippy::disallowed_types"),
179
("clippy::for_loop_over_option", "clippy::for_loops_over_fallibles"),
1810
("clippy::for_loop_over_result", "clippy::for_loops_over_fallibles"),
1911
("clippy::identity_conversion", "clippy::useless_conversion"),
20-
("clippy::zero_width_space", "clippy::invisible_characters"),
21-
("clippy::single_char_push_str", "clippy::single_char_add_str"),
2212
("clippy::if_let_some_result", "clippy::match_result_ok"),
23-
("clippy::disallowed_type", "clippy::disallowed_types"),
24-
("clippy::disallowed_method", "clippy::disallowed_methods"),
13+
("clippy::new_without_default_derive", "clippy::new_without_default"),
14+
("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
15+
("clippy::option_expect_used", "clippy::expect_used"),
16+
("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"),
17+
("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"),
18+
("clippy::option_unwrap_used", "clippy::unwrap_used"),
2519
("clippy::ref_in_deref", "clippy::needless_borrow"),
20+
("clippy::result_expect_used", "clippy::expect_used"),
21+
("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"),
22+
("clippy::result_unwrap_used", "clippy::unwrap_used"),
23+
("clippy::single_char_push_str", "clippy::single_char_add_str"),
24+
("clippy::stutter", "clippy::module_name_repetitions"),
2625
("clippy::to_string_in_display", "clippy::recursive_format_impl"),
27-
// uplifted lints
28-
("clippy::invalid_ref", "invalid_value"),
29-
("clippy::into_iter_on_array", "array_into_iter"),
30-
("clippy::unused_label", "unused_labels"),
26+
("clippy::zero_width_space", "clippy::invisible_characters"),
3127
("clippy::drop_bounds", "drop_bounds"),
32-
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
33-
("clippy::panic_params", "non_fmt_panics"),
34-
("clippy::unknown_clippy_lints", "unknown_lints"),
28+
("clippy::into_iter_on_array", "array_into_iter"),
3529
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
30+
("clippy::invalid_ref", "invalid_value"),
3631
("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
32+
("clippy::panic_params", "non_fmt_panics"),
33+
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
34+
("clippy::unknown_clippy_lints", "unknown_lints"),
35+
("clippy::unused_label", "unused_labels"),
3736
];

0 commit comments

Comments
 (0)