diff options
| author | Philipp Krones <hello@philkrones.com> | 2025-02-28 23:20:48 +0100 |
|---|---|---|
| committer | Philipp Krones <hello@philkrones.com> | 2025-02-28 23:27:09 +0100 |
| commit | fe01c4499507fc6ba21e07ff9824c14443b308e9 (patch) | |
| tree | 48eb83134a7122ddbecda437dfb8b558baf5cb8f /clippy_dev | |
| parent | 222aaba5a18a27f747573aa73d07d7fedfff0231 (diff) | |
| download | rust-fe01c4499507fc6ba21e07ff9824c14443b308e9.tar.gz rust-fe01c4499507fc6ba21e07ff9824c14443b308e9.zip | |
Merge commit '9f9a822509e5ad3e560cbbe830d1013f936fca28' into clippy-subtree-update
Diffstat (limited to 'clippy_dev')
| -rw-r--r-- | clippy_dev/src/dogfood.rs | 7 | ||||
| -rw-r--r-- | clippy_dev/src/fmt.rs | 9 | ||||
| -rw-r--r-- | clippy_dev/src/lint.rs | 4 | ||||
| -rw-r--r-- | clippy_dev/src/main.rs | 37 | ||||
| -rw-r--r-- | clippy_dev/src/new_lint.rs | 85 | ||||
| -rw-r--r-- | clippy_dev/src/setup/toolchain.rs | 27 |
6 files changed, 114 insertions, 55 deletions
diff --git a/clippy_dev/src/dogfood.rs b/clippy_dev/src/dogfood.rs index 75a4cbd2f92..05fa24d8d4e 100644 --- a/clippy_dev/src/dogfood.rs +++ b/clippy_dev/src/dogfood.rs @@ -4,7 +4,8 @@ use std::process::Command; /// # Panics /// /// Panics if unable to run the dogfood test -pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) { +#[allow(clippy::fn_params_excessive_bools)] +pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool, allow_no_vcs: bool) { let mut cmd = Command::new("cargo"); cmd.current_dir(clippy_project_root()) @@ -25,6 +26,10 @@ pub fn dogfood(fix: bool, allow_dirty: bool, allow_staged: bool) { dogfood_args.push("--allow-staged"); } + if allow_no_vcs { + dogfood_args.push("--allow-no-vcs"); + } + cmd.env("__CLIPPY_DOGFOOD_ARGS", dogfood_args.join(" ")); exit_if_err(cmd.status()); diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 790dafa811f..bdddf46a2cb 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -290,8 +290,13 @@ fn run_rustfmt(context: &FmtContext) -> Result<(), Error> { .filter_map(|entry| { let entry = entry.expect("failed to find tests"); let path = entry.path(); - - if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" { + if path.extension() != Some("rs".as_ref()) + || path + .components() + .nth_back(1) + .is_some_and(|c| c.as_os_str() == "syntax-error-recovery") + || entry.file_name() == "ice-3891.rs" + { None } else { Some(entry.into_path().into_os_string()) diff --git a/clippy_dev/src/lint.rs b/clippy_dev/src/lint.rs index 125195397e6..e0e036757d5 100644 --- a/clippy_dev/src/lint.rs +++ b/clippy_dev/src/lint.rs @@ -2,7 +2,7 @@ use crate::utils::{cargo_clippy_path, exit_if_err}; use std::process::{self, Command}; use std::{env, fs}; -pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) { +pub fn run<'a>(path: &str, edition: &str, args: impl Iterator<Item = &'a String>) { let is_file = match fs::metadata(path) { Ok(metadata) => metadata.is_file(), Err(e) => { @@ -17,7 +17,7 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) { .args(["run", "--bin", "clippy-driver", "--"]) .args(["-L", "./target/debug"]) .args(["-Z", "no-codegen"]) - .args(["--edition", "2021"]) + .args(["--edition", edition]) .arg(path) .args(args) // Prevent rustc from creating `rustc-ice-*` files the console output is enough. diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 56ed60256f1..074dea4ab77 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -17,7 +17,8 @@ fn main() { fix, allow_dirty, allow_staged, - } => dogfood::dogfood(fix, allow_dirty, allow_staged), + allow_no_vcs, + } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs), DevCommand::Fmt { check, verbose } => fmt::run(check, verbose), DevCommand::UpdateLints { print_only, check } => { if print_only { @@ -34,7 +35,7 @@ fn main() { category, r#type, msrv, - } => match new_lint::create(&pass, &name, &category, r#type.as_deref(), msrv) { + } => match new_lint::create(pass, &name, &category, r#type.as_deref(), msrv) { Ok(()) => update_lints::update(utils::UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {e}"), }, @@ -53,7 +54,12 @@ fn main() { setup::git_hook::install_hook(force_override); } }, - SetupSubcommand::Toolchain { force, release, name } => setup::toolchain::create(force, release, &name), + SetupSubcommand::Toolchain { + standalone, + force, + release, + name, + } => setup::toolchain::create(standalone, force, release, &name), SetupSubcommand::VscodeTasks { remove, force_override } => { if remove { setup::vscode::remove_tasks(); @@ -68,7 +74,7 @@ fn main() { RemoveSubcommand::VscodeTasks => setup::vscode::remove_tasks(), }, DevCommand::Serve { port, lint } => serve::run(port, lint), - DevCommand::Lint { path, args } => lint::run(&path, args.iter()), + DevCommand::Lint { path, edition, args } => lint::run(&path, &edition, args.iter()), DevCommand::RenameLint { old_name, new_name, @@ -106,6 +112,9 @@ enum DevCommand { #[arg(long, requires = "fix")] /// Fix code even if the working directory has staged changes allow_staged: bool, + #[arg(long, requires = "fix")] + /// Fix code even if a VCS was not detected + allow_no_vcs: bool, }, /// Run rustfmt on all projects and tests Fmt { @@ -138,9 +147,9 @@ enum DevCommand { #[command(name = "new_lint")] /// Create a new lint and run `cargo dev update_lints` NewLint { - #[arg(short, long, value_parser = ["early", "late"], conflicts_with = "type", default_value = "late")] + #[arg(short, long, conflicts_with = "type", default_value = "late")] /// Specify whether the lint runs during the early or late pass - pass: String, + pass: new_lint::Pass, #[arg( short, long, @@ -206,6 +215,9 @@ enum DevCommand { /// cargo dev lint file.rs -- -W clippy::pedantic {n} /// cargo dev lint ~/my-project -- -- -W clippy::pedantic Lint { + /// The Rust edition to use + #[arg(long, default_value = "2024")] + edition: String, /// The path to a file or package directory to lint path: String, /// Pass extra arguments to cargo/clippy-driver @@ -264,14 +276,25 @@ enum SetupSubcommand { force_override: bool, }, /// Install a rustup toolchain pointing to the local clippy build + /// + /// This creates a toolchain with symlinks pointing at + /// `target/.../{clippy-driver,cargo-clippy}`, rebuilds of the project will be reflected in the + /// created toolchain unless `--standalone` is passed Toolchain { #[arg(long, short)] + /// Create a standalone toolchain by copying the clippy binaries instead + /// of symlinking them + /// + /// Use this for example to create a toolchain, make a small change and then make another + /// toolchain with a different name in order to easily compare the two + standalone: bool, + #[arg(long, short)] /// Override an existing toolchain force: bool, #[arg(long, short)] /// Point to --release clippy binary release: bool, - #[arg(long, default_value = "clippy")] + #[arg(long, short, default_value = "clippy")] /// Name of the toolchain name: String, }, diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index cc4b26867a2..96e12706c9e 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -1,14 +1,28 @@ use crate::utils::{clippy_project_root, clippy_version}; +use clap::ValueEnum; use indoc::{formatdoc, writedoc}; -use std::fmt; -use std::fmt::Write as _; +use std::fmt::{self, Write as _}; use std::fs::{self, OpenOptions}; -use std::io::prelude::*; -use std::io::{self, ErrorKind}; +use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; +#[derive(Clone, Copy, PartialEq, ValueEnum)] +pub enum Pass { + Early, + Late, +} + +impl fmt::Display for Pass { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Pass::Early => "early", + Pass::Late => "late", + }) + } +} + struct LintData<'a> { - pass: &'a str, + pass: Pass, name: &'a str, category: &'a str, ty: Option<&'a str>, @@ -25,7 +39,7 @@ impl<T> Context for io::Result<T> { Ok(t) => Ok(t), Err(e) => { let message = format!("{}: {e}", text.as_ref()); - Err(io::Error::new(ErrorKind::Other, message)) + Err(io::Error::other(message)) }, } } @@ -36,7 +50,7 @@ impl<T> Context for io::Result<T> { /// # Errors /// /// This function errors out if the files couldn't be created or written to. -pub fn create(pass: &str, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> { +pub fn create(pass: Pass, name: &str, category: &str, mut ty: Option<&str>, msrv: bool) -> io::Result<()> { if category == "cargo" && ty.is_none() { // `cargo` is a special category, these lints should always be in `clippy_lints/src/cargo` ty = Some("cargo"); @@ -57,7 +71,7 @@ pub fn create(pass: &str, name: &str, category: &str, mut ty: Option<&str>, msrv add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")?; } - if pass == "early" { + if pass == Pass::Early { println!( "\n\ NOTE: Use a late pass unless you need something specific from\n\ @@ -137,23 +151,17 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> { let mut lib_rs = fs::read_to_string(path).context("reading")?; let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment"); + let ctor_arg = if lint.pass == Pass::Late { "_" } else { "" }; + let lint_pass = lint.pass; + let module_name = lint.name; + let camel_name = to_camel_case(lint.name); let new_lint = if enable_msrv { format!( "store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(conf)));\n ", - lint_pass = lint.pass, - ctor_arg = if lint.pass == "late" { "_" } else { "" }, - module_name = lint.name, - camel_name = to_camel_case(lint.name), ) } else { - format!( - "store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ", - lint_pass = lint.pass, - ctor_arg = if lint.pass == "late" { "_" } else { "" }, - module_name = lint.name, - camel_name = to_camel_case(lint.name), - ) + format!("store.register_{lint_pass}_pass(|{ctor_arg}| Box::new({module_name}::{camel_name}));\n ",) }; lib_rs.insert_str(comment_start, &new_lint); @@ -243,11 +251,16 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { let mut result = String::new(); let (pass_type, pass_lifetimes, pass_import, context_import) = match lint.pass { - "early" => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), - "late" => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"), - _ => { - unreachable!("`pass_type` should only ever be `early` or `late`!"); - }, + Pass::Early => ("EarlyLintPass", "", "use rustc_ast::ast::*;", "EarlyContext"), + Pass::Late => ("LateLintPass", "<'_>", "use rustc_hir::*;", "LateContext"), + }; + let (msrv_ty, msrv_ctor, extract_msrv) = match lint.pass { + Pass::Early => ( + "MsrvStack", + "MsrvStack::new(conf.msrv)", + "\n extract_msrv_attr!();\n", + ), + Pass::Late => ("Msrv", "conf.msrv", ""), }; let lint_name = lint.name; @@ -259,10 +272,10 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { let _: fmt::Result = writedoc!( result, r" - use clippy_utils::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, {msrv_ty}}}; use clippy_config::Conf; {pass_import} - use rustc_lint::{{{context_import}, {pass_type}, LintContext}}; + use rustc_lint::{{{context_import}, {pass_type}}}; use rustc_session::impl_lint_pass; " @@ -286,20 +299,18 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String { result, r" pub struct {name_camel} {{ - msrv: Msrv, + msrv: {msrv_ty}, }} impl {name_camel} {{ pub fn new(conf: &'static Conf) -> Self {{ - Self {{ msrv: conf.msrv.clone() }} + Self {{ msrv: {msrv_ctor} }} }} }} impl_lint_pass!({name_camel} => [{name_upper}]); - impl {pass_type}{pass_lifetimes} for {name_camel} {{ - extract_msrv_attr!({context_import}); - }} + impl {pass_type}{pass_lifetimes} for {name_camel} {{{extract_msrv}}} // TODO: Add MSRV level to `clippy_config/src/msrvs.rs` if needed. // TODO: Update msrv config comment in `clippy_config/src/conf.rs` @@ -376,9 +387,9 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let mod_file_path = ty_dir.join("mod.rs"); let context_import = setup_mod_file(&mod_file_path, lint)?; - let pass_lifetimes = match context_import { - "LateContext" => "<'_>", - _ => "", + let (pass_lifetimes, msrv_ty, msrv_ref, msrv_cx) = match context_import { + "LateContext" => ("<'_>", "Msrv", "", "cx, "), + _ => ("", "MsrvStack", "&", ""), }; let name_upper = lint.name.to_uppercase(); @@ -388,14 +399,14 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R let _: fmt::Result = writedoc!( lint_file_contents, r#" - use clippy_utils::msrvs::{{self, Msrv}}; + use clippy_utils::msrvs::{{self, {msrv_ty}}}; use rustc_lint::{{{context_import}, LintContext}}; use super::{name_upper}; // TODO: Adjust the parameters as necessary - pub(super) fn check(cx: &{context_import}{pass_lifetimes}, msrv: &Msrv) {{ - if !msrv.meets(todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ + pub(super) fn check(cx: &{context_import}{pass_lifetimes}, msrv: {msrv_ref}{msrv_ty}) {{ + if !msrv.meets({msrv_cx}todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{ return; }} todo!(); diff --git a/clippy_dev/src/setup/toolchain.rs b/clippy_dev/src/setup/toolchain.rs index 8d98c6c92d9..2966629cf70 100644 --- a/clippy_dev/src/setup/toolchain.rs +++ b/clippy_dev/src/setup/toolchain.rs @@ -3,11 +3,14 @@ use std::env::current_dir; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; +use std::process::Command; use walkdir::WalkDir; +use crate::utils::exit_if_err; + use super::verify_inside_clippy_dir; -pub fn create(force: bool, release: bool, name: &str) { +pub fn create(standalone: bool, force: bool, release: bool, name: &str) { if !verify_inside_clippy_dir() { return; } @@ -48,14 +51,22 @@ pub fn create(force: bool, release: bool, name: &str) { } } - symlink_bin("cargo-clippy", &dest, release); - symlink_bin("clippy-driver", &dest, release); + let status = Command::new("cargo") + .arg("build") + .args(release.then_some("--release")) + .status(); + exit_if_err(status); + + install_bin("cargo-clippy", &dest, standalone, release); + install_bin("clippy-driver", &dest, standalone, release); println!("Created toolchain {name}, use it in other projects with e.g. `cargo +{name} clippy`"); - println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes"); + if !standalone { + println!("Note: This will need to be re-run whenever the Clippy `rust-toolchain` changes"); + } } -fn symlink_bin(bin: &str, dest: &Path, release: bool) { +fn install_bin(bin: &str, dest: &Path, standalone: bool, release: bool) { #[cfg(windows)] use std::os::windows::fs::symlink_file as symlink; @@ -71,5 +82,9 @@ fn symlink_bin(bin: &str, dest: &Path, release: bool) { let mut dest = dest.to_path_buf(); dest.extend(["bin", &file_name]); - symlink(src, dest).unwrap(); + if standalone { + fs::copy(src, dest).unwrap(); + } else { + symlink(src, dest).unwrap(); + } } |
