fallout2: rework clippy_dev & _lints fmt inlining

* Inline format args where possible
* simplify a few complex macros into format str
* use formatdoc!() instead format!(indoc!(...))
This commit is contained in:
Yuri Astrakhan
2022-09-23 22:20:42 -04:00
parent c2d426650b
commit cc6b375cd3
9 changed files with 178 additions and 263 deletions

View File

@@ -82,16 +82,16 @@ pub fn run(check: bool, verbose: bool) {
fn output_err(err: CliError) { fn output_err(err: CliError) {
match err { match err {
CliError::CommandFailed(command, stderr) => { CliError::CommandFailed(command, stderr) => {
eprintln!("error: A command failed! `{}`\nstderr: {}", command, stderr); eprintln!("error: A command failed! `{command}`\nstderr: {stderr}");
}, },
CliError::IoError(err) => { CliError::IoError(err) => {
eprintln!("error: {}", err); eprintln!("error: {err}");
}, },
CliError::RustfmtNotInstalled => { CliError::RustfmtNotInstalled => {
eprintln!("error: rustfmt nightly is not installed."); eprintln!("error: rustfmt nightly is not installed.");
}, },
CliError::WalkDirError(err) => { CliError::WalkDirError(err) => {
eprintln!("error: {}", err); eprintln!("error: {err}");
}, },
CliError::IntellijSetupActive => { CliError::IntellijSetupActive => {
eprintln!( eprintln!(

View File

@@ -1,5 +1,5 @@
use crate::clippy_project_root; use crate::clippy_project_root;
use indoc::{indoc, writedoc}; use indoc::{formatdoc, writedoc};
use std::fmt::Write as _; use std::fmt::Write as _;
use std::fs::{self, OpenOptions}; use std::fs::{self, OpenOptions};
use std::io::prelude::*; use std::io::prelude::*;
@@ -23,7 +23,7 @@ impl<T> Context for io::Result<T> {
match self { match self {
Ok(t) => Ok(t), Ok(t) => Ok(t),
Err(e) => { Err(e) => {
let message = format!("{}: {}", text.as_ref(), e); let message = format!("{}: {e}", text.as_ref());
Err(io::Error::new(ErrorKind::Other, message)) Err(io::Error::new(ErrorKind::Other, message))
}, },
} }
@@ -72,7 +72,7 @@ fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
let lint_contents = get_lint_file_contents(lint, enable_msrv); let lint_contents = get_lint_file_contents(lint, enable_msrv);
let lint_path = format!("clippy_lints/src/{}.rs", lint.name); let lint_path = format!("clippy_lints/src/{}.rs", lint.name);
write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes())?; write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes())?;
println!("Generated lint file: `{}`", lint_path); println!("Generated lint file: `{lint_path}`");
Ok(()) Ok(())
} }
@@ -86,7 +86,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
path.push("src"); path.push("src");
fs::create_dir(&path)?; fs::create_dir(&path)?;
let header = format!("// compile-flags: --crate-name={}", lint_name); let header = format!("// compile-flags: --crate-name={lint_name}");
write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?; write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?;
Ok(()) Ok(())
@@ -106,7 +106,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
let test_contents = get_test_file_contents(lint.name, None); let test_contents = get_test_file_contents(lint.name, None);
write_file(lint.project_root.join(&test_path), test_contents)?; write_file(lint.project_root.join(&test_path), test_contents)?;
println!("Generated test file: `{}`", test_path); println!("Generated test file: `{test_path}`");
} }
Ok(()) Ok(())
@@ -184,38 +184,36 @@ pub(crate) fn get_stabilization_version() -> String {
} }
fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String { fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
let mut contents = format!( let mut contents = formatdoc!(
indoc! {" r#"
#![allow(unused)] #![allow(unused)]
#![warn(clippy::{})] #![warn(clippy::{lint_name})]
fn main() {{ fn main() {{
// test code goes here // test code goes here
}} }}
"}, "#
lint_name
); );
if let Some(header) = header_commands { if let Some(header) = header_commands {
contents = format!("{}\n{}", header, contents); contents = format!("{header}\n{contents}");
} }
contents contents
} }
fn get_manifest_contents(lint_name: &str, hint: &str) -> String { fn get_manifest_contents(lint_name: &str, hint: &str) -> String {
format!( formatdoc!(
indoc! {r#" r#"
# {} # {hint}
[package] [package]
name = "{}" name = "{lint_name}"
version = "0.1.0" version = "0.1.0"
publish = false publish = false
[workspace] [workspace]
"#}, "#
hint, lint_name
) )
} }
@@ -236,38 +234,32 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
let name_upper = lint_name.to_uppercase(); let name_upper = lint_name.to_uppercase();
result.push_str(&if enable_msrv { result.push_str(&if enable_msrv {
format!( formatdoc!(
indoc! {" r#"
use clippy_utils::msrvs; use clippy_utils::msrvs;
{pass_import} {pass_import}
use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; use rustc_lint::{{{context_import}, {pass_type}, LintContext}};
use rustc_semver::RustcVersion; use rustc_semver::RustcVersion;
use rustc_session::{{declare_tool_lint, impl_lint_pass}}; use rustc_session::{{declare_tool_lint, impl_lint_pass}};
"}, "#
pass_type = pass_type,
pass_import = pass_import,
context_import = context_import,
) )
} else { } else {
format!( formatdoc!(
indoc! {" r#"
{pass_import} {pass_import}
use rustc_lint::{{{context_import}, {pass_type}}}; use rustc_lint::{{{context_import}, {pass_type}}};
use rustc_session::{{declare_lint_pass, declare_tool_lint}}; use rustc_session::{{declare_lint_pass, declare_tool_lint}};
"}, "#
pass_import = pass_import,
pass_type = pass_type,
context_import = context_import
) )
}); });
let _ = write!(result, "{}", get_lint_declaration(&name_upper, category)); let _ = write!(result, "{}", get_lint_declaration(&name_upper, category));
result.push_str(&if enable_msrv { result.push_str(&if enable_msrv {
format!( formatdoc!(
indoc! {" r#"
pub struct {name_camel} {{ pub struct {name_camel} {{
msrv: Option<RustcVersion>, msrv: Option<RustcVersion>,
}} }}
@@ -288,24 +280,15 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
// TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed. // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
// TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`. // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
// TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs` // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
"}, "#
pass_type = pass_type,
pass_lifetimes = pass_lifetimes,
name_upper = name_upper,
name_camel = name_camel,
context_import = context_import,
) )
} else { } else {
format!( formatdoc!(
indoc! {" r#"
declare_lint_pass!({name_camel} => [{name_upper}]); declare_lint_pass!({name_camel} => [{name_upper}]);
impl {pass_type}{pass_lifetimes} for {name_camel} {{}} impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
"}, "#
pass_type = pass_type,
pass_lifetimes = pass_lifetimes,
name_upper = name_upper,
name_camel = name_camel,
) )
}); });
@@ -313,8 +296,8 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
} }
fn get_lint_declaration(name_upper: &str, category: &str) -> String { fn get_lint_declaration(name_upper: &str, category: &str) -> String {
format!( formatdoc!(
indoc! {r#" r#"
declare_clippy_lint! {{ declare_clippy_lint! {{
/// ### What it does /// ### What it does
/// ///
@@ -328,15 +311,13 @@ fn get_lint_declaration(name_upper: &str, category: &str) -> String {
/// ```rust /// ```rust
/// // example code which does not raise clippy warning /// // example code which does not raise clippy warning
/// ``` /// ```
#[clippy::version = "{version}"] #[clippy::version = "{}"]
pub {name_upper}, pub {name_upper},
{category}, {category},
"default lint description" "default lint description"
}} }}
"#}, "#,
version = get_stabilization_version(), get_stabilization_version(),
name_upper = name_upper,
category = category,
) )
} }
@@ -350,7 +331,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
_ => {}, _ => {},
} }
let ty_dir = lint.project_root.join(format!("clippy_lints/src/{}", ty)); let ty_dir = lint.project_root.join(format!("clippy_lints/src/{ty}"));
assert!( assert!(
ty_dir.exists() && ty_dir.is_dir(), ty_dir.exists() && ty_dir.is_dir(),
"Directory `{}` does not exist!", "Directory `{}` does not exist!",
@@ -410,10 +391,10 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
} }
write_file(lint_file_path.as_path(), lint_file_contents)?; write_file(lint_file_path.as_path(), lint_file_contents)?;
println!("Generated lint file: `clippy_lints/src/{}/{}.rs`", ty, lint.name); println!("Generated lint file: `clippy_lints/src/{ty}/{}.rs`", lint.name);
println!( println!(
"Be sure to add a call to `{}::check` in `clippy_lints/src/{}/mod.rs`!", "Be sure to add a call to `{}::check` in `clippy_lints/src/{ty}/mod.rs`!",
lint.name, ty lint.name
); );
Ok(()) Ok(())
@@ -540,7 +521,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
.chain(std::iter::once(&*lint_name_upper)) .chain(std::iter::once(&*lint_name_upper))
.filter(|s| !s.is_empty()) .filter(|s| !s.is_empty())
{ {
let _ = write!(new_arr_content, "\n {},", ident); let _ = write!(new_arr_content, "\n {ident},");
} }
new_arr_content.push('\n'); new_arr_content.push('\n');

View File

@@ -10,8 +10,8 @@ use std::time::{Duration, SystemTime};
/// Panics if the python commands could not be spawned /// Panics if the python commands could not be spawned
pub fn run(port: u16, lint: Option<&String>) -> ! { pub fn run(port: u16, lint: Option<&String>) -> ! {
let mut url = Some(match lint { let mut url = Some(match lint {
None => format!("http://localhost:{}", port), None => format!("http://localhost:{port}"),
Some(lint) => format!("http://localhost:{}/#{}", port, lint), Some(lint) => format!("http://localhost:{port}/#{lint}"),
}); });
loop { loop {

View File

@@ -30,10 +30,7 @@ pub fn install_hook(force_override: bool) {
println!("info: the hook can be removed with `cargo dev remove git-hook`"); println!("info: the hook can be removed with `cargo dev remove git-hook`");
println!("git hook successfully installed"); println!("git hook successfully installed");
}, },
Err(err) => eprintln!( Err(err) => eprintln!("error: unable to copy `{HOOK_SOURCE_FILE}` to `{HOOK_TARGET_FILE}` ({err})"),
"error: unable to copy `{}` to `{}` ({})",
HOOK_SOURCE_FILE, HOOK_TARGET_FILE, err
),
} }
} }
@@ -77,7 +74,7 @@ pub fn remove_hook() {
fn delete_git_hook_file(path: &Path) -> bool { fn delete_git_hook_file(path: &Path) -> bool {
if let Err(err) = fs::remove_file(path) { if let Err(err) = fs::remove_file(path) {
eprintln!("error: unable to delete existing pre-commit git hook ({})", err); eprintln!("error: unable to delete existing pre-commit git hook ({err})");
false false
} else { } else {
true true

View File

@@ -60,7 +60,7 @@ fn check_and_get_rustc_dir(rustc_path: &str) -> Result<PathBuf, ()> {
path = absolute_path; path = absolute_path;
}, },
Err(err) => { Err(err) => {
eprintln!("error: unable to get the absolute path of rustc ({})", err); eprintln!("error: unable to get the absolute path of rustc ({err})");
return Err(()); return Err(());
}, },
}; };
@@ -103,14 +103,14 @@ fn inject_deps_into_project(rustc_source_dir: &Path, project: &ClippyProjectInfo
fn read_project_file(file_path: &str) -> Result<String, ()> { fn read_project_file(file_path: &str) -> Result<String, ()> {
let path = Path::new(file_path); let path = Path::new(file_path);
if !path.exists() { if !path.exists() {
eprintln!("error: unable to find the file `{}`", file_path); eprintln!("error: unable to find the file `{file_path}`");
return Err(()); return Err(());
} }
match fs::read_to_string(path) { match fs::read_to_string(path) {
Ok(content) => Ok(content), Ok(content) => Ok(content),
Err(err) => { Err(err) => {
eprintln!("error: the file `{}` could not be read ({})", file_path, err); eprintln!("error: the file `{file_path}` could not be read ({err})");
Err(()) Err(())
}, },
} }
@@ -124,10 +124,7 @@ fn inject_deps_into_manifest(
) -> std::io::Result<()> { ) -> std::io::Result<()> {
// do not inject deps if we have already done so // do not inject deps if we have already done so
if cargo_toml.contains(RUSTC_PATH_SECTION) { if cargo_toml.contains(RUSTC_PATH_SECTION) {
eprintln!( eprintln!("warn: dependencies are already setup inside {manifest_path}, skipping file");
"warn: dependencies are already setup inside {}, skipping file",
manifest_path
);
return Ok(()); return Ok(());
} }
@@ -142,11 +139,7 @@ fn inject_deps_into_manifest(
let new_deps = extern_crates.map(|dep| { let new_deps = extern_crates.map(|dep| {
// format the dependencies that are going to be put inside the Cargo.toml // format the dependencies that are going to be put inside the Cargo.toml
format!( format!("{dep} = {{ path = \"{}/{dep}\" }}\n", rustc_source_dir.display())
"{dep} = {{ path = \"{source_path}/{dep}\" }}\n",
dep = dep,
source_path = rustc_source_dir.display()
)
}); });
// format a new [dependencies]-block with the new deps we need to inject // format a new [dependencies]-block with the new deps we need to inject
@@ -163,11 +156,11 @@ fn inject_deps_into_manifest(
// etc // etc
let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1); let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);
// println!("{}", new_manifest); // println!("{new_manifest}");
let mut file = File::create(manifest_path)?; let mut file = File::create(manifest_path)?;
file.write_all(new_manifest.as_bytes())?; file.write_all(new_manifest.as_bytes())?;
println!("info: successfully setup dependencies inside {}", manifest_path); println!("info: successfully setup dependencies inside {manifest_path}");
Ok(()) Ok(())
} }
@@ -214,8 +207,8 @@ fn remove_rustc_src_from_project(project: &ClippyProjectInfo) -> bool {
}, },
Err(err) => { Err(err) => {
eprintln!( eprintln!(
"error: unable to open file `{}` to remove rustc dependencies for {} ({})", "error: unable to open file `{}` to remove rustc dependencies for {} ({err})",
project.cargo_file, project.name, err project.cargo_file, project.name
); );
false false
}, },

View File

@@ -17,10 +17,7 @@ pub fn install_tasks(force_override: bool) {
println!("info: the task file can be removed with `cargo dev remove vscode-tasks`"); println!("info: the task file can be removed with `cargo dev remove vscode-tasks`");
println!("vscode tasks successfully installed"); println!("vscode tasks successfully installed");
}, },
Err(err) => eprintln!( Err(err) => eprintln!("error: unable to copy `{TASK_SOURCE_FILE}` to `{TASK_TARGET_FILE}` ({err})"),
"error: unable to copy `{}` to `{}` ({})",
TASK_SOURCE_FILE, TASK_TARGET_FILE, err
),
} }
} }
@@ -44,23 +41,17 @@ fn check_install_precondition(force_override: bool) -> bool {
return delete_vs_task_file(path); return delete_vs_task_file(path);
} }
eprintln!( eprintln!("error: there is already a `task.json` file inside the `{VSCODE_DIR}` directory");
"error: there is already a `task.json` file inside the `{}` directory",
VSCODE_DIR
);
println!("info: use the `--force-override` flag to override the existing `task.json` file"); println!("info: use the `--force-override` flag to override the existing `task.json` file");
return false; return false;
} }
} else { } else {
match fs::create_dir(vs_dir_path) { match fs::create_dir(vs_dir_path) {
Ok(_) => { Ok(_) => {
println!("info: created `{}` directory for clippy", VSCODE_DIR); println!("info: created `{VSCODE_DIR}` directory for clippy");
}, },
Err(err) => { Err(err) => {
eprintln!( eprintln!("error: the task target directory `{VSCODE_DIR}` could not be created ({err})");
"error: the task target directory `{}` could not be created ({})",
VSCODE_DIR, err
);
}, },
} }
} }
@@ -82,7 +73,7 @@ pub fn remove_tasks() {
fn delete_vs_task_file(path: &Path) -> bool { fn delete_vs_task_file(path: &Path) -> bool {
if let Err(err) = fs::remove_file(path) { if let Err(err) = fs::remove_file(path) {
eprintln!("error: unable to delete the existing `tasks.json` file ({})", err); eprintln!("error: unable to delete the existing `tasks.json` file ({err})");
return false; return false;
} }

View File

@@ -86,7 +86,7 @@ fn generate_lint_files(
) )
.sorted() .sorted()
{ {
writeln!(res, "[`{}`]: {}#{}", lint, DOCS_LINK, lint).unwrap(); writeln!(res, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
} }
}, },
); );
@@ -99,7 +99,7 @@ fn generate_lint_files(
"// end lints modules, do not remove this comment, its used in `update_lints`", "// end lints modules, do not remove this comment, its used in `update_lints`",
|res| { |res| {
for lint_mod in usable_lints.iter().map(|l| &l.module).unique().sorted() { for lint_mod in usable_lints.iter().map(|l| &l.module).unique().sorted() {
writeln!(res, "mod {};", lint_mod).unwrap(); writeln!(res, "mod {lint_mod};").unwrap();
} }
}, },
); );
@@ -129,7 +129,7 @@ fn generate_lint_files(
for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) { for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
let content = gen_lint_group_list(&lint_group, lints.iter()); let content = gen_lint_group_list(&lint_group, lints.iter());
process_file( process_file(
&format!("clippy_lints/src/lib.register_{}.rs", lint_group), &format!("clippy_lints/src/lib.register_{lint_group}.rs"),
update_mode, update_mode,
&content, &content,
); );
@@ -190,9 +190,9 @@ fn print_lint_names(header: &str, lints: &BTreeSet<String>) -> bool {
if lints.is_empty() { if lints.is_empty() {
return false; return false;
} }
println!("{}", header); println!("{header}");
for lint in lints.iter().sorted() { for lint in lints.iter().sorted() {
println!(" {}", lint); println!(" {lint}");
} }
println!(); println!();
true true
@@ -205,16 +205,16 @@ pub fn print_lints() {
let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter()); let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter());
for (lint_group, mut lints) in grouped_by_lint_group { for (lint_group, mut lints) in grouped_by_lint_group {
println!("\n## {}", lint_group); println!("\n## {lint_group}");
lints.sort_by_key(|l| l.name.clone()); lints.sort_by_key(|l| l.name.clone());
for lint in lints { for lint in lints {
println!("* [{}]({}#{}) ({})", lint.name, DOCS_LINK, lint.name, lint.desc); println!("* [{}]({DOCS_LINK}#{}) ({})", lint.name, lint.name, lint.desc);
} }
} }
println!("there are {} lints", usable_lint_count); println!("there are {usable_lint_count} lints");
} }
/// Runs the `rename_lint` command. /// Runs the `rename_lint` command.
@@ -235,10 +235,10 @@ pub fn print_lints() {
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
pub fn rename(old_name: &str, new_name: &str, uplift: bool) { pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
if let Some((prefix, _)) = old_name.split_once("::") { if let Some((prefix, _)) = old_name.split_once("::") {
panic!("`{}` should not contain the `{}` prefix", old_name, prefix); panic!("`{old_name}` should not contain the `{prefix}` prefix");
} }
if let Some((prefix, _)) = new_name.split_once("::") { if let Some((prefix, _)) = new_name.split_once("::") {
panic!("`{}` should not contain the `{}` prefix", new_name, prefix); panic!("`{new_name}` should not contain the `{prefix}` prefix");
} }
let (mut lints, deprecated_lints, mut renamed_lints) = gather_all(); let (mut lints, deprecated_lints, mut renamed_lints) = gather_all();
@@ -251,14 +251,14 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
found_new_name = true; found_new_name = true;
} }
} }
let old_lint_index = old_lint_index.unwrap_or_else(|| panic!("could not find lint `{}`", old_name)); let old_lint_index = old_lint_index.unwrap_or_else(|| panic!("could not find lint `{old_name}`"));
let lint = RenamedLint { let lint = RenamedLint {
old_name: format!("clippy::{}", old_name), old_name: format!("clippy::{old_name}"),
new_name: if uplift { new_name: if uplift {
new_name.into() new_name.into()
} else { } else {
format!("clippy::{}", new_name) format!("clippy::{new_name}")
}, },
}; };
@@ -266,13 +266,11 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
// case. // case.
assert!( assert!(
!renamed_lints.iter().any(|l| lint.old_name == l.old_name), !renamed_lints.iter().any(|l| lint.old_name == l.old_name),
"`{}` has already been renamed", "`{old_name}` has already been renamed"
old_name
); );
assert!( assert!(
!deprecated_lints.iter().any(|l| lint.old_name == l.name), !deprecated_lints.iter().any(|l| lint.old_name == l.name),
"`{}` has already been deprecated", "`{old_name}` has already been deprecated"
old_name
); );
// Update all lint level attributes. (`clippy::lint_name`) // Update all lint level attributes. (`clippy::lint_name`)
@@ -309,14 +307,12 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
if uplift { if uplift {
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints)); write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
println!( println!(
"`{}` has be uplifted. All the code inside `clippy_lints` related to it needs to be removed manually.", "`{old_name}` has be uplifted. All the code inside `clippy_lints` related to it needs to be removed manually."
old_name
); );
} else if found_new_name { } else if found_new_name {
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints)); write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
println!( println!(
"`{}` is already defined. The old linting code inside `clippy_lints` needs to be updated/removed manually.", "`{new_name}` is already defined. The old linting code inside `clippy_lints` needs to be updated/removed manually."
new_name
); );
} else { } else {
// Rename the lint struct and source files sharing a name with the lint. // Rename the lint struct and source files sharing a name with the lint.
@@ -327,16 +323,16 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
// Rename test files. only rename `.stderr` and `.fixed` files if the new test name doesn't exist. // Rename test files. only rename `.stderr` and `.fixed` files if the new test name doesn't exist.
if try_rename_file( if try_rename_file(
Path::new(&format!("tests/ui/{}.rs", old_name)), Path::new(&format!("tests/ui/{old_name}.rs")),
Path::new(&format!("tests/ui/{}.rs", new_name)), Path::new(&format!("tests/ui/{new_name}.rs")),
) { ) {
try_rename_file( try_rename_file(
Path::new(&format!("tests/ui/{}.stderr", old_name)), Path::new(&format!("tests/ui/{old_name}.stderr")),
Path::new(&format!("tests/ui/{}.stderr", new_name)), Path::new(&format!("tests/ui/{new_name}.stderr")),
); );
try_rename_file( try_rename_file(
Path::new(&format!("tests/ui/{}.fixed", old_name)), Path::new(&format!("tests/ui/{old_name}.fixed")),
Path::new(&format!("tests/ui/{}.fixed", new_name)), Path::new(&format!("tests/ui/{new_name}.fixed")),
); );
} }
@@ -344,8 +340,8 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
let replacements; let replacements;
let replacements = if lint.module == old_name let replacements = if lint.module == old_name
&& try_rename_file( && try_rename_file(
Path::new(&format!("clippy_lints/src/{}.rs", old_name)), Path::new(&format!("clippy_lints/src/{old_name}.rs")),
Path::new(&format!("clippy_lints/src/{}.rs", new_name)), Path::new(&format!("clippy_lints/src/{new_name}.rs")),
) { ) {
// Edit the module name in the lint list. Note there could be multiple lints. // Edit the module name in the lint list. Note there could be multiple lints.
for lint in lints.iter_mut().filter(|l| l.module == old_name) { for lint in lints.iter_mut().filter(|l| l.module == old_name) {
@@ -356,14 +352,14 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
} else if !lint.module.contains("::") } else if !lint.module.contains("::")
// Catch cases like `methods/lint_name.rs` where the lint is stored in `methods/mod.rs` // Catch cases like `methods/lint_name.rs` where the lint is stored in `methods/mod.rs`
&& try_rename_file( && try_rename_file(
Path::new(&format!("clippy_lints/src/{}/{}.rs", lint.module, old_name)), Path::new(&format!("clippy_lints/src/{}/{old_name}.rs", lint.module)),
Path::new(&format!("clippy_lints/src/{}/{}.rs", lint.module, new_name)), Path::new(&format!("clippy_lints/src/{}/{new_name}.rs", lint.module)),
) )
{ {
// Edit the module name in the lint list. Note there could be multiple lints, or none. // Edit the module name in the lint list. Note there could be multiple lints, or none.
let renamed_mod = format!("{}::{}", lint.module, old_name); let renamed_mod = format!("{}::{old_name}", lint.module);
for lint in lints.iter_mut().filter(|l| l.module == renamed_mod) { for lint in lints.iter_mut().filter(|l| l.module == renamed_mod) {
lint.module = format!("{}::{}", lint.module, new_name); lint.module = format!("{}::{new_name}", lint.module);
} }
replacements = [(&*old_name_upper, &*new_name_upper), (old_name, new_name)]; replacements = [(&*old_name_upper, &*new_name_upper), (old_name, new_name)];
replacements.as_slice() replacements.as_slice()
@@ -379,7 +375,7 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
} }
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
println!("{} has been successfully renamed", old_name); println!("{old_name} has been successfully renamed");
} }
println!("note: `cargo uitest` still needs to be run to update the test results"); println!("note: `cargo uitest` still needs to be run to update the test results");
@@ -408,7 +404,7 @@ pub fn deprecate(name: &str, reason: Option<&String>) {
}); });
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints); generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
println!("info: `{}` has successfully been deprecated", name); println!("info: `{name}` has successfully been deprecated");
if reason == DEFAULT_DEPRECATION_REASON { if reason == DEFAULT_DEPRECATION_REASON {
println!("note: the deprecation reason must be updated in `clippy_lints/src/deprecated_lints.rs`"); println!("note: the deprecation reason must be updated in `clippy_lints/src/deprecated_lints.rs`");
@@ -421,7 +417,7 @@ pub fn deprecate(name: &str, reason: Option<&String>) {
let name_upper = name.to_uppercase(); let name_upper = name.to_uppercase();
let (mut lints, deprecated_lints, renamed_lints) = gather_all(); let (mut lints, deprecated_lints, renamed_lints) = gather_all();
let Some(lint) = lints.iter().find(|l| l.name == name_lower) else { eprintln!("error: failed to find lint `{}`", name); return; }; let Some(lint) = lints.iter().find(|l| l.name == name_lower) else { eprintln!("error: failed to find lint `{name}`"); return; };
let mod_path = { let mod_path = {
let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module)); let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module));
@@ -450,7 +446,7 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
} }
fn remove_test_assets(name: &str) { fn remove_test_assets(name: &str) {
let test_file_stem = format!("tests/ui/{}", name); let test_file_stem = format!("tests/ui/{name}");
let path = Path::new(&test_file_stem); let path = Path::new(&test_file_stem);
// Some lints have their own directories, delete them // Some lints have their own directories, delete them
@@ -512,8 +508,7 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy())); fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy()));
eprintln!( eprintln!(
"warn: you will have to manually remove any code related to `{}` from `{}`", "warn: you will have to manually remove any code related to `{name}` from `{}`",
name,
path.display() path.display()
); );
@@ -528,7 +523,7 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
content.replace_range(lint.declaration_range.clone(), ""); content.replace_range(lint.declaration_range.clone(), "");
// Remove the module declaration (mod xyz;) // Remove the module declaration (mod xyz;)
let mod_decl = format!("\nmod {};", name); let mod_decl = format!("\nmod {name};");
content = content.replacen(&mod_decl, "", 1); content = content.replacen(&mod_decl, "", 1);
remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content); remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content);
@@ -621,13 +616,13 @@ fn round_to_fifty(count: usize) -> usize {
fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str) { fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str) {
if update_mode == UpdateMode::Check { if update_mode == UpdateMode::Check {
let old_content = let old_content =
fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.as_ref().display(), e)); fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {e}", path.as_ref().display()));
if content != old_content { if content != old_content {
exit_with_failure(); exit_with_failure();
} }
} else { } else {
fs::write(&path, content.as_bytes()) fs::write(&path, content.as_bytes())
.unwrap_or_else(|e| panic!("Cannot write to {}: {}", path.as_ref().display(), e)); .unwrap_or_else(|e| panic!("Cannot write to {}: {e}", path.as_ref().display()));
} }
} }
@@ -731,11 +726,10 @@ fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lin
let _ = writeln!( let _ = writeln!(
output, output,
"store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![", "store.register_group(true, \"clippy::{group_name}\", Some(\"clippy_{group_name}\"), vec![",
group_name
); );
for (module, name) in details { for (module, name) in details {
let _ = writeln!(output, " LintId::of({}::{}),", module, name); let _ = writeln!(output, " LintId::of({module}::{name}),");
} }
output.push_str("])\n"); output.push_str("])\n");
@@ -783,7 +777,7 @@ fn gen_register_lint_list<'a>(
if !is_public { if !is_public {
output.push_str(" #[cfg(feature = \"internal\")]\n"); output.push_str(" #[cfg(feature = \"internal\")]\n");
} }
let _ = writeln!(output, " {}::{},", module_name, lint_name); let _ = writeln!(output, " {module_name}::{lint_name},");
} }
output.push_str("])\n"); output.push_str("])\n");
@@ -841,7 +835,7 @@ fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
for (rel_path, file) in clippy_lints_src_files() { for (rel_path, file) in clippy_lints_src_files() {
let path = file.path(); let path = file.path();
let contents = let contents =
fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e)); fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display()));
let module = rel_path let module = rel_path
.components() .components()
.map(|c| c.as_os_str().to_str().unwrap()) .map(|c| c.as_os_str().to_str().unwrap())
@@ -1050,7 +1044,7 @@ fn remove_line_splices(s: &str) -> String {
.trim_matches('#') .trim_matches('#')
.strip_prefix('"') .strip_prefix('"')
.and_then(|s| s.strip_suffix('"')) .and_then(|s| s.strip_suffix('"'))
.unwrap_or_else(|| panic!("expected quoted string, found `{}`", s)); .unwrap_or_else(|| panic!("expected quoted string, found `{s}`"));
let mut res = String::with_capacity(s.len()); let mut res = String::with_capacity(s.len());
unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| { unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| {
if ch.is_ok() { if ch.is_ok() {
@@ -1076,10 +1070,10 @@ fn replace_region_in_file(
end: &str, end: &str,
write_replacement: impl FnMut(&mut String), write_replacement: impl FnMut(&mut String),
) { ) {
let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e)); let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display()));
let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) { let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) {
Ok(x) => x, Ok(x) => x,
Err(delim) => panic!("Couldn't find `{}` in file `{}`", delim, path.display()), Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()),
}; };
match update_mode { match update_mode {
@@ -1087,7 +1081,7 @@ fn replace_region_in_file(
UpdateMode::Check => (), UpdateMode::Check => (),
UpdateMode::Change => { UpdateMode::Change => {
if let Err(e) = fs::write(path, new_contents.as_bytes()) { if let Err(e) = fs::write(path, new_contents.as_bytes()) {
panic!("Cannot write to `{}`: {}", path.display(), e); panic!("Cannot write to `{}`: {e}", path.display());
} }
}, },
} }
@@ -1135,7 +1129,7 @@ fn try_rename_file(old_name: &Path, new_name: &Path) -> bool {
#[allow(clippy::needless_pass_by_value)] #[allow(clippy::needless_pass_by_value)]
fn panic_file(error: io::Error, name: &Path, action: &str) -> ! { fn panic_file(error: io::Error, name: &Path, action: &str) -> ! {
panic!("failed to {} file `{}`: {}", action, name.display(), error) panic!("failed to {action} file `{}`: {error}", name.display())
} }
fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option<String>) { fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option<String>) {

View File

@@ -530,7 +530,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
cx, cx,
LINT_WITHOUT_LINT_PASS, LINT_WITHOUT_LINT_PASS,
lint_span, lint_span,
&format!("the lint `{}` is not added to any `LintPass`", lint_name), &format!("the lint `{lint_name}` is not added to any `LintPass`"),
); );
} }
} }
@@ -666,7 +666,7 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
path.ident.span, path.ident.span,
"usage of a compiler lint function", "usage of a compiler lint function",
None, None,
&format!("please use the Clippy variant of this function: `{}`", sugg), &format!("please use the Clippy variant of this function: `{sugg}`"),
); );
} }
} }
@@ -854,13 +854,8 @@ fn suggest_help(
"this call is collapsible", "this call is collapsible",
"collapse into", "collapse into",
format!( format!(
"span_lint_and_help({}, {}, {}, {}, {}, {})", "span_lint_and_help({}, {}, {}, {}, {}, {help})",
and_then_snippets.cx, and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span,
and_then_snippets.lint,
and_then_snippets.span,
and_then_snippets.msg,
&option_span,
help
), ),
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
@@ -886,13 +881,8 @@ fn suggest_note(
"this call is collapsible", "this call is collapsible",
"collapse into", "collapse into",
format!( format!(
"span_lint_and_note({}, {}, {}, {}, {}, {})", "span_lint_and_note({}, {}, {}, {}, {note_span}, {note})",
and_then_snippets.cx, and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg,
and_then_snippets.lint,
and_then_snippets.span,
and_then_snippets.msg,
note_span,
note
), ),
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
@@ -927,7 +917,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem {
expr.span, expr.span,
"usage of `clippy_utils::ty::match_type()` on a type diagnostic item", "usage of `clippy_utils::ty::match_type()` on a type diagnostic item",
"try", "try",
format!("clippy_utils::ty::is_type_diagnostic_item({}, {}, sym::{})", cx_snippet, ty_snippet, item_name), format!("clippy_utils::ty::is_type_diagnostic_item({cx_snippet}, {ty_snippet}, sym::{item_name})"),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }

View File

@@ -64,46 +64,6 @@ const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[
/// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed /// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed
/// to only keep the actual lint group in the output. /// to only keep the actual lint group in the output.
const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::"; const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::";
/// This template will be used to format the configuration section in the lint documentation.
/// The `configurations` parameter will be replaced with one or multiple formatted
/// `ClippyConfiguration` instances. See `CONFIGURATION_VALUE_TEMPLATE` for further customizations
macro_rules! CONFIGURATION_SECTION_TEMPLATE {
() => {
r#"
### Configuration
This lint has the following configuration variables:
{configurations}
"#
};
}
/// This template will be used to format an individual `ClippyConfiguration` instance in the
/// lint documentation.
///
/// The format function will provide strings for the following parameters: `name`, `ty`, `doc` and
/// `default`
macro_rules! CONFIGURATION_VALUE_TEMPLATE {
() => {
"* `{name}`: `{ty}`: {doc} (defaults to `{default}`)\n"
};
}
macro_rules! RENAMES_SECTION_TEMPLATE {
() => {
r#"
### Past names
{names}
"#
};
}
macro_rules! RENAME_VALUE_TEMPLATE {
() => {
"* `{name}`\n"
};
}
const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [ const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
&["clippy_utils", "diagnostics", "span_lint"], &["clippy_utils", "diagnostics", "span_lint"],
&["clippy_utils", "diagnostics", "span_lint_and_help"], &["clippy_utils", "diagnostics", "span_lint_and_help"],
@@ -205,7 +165,16 @@ impl MetadataCollector {
.filter(|config| config.lints.iter().any(|lint| lint == lint_name)) .filter(|config| config.lints.iter().any(|lint| lint == lint_name))
.map(ToString::to_string) .map(ToString::to_string)
.reduce(|acc, x| acc + &x) .reduce(|acc, x| acc + &x)
.map(|configurations| format!(CONFIGURATION_SECTION_TEMPLATE!(), configurations = configurations)) .map(|configurations| {
format!(
r#"
### Configuration
This lint has the following configuration variables:
{configurations}
"#
)
})
} }
} }
@@ -291,16 +260,13 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
continue; continue;
} }
panic!("lint `{}` has an unterminated code block", lint_name) panic!("lint `{lint_name}` has an unterminated code block")
} }
break; break;
}, },
Some(line) if line.trim_start() == "{{produces}}" => { Some(line) if line.trim_start() == "{{produces}}" => {
panic!( panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block")
"lint `{}` has marker {{{{produces}}}} with an ignored or missing code block",
lint_name
)
}, },
Some(line) => { Some(line) => {
let line = line.trim(); let line = line.trim();
@@ -319,7 +285,7 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
match lines.next() { match lines.next() {
Some(line) if line.trim_start() == "```" => break, Some(line) if line.trim_start() == "```" => break,
Some(line) => example.push(line), Some(line) => example.push(line),
None => panic!("lint `{}` has an unterminated code block", lint_name), None => panic!("lint `{lint_name}` has an unterminated code block"),
} }
} }
@@ -336,10 +302,9 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
<summary>Produces</summary>\n\ <summary>Produces</summary>\n\
\n\ \n\
```text\n\ ```text\n\
{}\n\ {output}\n\
```\n\ ```\n\
</details>", </details>"
output
), ),
); );
@@ -394,7 +359,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy()); panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy());
} }
let prefixed_name = format!("{}{lint_name}", CLIPPY_LINT_GROUP_PREFIX); let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}");
let mut cmd = Command::new("cargo"); let mut cmd = Command::new("cargo");
@@ -417,7 +382,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
let output = cmd let output = cmd
.arg(file.as_path()) .arg(file.as_path())
.output() .output()
.unwrap_or_else(|e| panic!("failed to run `{:?}`: {e}", cmd)); .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
let tmp_file_path = file.to_string_lossy(); let tmp_file_path = file.to_string_lossy();
let stderr = std::str::from_utf8(&output.stderr).unwrap(); let stderr = std::str::from_utf8(&output.stderr).unwrap();
@@ -441,8 +406,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect(); let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect(); let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
panic!( panic!(
"did not find lint `{}` in output of example, got:\n{}\n{}", "did not find lint `{lint_name}` in output of example, got:\n{}\n{}",
lint_name,
non_json.join("\n"), non_json.join("\n"),
rendered.join("\n") rendered.join("\n")
); );
@@ -588,13 +552,10 @@ fn to_kebab(config_name: &str) -> String {
impl fmt::Display for ClippyConfiguration { impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
write!( writeln!(
f, f,
CONFIGURATION_VALUE_TEMPLATE!(), "* `{}`: `{}`: {} (defaults to `{}`)",
name = self.name, self.name, self.config_type, self.doc, self.default
ty = self.config_type,
doc = self.doc,
default = self.default
) )
} }
} }
@@ -811,7 +772,7 @@ fn get_lint_group_and_level_or_lint(
lint_collection_error_item( lint_collection_error_item(
cx, cx,
item, item,
&format!("Unable to determine lint level for found group `{}`", group), &format!("Unable to determine lint level for found group `{group}`"),
); );
None None
} }
@@ -869,7 +830,7 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
if name == lint_name; if name == lint_name;
if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX); if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
then { then {
write!(collected, RENAME_VALUE_TEMPLATE!(), name = past_name).unwrap(); writeln!(collected, "* `{past_name}`").unwrap();
names.push(past_name.to_string()); names.push(past_name.to_string());
} }
} }
@@ -882,7 +843,15 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
} }
if !collected.is_empty() { if !collected.is_empty() {
write!(&mut lint.docs, RENAMES_SECTION_TEMPLATE!(), names = collected).unwrap(); write!(
&mut lint.docs,
r#"
### Past names
{collected}
"#
)
.unwrap();
} }
} }
} }
@@ -895,7 +864,7 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s
cx, cx,
INTERNAL_METADATA_COLLECTOR, INTERNAL_METADATA_COLLECTOR,
item.ident.span, item.ident.span,
&format!("metadata collection error for `{}`: {}", item.ident.name, message), &format!("metadata collection error for `{}`: {message}", item.ident.name),
); );
} }