clippy_dev: Rename deprecate_lint module to edit_lints.
This commit is contained in:
parent
756e1bac6e
commit
d9fa6d9515
3 changed files with 218 additions and 5 deletions
213
clippy_dev/src/edit_lints.rs
Normal file
213
clippy_dev/src/edit_lints.rs
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
use crate::parse::{DeprecatedLint, Lint, ParseCx, RenamedLint};
|
||||
use crate::update_lints::generate_lint_files;
|
||||
use crate::utils::{UpdateMode, Version};
|
||||
use std::ffi::OsStr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
|
||||
/// Runs the `deprecate` command
|
||||
///
|
||||
/// This does the following:
|
||||
/// * Adds an entry to `deprecated_lints.rs`.
|
||||
/// * Removes the lint declaration (and the entire file if applicable)
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If a file path could not read from or written to
|
||||
pub fn deprecate<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, name: &'env str, reason: &'env str) {
|
||||
let mut lints = cx.find_lint_decls();
|
||||
let (mut deprecated_lints, renamed_lints) = cx.read_deprecated_lints();
|
||||
|
||||
let Some(lint) = lints.iter().find(|l| l.name == name) else {
|
||||
eprintln!("error: failed to find lint `{name}`");
|
||||
return;
|
||||
};
|
||||
|
||||
let prefixed_name = cx.str_buf.with(|buf| {
|
||||
buf.extend(["clippy::", name]);
|
||||
cx.arena.alloc_str(buf)
|
||||
});
|
||||
match deprecated_lints.binary_search_by(|x| x.name.cmp(prefixed_name)) {
|
||||
Ok(_) => {
|
||||
println!("`{name}` is already deprecated");
|
||||
return;
|
||||
},
|
||||
Err(idx) => deprecated_lints.insert(
|
||||
idx,
|
||||
DeprecatedLint {
|
||||
name: prefixed_name,
|
||||
reason,
|
||||
version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()),
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
let mod_path = {
|
||||
let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module));
|
||||
if mod_path.is_dir() {
|
||||
mod_path = mod_path.join("mod");
|
||||
}
|
||||
|
||||
mod_path.set_extension("rs");
|
||||
mod_path
|
||||
};
|
||||
|
||||
if remove_lint_declaration(name, &mod_path, &mut lints).unwrap_or(false) {
|
||||
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
|
||||
println!("info: `{name}` has successfully been deprecated");
|
||||
println!("note: you must run `cargo uitest` to update the test results");
|
||||
} else {
|
||||
eprintln!("error: lint not found");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uplift<'cx, 'env: 'cx>(cx: ParseCx<'cx>, clippy_version: Version, old_name: &'env str, new_name: &'env str) {
|
||||
let mut lints = cx.find_lint_decls();
|
||||
let (deprecated_lints, mut renamed_lints) = cx.read_deprecated_lints();
|
||||
|
||||
let Some(lint) = lints.iter().find(|l| l.name == old_name) else {
|
||||
eprintln!("error: failed to find lint `{old_name}`");
|
||||
return;
|
||||
};
|
||||
|
||||
let old_name_prefixed = cx.str_buf.with(|buf| {
|
||||
buf.extend(["clippy::", old_name]);
|
||||
cx.arena.alloc_str(buf)
|
||||
});
|
||||
for lint in &mut renamed_lints {
|
||||
if lint.new_name == old_name_prefixed {
|
||||
lint.new_name = new_name;
|
||||
}
|
||||
}
|
||||
match renamed_lints.binary_search_by(|x| x.old_name.cmp(old_name_prefixed)) {
|
||||
Ok(_) => {
|
||||
println!("`{old_name}` is already deprecated");
|
||||
return;
|
||||
},
|
||||
Err(idx) => renamed_lints.insert(
|
||||
idx,
|
||||
RenamedLint {
|
||||
old_name: old_name_prefixed,
|
||||
new_name,
|
||||
version: cx.str_buf.alloc_display(cx.arena, clippy_version.rust_display()),
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
let mod_path = {
|
||||
let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module));
|
||||
if mod_path.is_dir() {
|
||||
mod_path = mod_path.join("mod");
|
||||
}
|
||||
|
||||
mod_path.set_extension("rs");
|
||||
mod_path
|
||||
};
|
||||
|
||||
if remove_lint_declaration(old_name, &mod_path, &mut lints).unwrap_or(false) {
|
||||
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
|
||||
println!("info: `{old_name}` has successfully been uplifted");
|
||||
println!("note: you must run `cargo uitest` to update the test results");
|
||||
} else {
|
||||
eprintln!("error: lint not found");
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint<'_>>) -> io::Result<bool> {
|
||||
fn remove_lint(name: &str, lints: &mut Vec<Lint<'_>>) {
|
||||
lints.iter().position(|l| l.name == name).map(|pos| lints.remove(pos));
|
||||
}
|
||||
|
||||
fn remove_test_assets(name: &str) {
|
||||
let test_file_stem = format!("tests/ui/{name}");
|
||||
let path = Path::new(&test_file_stem);
|
||||
|
||||
// Some lints have their own directories, delete them
|
||||
if path.is_dir() {
|
||||
let _ = fs::remove_dir_all(path);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove all related test files
|
||||
let _ = fs::remove_file(path.with_extension("rs"));
|
||||
let _ = fs::remove_file(path.with_extension("stderr"));
|
||||
let _ = fs::remove_file(path.with_extension("fixed"));
|
||||
}
|
||||
|
||||
fn remove_impl_lint_pass(lint_name_upper: &str, content: &mut String) {
|
||||
let impl_lint_pass_start = content.find("impl_lint_pass!").unwrap_or_else(|| {
|
||||
content
|
||||
.find("declare_lint_pass!")
|
||||
.unwrap_or_else(|| panic!("failed to find `impl_lint_pass`"))
|
||||
});
|
||||
let mut impl_lint_pass_end = content[impl_lint_pass_start..]
|
||||
.find(']')
|
||||
.expect("failed to find `impl_lint_pass` terminator");
|
||||
|
||||
impl_lint_pass_end += impl_lint_pass_start;
|
||||
if let Some(lint_name_pos) = content[impl_lint_pass_start..impl_lint_pass_end].find(lint_name_upper) {
|
||||
let mut lint_name_end = impl_lint_pass_start + (lint_name_pos + lint_name_upper.len());
|
||||
for c in content[lint_name_end..impl_lint_pass_end].chars() {
|
||||
// Remove trailing whitespace
|
||||
if c == ',' || c.is_whitespace() {
|
||||
lint_name_end += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
content.replace_range(impl_lint_pass_start + lint_name_pos..lint_name_end, "");
|
||||
}
|
||||
}
|
||||
|
||||
if path.exists()
|
||||
&& let Some(lint) = lints.iter().find(|l| l.name == name)
|
||||
{
|
||||
if lint.module == name {
|
||||
// The lint name is the same as the file, we can just delete the entire file
|
||||
fs::remove_file(path)?;
|
||||
} else {
|
||||
// We can't delete the entire file, just remove the declaration
|
||||
|
||||
if let Some(Some("mod.rs")) = path.file_name().map(OsStr::to_str) {
|
||||
// Remove clippy_lints/src/some_mod/some_lint.rs
|
||||
let mut lint_mod_path = path.to_path_buf();
|
||||
lint_mod_path.set_file_name(name);
|
||||
lint_mod_path.set_extension("rs");
|
||||
|
||||
let _ = fs::remove_file(lint_mod_path);
|
||||
}
|
||||
|
||||
let mut content =
|
||||
fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy()));
|
||||
|
||||
eprintln!(
|
||||
"warn: you will have to manually remove any code related to `{name}` from `{}`",
|
||||
path.display()
|
||||
);
|
||||
|
||||
assert!(
|
||||
content[lint.declaration_range].contains(&name.to_uppercase()),
|
||||
"error: `{}` does not contain lint `{}`'s declaration",
|
||||
path.display(),
|
||||
lint.name
|
||||
);
|
||||
|
||||
// Remove lint declaration (declare_clippy_lint!)
|
||||
content.replace_range(lint.declaration_range, "");
|
||||
|
||||
// Remove the module declaration (mod xyz;)
|
||||
let mod_decl = format!("\nmod {name};");
|
||||
content = content.replacen(&mod_decl, "", 1);
|
||||
|
||||
remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content);
|
||||
fs::write(path, content).unwrap_or_else(|_| panic!("failed to write to `{}`", path.to_string_lossy()));
|
||||
}
|
||||
|
||||
remove_test_assets(name);
|
||||
remove_lint(name, lints);
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
|
@ -23,8 +23,8 @@ extern crate rustc_arena;
|
|||
extern crate rustc_driver;
|
||||
extern crate rustc_lexer;
|
||||
|
||||
pub mod deprecate_lint;
|
||||
pub mod dogfood;
|
||||
pub mod edit_lints;
|
||||
pub mod fmt;
|
||||
pub mod lint;
|
||||
pub mod new_lint;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use clippy_dev::{
|
||||
ClippyInfo, UpdateMode, deprecate_lint, dogfood, fmt, lint, new_lint, new_parse_cx, release, rename_lint, serve,
|
||||
setup, sync, update_lints,
|
||||
ClippyInfo, UpdateMode, dogfood, edit_lints, fmt, lint, new_lint, new_parse_cx, release, rename_lint, serve, setup,
|
||||
sync, update_lints,
|
||||
};
|
||||
use std::env;
|
||||
|
||||
|
|
@ -78,10 +78,10 @@ fn main() {
|
|||
rename_lint::rename(cx, clippy.version, &old_name, &new_name);
|
||||
}),
|
||||
DevCommand::Uplift { old_name, new_name } => new_parse_cx(|cx| {
|
||||
deprecate_lint::uplift(cx, clippy.version, &old_name, new_name.as_deref().unwrap_or(&old_name));
|
||||
edit_lints::uplift(cx, clippy.version, &old_name, new_name.as_deref().unwrap_or(&old_name));
|
||||
}),
|
||||
DevCommand::Deprecate { name, reason } => {
|
||||
new_parse_cx(|cx| deprecate_lint::deprecate(cx, clippy.version, &name, &reason));
|
||||
new_parse_cx(|cx| edit_lints::deprecate(cx, clippy.version, &name, &reason));
|
||||
},
|
||||
DevCommand::Sync(SyncCommand { subcommand }) => match subcommand {
|
||||
SyncSubcommand::UpdateNightly => sync::update_nightly(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue