diff --git a/Cargo.toml b/Cargo.toml index b6a1b9314c65..2da350ba44e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,6 @@ [package] name = "clippy" -# begin autogenerated version version = "0.1.89" -# end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index 1134b0e97af2..0606245f990c 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,8 +1,6 @@ [package] name = "clippy_config" -# begin autogenerated version version = "0.1.89" -# end autogenerated version edition = "2024" publish = false diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index a963fba7d98e..10c08dba50b9 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -10,7 +10,6 @@ clap = { version = "4.4", features = ["derive"] } indoc = "1.0" itertools = "0.12" opener = "0.7" -shell-escape = "0.1" walkdir = "2.3" [package.metadata.rust-analyzer] diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index b4c13213f552..298326174a48 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -1,19 +1,15 @@ +use crate::utils::{ClippyInfo, ErrAction, UpdateMode, panic_action, run_with_args_split, run_with_output}; use itertools::Itertools; use rustc_lexer::{TokenKind, tokenize}; -use shell_escape::escape; -use std::ffi::{OsStr, OsString}; +use std::fs; +use std::io::{self, Read}; use std::ops::ControlFlow; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process::{self, Command, Stdio}; -use std::{fs, io}; use walkdir::WalkDir; pub enum Error { - CommandFailed(String, String), Io(io::Error), - RustfmtNotInstalled, - WalkDir(walkdir::Error), - IntellijSetupActive, Parse(PathBuf, usize, String), CheckFailed, } @@ -24,37 +20,15 @@ impl From for Error { } } -impl From for Error { - fn from(error: walkdir::Error) -> Self { - Self::WalkDir(error) - } -} - impl Error { fn display(&self) { match self { Self::CheckFailed => { eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update."); }, - Self::CommandFailed(command, stderr) => { - eprintln!("error: command `{command}` failed!\nstderr: {stderr}"); - }, Self::Io(err) => { eprintln!("error: {err}"); }, - Self::RustfmtNotInstalled => { - eprintln!("error: rustfmt nightly is not installed."); - }, - Self::WalkDir(err) => { - eprintln!("error: {err}"); - }, - Self::IntellijSetupActive => { - eprintln!( - "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.\n\ - Not formatting because that would format the local repo as well!\n\ - Please revert the changes to `Cargo.toml`s with `cargo dev remove intellij`." - ); - }, Self::Parse(path, line, msg) => { eprintln!("error parsing `{}:{line}`: {msg}", path.display()); }, @@ -62,12 +36,6 @@ impl Error { } } -struct FmtContext { - check: bool, - verbose: bool, - rustfmt_path: String, -} - struct ClippyConf<'a> { name: &'a str, attrs: &'a str, @@ -257,155 +225,120 @@ fn fmt_conf(check: bool) -> Result<(), Error> { Ok(()) } -fn run_rustfmt(context: &FmtContext) -> Result<(), Error> { - // if we added a local rustc repo as path dependency to clippy for rust analyzer, we do NOT want to - // format because rustfmt would also format the entire rustc repo as it is a local - // dependency - if fs::read_to_string("Cargo.toml") - .expect("Failed to read clippy Cargo.toml") - .contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") - { - return Err(Error::IntellijSetupActive); - } - - check_for_rustfmt(context)?; +fn run_rustfmt(clippy: &ClippyInfo, update_mode: UpdateMode) { + let mut rustfmt_path = String::from_utf8(run_with_output( + "rustup which rustfmt", + Command::new("rustup").args(["which", "rustfmt"]), + )) + .expect("invalid rustfmt path"); + rustfmt_path.truncate(rustfmt_path.trim_end().len()); - cargo_fmt(context, ".".as_ref())?; - cargo_fmt(context, "clippy_dev".as_ref())?; - cargo_fmt(context, "rustc_tools_util".as_ref())?; - cargo_fmt(context, "lintcheck".as_ref())?; + let mut cargo_path = String::from_utf8(run_with_output( + "rustup which cargo", + Command::new("rustup").args(["which", "cargo"]), + )) + .expect("invalid cargo path"); + cargo_path.truncate(cargo_path.trim_end().len()); + + // Start all format jobs first before waiting on the results. + let mut children = Vec::with_capacity(16); + for &path in &[ + ".", + "clippy_config", + "clippy_dev", + "clippy_lints", + "clippy_utils", + "rustc_tools_util", + "lintcheck", + ] { + let mut cmd = Command::new(&cargo_path); + cmd.current_dir(clippy.path.join(path)) + .args(["fmt"]) + .env("RUSTFMT", &rustfmt_path) + .stdout(Stdio::null()) + .stdin(Stdio::null()) + .stderr(Stdio::piped()); + if update_mode.is_check() { + cmd.arg("--check"); + } + match cmd.spawn() { + Ok(x) => children.push(("cargo fmt", x)), + Err(ref e) => panic_action(&e, ErrAction::Run, "cargo fmt".as_ref()), + } + } - let chunks = WalkDir::new("tests") - .into_iter() - .filter_map(|entry| { - let entry = entry.expect("failed to find tests"); - let path = entry.path(); - 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()) + run_with_args_split( + || { + let mut cmd = Command::new(&rustfmt_path); + if update_mode.is_check() { + cmd.arg("--check"); } - }) - .chunks(250); + cmd.stdout(Stdio::null()) + .stdin(Stdio::null()) + .stderr(Stdio::piped()) + .args(["--config", "show_parse_errors=false"]); + cmd + }, + |cmd| match cmd.spawn() { + Ok(x) => children.push(("rustfmt", x)), + Err(ref e) => panic_action(&e, ErrAction::Run, "rustfmt".as_ref()), + }, + WalkDir::new("tests") + .into_iter() + .filter_entry(|p| p.path().file_name().is_none_or(|x| x != "skip_rustfmt")) + .filter_map(|e| { + let e = e.expect("error reading `tests`"); + e.path() + .as_os_str() + .as_encoded_bytes() + .ends_with(b".rs") + .then(|| e.into_path().into_os_string()) + }), + ); - for chunk in &chunks { - rustfmt(context, chunk)?; + for (name, child) in &mut children { + match child.wait() { + Ok(status) => match (update_mode, status.exit_ok()) { + (UpdateMode::Check | UpdateMode::Change, Ok(())) => {}, + (UpdateMode::Check, Err(_)) => { + let mut s = String::new(); + if let Some(mut stderr) = child.stderr.take() + && stderr.read_to_string(&mut s).is_ok() + { + eprintln!("{s}"); + } + eprintln!("Formatting check failed!\nRun `cargo dev fmt` to update."); + process::exit(1); + }, + (UpdateMode::Change, Err(e)) => { + let mut s = String::new(); + if let Some(mut stderr) = child.stderr.take() + && stderr.read_to_string(&mut s).is_ok() + { + eprintln!("{s}"); + } + panic_action(&e, ErrAction::Run, name.as_ref()); + }, + }, + Err(ref e) => panic_action(e, ErrAction::Run, name.as_ref()), + } } - Ok(()) } // the "main" function of cargo dev fmt -pub fn run(check: bool, verbose: bool) { - let output = Command::new("rustup") - .args(["which", "rustfmt"]) - .stderr(Stdio::inherit()) - .output() - .expect("error running `rustup which rustfmt`"); - if !output.status.success() { - eprintln!("`rustup which rustfmt` did not execute successfully"); - process::exit(1); +pub fn run(clippy: &ClippyInfo, update_mode: UpdateMode) { + if clippy.has_intellij_hook { + eprintln!( + "error: a local rustc repo is enabled as path dependency via `cargo dev setup intellij`.\n\ + Not formatting because that would format the local repo as well!\n\ + Please revert the changes to `Cargo.toml`s with `cargo dev remove intellij`." + ); + return; } - let mut rustfmt_path = String::from_utf8(output.stdout).expect("invalid rustfmt path"); - rustfmt_path.truncate(rustfmt_path.trim_end().len()); + run_rustfmt(clippy, update_mode); - let context = FmtContext { - check, - verbose, - rustfmt_path, - }; - if let Err(e) = run_rustfmt(&context).and_then(|()| fmt_conf(check)) { + if let Err(e) = fmt_conf(update_mode.is_check()) { e.display(); process::exit(1); } } - -fn format_command(program: impl AsRef, dir: impl AsRef, args: &[impl AsRef]) -> String { - let arg_display: Vec<_> = args.iter().map(|a| escape(a.as_ref().to_string_lossy())).collect(); - - format!( - "cd {} && {} {}", - escape(dir.as_ref().to_string_lossy()), - escape(program.as_ref().to_string_lossy()), - arg_display.join(" ") - ) -} - -fn exec_fmt_command( - context: &FmtContext, - program: impl AsRef, - dir: impl AsRef, - args: &[impl AsRef], -) -> Result<(), Error> { - if context.verbose { - println!("{}", format_command(&program, &dir, args)); - } - - let output = Command::new(&program) - .env("RUSTFMT", &context.rustfmt_path) - .current_dir(&dir) - .args(args.iter()) - .output() - .unwrap(); - let success = output.status.success(); - - match (context.check, success) { - (_, true) => Ok(()), - (true, false) => Err(Error::CheckFailed), - (false, false) => { - let stderr = std::str::from_utf8(&output.stderr).unwrap_or(""); - Err(Error::CommandFailed( - format_command(&program, &dir, args), - String::from(stderr), - )) - }, - } -} - -fn cargo_fmt(context: &FmtContext, path: &Path) -> Result<(), Error> { - let mut args = vec!["fmt", "--all"]; - if context.check { - args.push("--check"); - } - exec_fmt_command(context, "cargo", path, &args) -} - -fn check_for_rustfmt(context: &FmtContext) -> Result<(), Error> { - let program = "rustfmt"; - let dir = std::env::current_dir()?; - let args = &["--version"]; - - if context.verbose { - println!("{}", format_command(program, &dir, args)); - } - - let output = Command::new(program).current_dir(&dir).args(args.iter()).output()?; - - if output.status.success() { - Ok(()) - } else if std::str::from_utf8(&output.stderr) - .unwrap_or("") - .starts_with("error: 'rustfmt' is not installed") - { - Err(Error::RustfmtNotInstalled) - } else { - Err(Error::CommandFailed( - format_command(program, &dir, args), - std::str::from_utf8(&output.stderr).unwrap_or("").to_string(), - )) - } -} - -fn rustfmt(context: &FmtContext, paths: impl Iterator) -> Result<(), Error> { - let mut args = Vec::new(); - if context.check { - args.push(OsString::from("--check")); - } - args.extend(paths); - exec_fmt_command(context, &context.rustfmt_path, std::env::current_dir()?, &args) -} diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 1cfcbdfe855e..3361443196ab 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,5 +1,6 @@ #![feature( rustc_private, + exit_status_error, if_let_guard, let_chains, os_str_slice, diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 5dce0be742b2..ebcd8611d78c 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -26,7 +26,7 @@ fn main() { allow_staged, allow_no_vcs, } => dogfood::dogfood(fix, allow_dirty, allow_staged, allow_no_vcs), - DevCommand::Fmt { check, verbose } => fmt::run(check, verbose), + DevCommand::Fmt { check } => fmt::run(&clippy, utils::UpdateMode::from_check(check)), DevCommand::UpdateLints { check } => update_lints::update(utils::UpdateMode::from_check(check)), DevCommand::NewLint { pass, @@ -125,9 +125,6 @@ enum DevCommand { #[arg(long)] /// Use the rustfmt --check option check: bool, - #[arg(short, long)] - /// Echo commands run - verbose: bool, }, #[command(name = "update_lints")] /// Updates lint registration and information from the source code diff --git a/clippy_dev/src/release.rs b/clippy_dev/src/release.rs index d3b1a7ff3201..62c1bee81850 100644 --- a/clippy_dev/src/release.rs +++ b/clippy_dev/src/release.rs @@ -1,4 +1,4 @@ -use crate::utils::{FileUpdater, Version, update_text_region_fn}; +use crate::utils::{FileUpdater, UpdateStatus, Version, parse_cargo_package}; use std::fmt::Write; static CARGO_TOML_FILES: &[&str] = &[ @@ -13,15 +13,17 @@ pub fn bump_version(mut version: Version) { let mut updater = FileUpdater::default(); for file in CARGO_TOML_FILES { - updater.update_file( - file, - &mut update_text_region_fn( - "# begin autogenerated version\n", - "# end autogenerated version", - |dst| { - writeln!(dst, "version = \"{}\"", version.toml_display()).unwrap(); - }, - ), - ); + updater.update_file(file, &mut |_, src, dst| { + let package = parse_cargo_package(src); + if package.version_range.is_empty() { + dst.push_str(src); + UpdateStatus::Unchanged + } else { + dst.push_str(&src[..package.version_range.start]); + write!(dst, "\"{}\"", version.toml_display()).unwrap(); + dst.push_str(&src[package.version_range.end..]); + UpdateStatus::from_changed(src.get(package.version_range.clone()) != dst.get(package.version_range)) + } + }); } } diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 8e203ae51422..25ba2c720490 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -1,5 +1,5 @@ use crate::utils::{ - File, FileAction, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, panic_file, update_text_region_fn, + ErrAction, File, FileUpdater, RustSearcher, Token, UpdateMode, UpdateStatus, panic_action, update_text_region_fn, }; use itertools::Itertools; use std::collections::HashSet; @@ -203,7 +203,7 @@ fn read_src_with_module(src_root: &Path) -> impl use<'_> + Iterator e, - Err(ref e) => panic_file(e, FileAction::Read, src_root), + Err(ref e) => panic_action(e, ErrAction::Read, src_root), }; let path = e.path().as_os_str().as_encoded_bytes(); if let Some(path) = path.strip_suffix(b".rs") diff --git a/clippy_dev/src/utils.rs b/clippy_dev/src/utils.rs index fb2e25e655dc..255e36afe69c 100644 --- a/clippy_dev/src/utils.rs +++ b/clippy_dev/src/utils.rs @@ -1,12 +1,14 @@ use core::fmt::{self, Display}; +use core::ops::Range; use core::slice; use core::str::FromStr; use rustc_lexer::{self as lexer, FrontmatterAllowed}; use std::env; +use std::ffi::OsStr; use std::fs::{self, OpenOptions}; use std::io::{self, Read as _, Seek as _, SeekFrom, Write}; use std::path::{Path, PathBuf}; -use std::process::{self, ExitStatus}; +use std::process::{self, Command, ExitStatus, Stdio}; #[cfg(not(windows))] static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; @@ -14,15 +16,16 @@ static CARGO_CLIPPY_EXE: &str = "cargo-clippy"; static CARGO_CLIPPY_EXE: &str = "cargo-clippy.exe"; #[derive(Clone, Copy)] -pub enum FileAction { +pub enum ErrAction { Open, Read, Write, Create, Rename, Delete, + Run, } -impl FileAction { +impl ErrAction { fn as_str(self) -> &'static str { match self { Self::Open => "opening", @@ -31,13 +34,14 @@ impl FileAction { Self::Create => "creating", Self::Rename => "renaming", Self::Delete => "deleting", + Self::Run => "running", } } } #[cold] #[track_caller] -pub fn panic_file(err: &impl Display, action: FileAction, path: &Path) -> ! { +pub fn panic_action(err: &impl Display, action: ErrAction, path: &Path) -> ! { panic!("error {} `{}`: {}", action.as_str(), path.display(), *err) } @@ -53,7 +57,7 @@ impl<'a> File<'a> { let path = path.as_ref(); match options.open(path) { Ok(inner) => Self { inner, path }, - Err(e) => panic_file(&e, FileAction::Open, path), + Err(e) => panic_action(&e, ErrAction::Open, path), } } @@ -64,7 +68,7 @@ impl<'a> File<'a> { match options.open(path) { Ok(inner) => Some(Self { inner, path }), Err(e) if e.kind() == io::ErrorKind::NotFound => None, - Err(e) => panic_file(&e, FileAction::Open, path), + Err(e) => panic_action(&e, ErrAction::Open, path), } } @@ -82,7 +86,7 @@ impl<'a> File<'a> { pub fn read_append_to_string<'dst>(&mut self, dst: &'dst mut String) -> &'dst mut String { match self.inner.read_to_string(dst) { Ok(_) => {}, - Err(e) => panic_file(&e, FileAction::Read, self.path), + Err(e) => panic_action(&e, ErrAction::Read, self.path), } dst } @@ -104,7 +108,7 @@ impl<'a> File<'a> { Err(e) => Err(e), }; if let Err(e) = res { - panic_file(&e, FileAction::Write, self.path); + panic_action(&e, ErrAction::Write, self.path); } } } @@ -166,9 +170,83 @@ impl Version { } } +enum TomlPart<'a> { + Table(&'a str), + Value(&'a str, &'a str), +} + +fn toml_iter(s: &str) -> impl Iterator)> { + let mut pos = 0; + s.split('\n') + .map(move |s| { + let x = pos; + pos += s.len() + 1; + (x, s) + }) + .filter_map(|(pos, s)| { + if let Some(s) = s.strip_prefix('[') { + s.split_once(']').map(|(name, _)| (pos, TomlPart::Table(name))) + } else if matches!(s.bytes().next(), Some(b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_')) { + s.split_once('=').map(|(key, value)| (pos, TomlPart::Value(key, value))) + } else { + None + } + }) +} + +pub struct CargoPackage<'a> { + pub name: &'a str, + pub version_range: Range, + pub not_a_platform_range: Range, +} + +#[must_use] +pub fn parse_cargo_package(s: &str) -> CargoPackage<'_> { + let mut in_package = false; + let mut in_platform_deps = false; + let mut name = ""; + let mut version_range = 0..0; + let mut not_a_platform_range = 0..0; + for (offset, part) in toml_iter(s) { + match part { + TomlPart::Table(name) => { + if in_platform_deps { + not_a_platform_range.end = offset; + } + in_package = false; + in_platform_deps = false; + + match name.trim() { + "package" => in_package = true, + "target.'cfg(NOT_A_PLATFORM)'.dependencies" => { + in_platform_deps = true; + not_a_platform_range.start = offset; + }, + _ => {}, + } + }, + TomlPart::Value(key, value) if in_package => match key.trim_end() { + "name" => name = value.trim(), + "version" => { + version_range.start = offset + (value.len() - value.trim().len()) + key.len() + 1; + version_range.end = offset + key.len() + value.trim_end().len() + 1; + }, + _ => {}, + }, + TomlPart::Value(..) => {}, + } + } + CargoPackage { + name, + version_range, + not_a_platform_range, + } +} + pub struct ClippyInfo { pub path: PathBuf, pub version: Version, + pub has_intellij_hook: bool, } impl ClippyInfo { #[must_use] @@ -178,35 +256,21 @@ impl ClippyInfo { loop { path.push("Cargo.toml"); if let Some(mut file) = File::open_if_exists(&path, OpenOptions::new().read(true)) { - let mut in_package = false; - let mut is_clippy = false; - let mut version: Option = None; - - // Ad-hoc parsing to avoid dependencies. We control all the file so this - // isn't actually a problem - for line in file.read_to_cleared_string(&mut buf).lines() { - if line.starts_with('[') { - in_package = line.starts_with("[package]"); - } else if in_package && let Some((name, value)) = line.split_once('=') { - match name.trim() { - "name" => is_clippy = value.trim() == "\"clippy\"", - "version" - if let Some(value) = value.trim().strip_prefix('"') - && let Some(value) = value.strip_suffix('"') => - { - version = value.parse().ok(); - }, - _ => {}, - } + file.read_to_cleared_string(&mut buf); + let package = parse_cargo_package(&buf); + if package.name == "\"clippy\"" { + if let Some(version) = buf[package.version_range].strip_prefix('"') + && let Some(version) = version.strip_suffix('"') + && let Ok(version) = version.parse() + { + path.pop(); + return ClippyInfo { + path, + version, + has_intellij_hook: !package.not_a_platform_range.is_empty(), + }; } - } - - if is_clippy { - let Some(version) = version else { - panic!("error reading clippy version from {}", file.path.display()); - }; - path.pop(); - return ClippyInfo { path, version }; + panic!("error reading clippy version from `{}`", file.path.display()); } } @@ -259,6 +323,11 @@ impl UpdateMode { pub fn from_check(check: bool) -> Self { if check { Self::Check } else { Self::Change } } + + #[must_use] + pub fn is_check(self) -> bool { + matches!(self, Self::Check) + } } #[derive(Default)] @@ -547,7 +616,7 @@ pub fn try_rename_file(old_name: &Path, new_name: &Path) -> bool { match OpenOptions::new().create_new(true).write(true).open(new_name) { Ok(file) => drop(file), Err(e) if matches!(e.kind(), io::ErrorKind::AlreadyExists | io::ErrorKind::NotFound) => return false, - Err(ref e) => panic_file(e, FileAction::Create, new_name), + Err(ref e) => panic_action(e, ErrAction::Create, new_name), } match fs::rename(old_name, new_name) { Ok(()) => true, @@ -558,7 +627,7 @@ pub fn try_rename_file(old_name: &Path, new_name: &Path) -> bool { if matches!(e.kind(), io::ErrorKind::NotFound | io::ErrorKind::NotADirectory) { false } else { - panic_file(e, FileAction::Rename, old_name); + panic_action(e, ErrAction::Rename, old_name); } }, } @@ -569,7 +638,7 @@ pub fn try_rename_dir(old_name: &Path, new_name: &Path) -> bool { match fs::create_dir(new_name) { Ok(()) => {}, Err(e) if matches!(e.kind(), io::ErrorKind::AlreadyExists | io::ErrorKind::NotFound) => return false, - Err(ref e) => panic_file(e, FileAction::Create, new_name), + Err(ref e) => panic_action(e, ErrAction::Create, new_name), } // Windows can't reliably rename to an empty directory. #[cfg(windows)] @@ -584,14 +653,55 @@ pub fn try_rename_dir(old_name: &Path, new_name: &Path) -> bool { if matches!(e.kind(), io::ErrorKind::NotFound | io::ErrorKind::NotADirectory) { false } else { - panic_file(e, FileAction::Rename, old_name); + panic_action(e, ErrAction::Rename, old_name); } }, } } pub fn write_file(path: &Path, contents: &str) { - fs::write(path, contents).unwrap_or_else(|e| panic_file(&e, FileAction::Write, path)); + fs::write(path, contents).unwrap_or_else(|e| panic_action(&e, ErrAction::Write, path)); +} + +#[must_use] +pub fn run_with_output(path: &(impl AsRef + ?Sized), cmd: &mut Command) -> Vec { + fn f(path: &Path, cmd: &mut Command) -> Vec { + match cmd + .stdin(Stdio::null()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .output() + { + Ok(x) => match x.status.exit_ok() { + Ok(()) => x.stdout, + Err(ref e) => panic_action(e, ErrAction::Run, path), + }, + Err(ref e) => panic_action(e, ErrAction::Run, path), + } + } + f(path.as_ref(), cmd) +} + +pub fn run_with_args_split( + mut make_cmd: impl FnMut() -> Command, + mut run_cmd: impl FnMut(&mut Command), + args: impl Iterator>, +) { + let mut cmd = make_cmd(); + let mut len = 0; + for arg in args { + len += arg.as_ref().len(); + cmd.arg(arg); + // Very conservative limit + if len > 10000 { + run_cmd(&mut cmd); + cmd = make_cmd(); + len = 0; + } + } + if len != 0 { + run_cmd(&mut cmd); + } } #[expect(clippy::must_use_candidate)] @@ -599,7 +709,7 @@ pub fn delete_file_if_exists(path: &Path) -> bool { match fs::remove_file(path) { Ok(()) => true, Err(e) if matches!(e.kind(), io::ErrorKind::NotFound | io::ErrorKind::IsADirectory) => false, - Err(ref e) => panic_file(e, FileAction::Delete, path), + Err(ref e) => panic_action(e, ErrAction::Delete, path), } } @@ -607,6 +717,6 @@ pub fn delete_dir_if_exists(path: &Path) { match fs::remove_dir_all(path) { Ok(()) => {}, Err(e) if matches!(e.kind(), io::ErrorKind::NotFound | io::ErrorKind::NotADirectory) => {}, - Err(ref e) => panic_file(e, FileAction::Delete, path), + Err(ref e) => panic_action(e, ErrAction::Delete, path), } } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 7e3cb4042479..39e4e2e365ea 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,8 +1,6 @@ [package] name = "clippy_lints" -# begin autogenerated version version = "0.1.89" -# end autogenerated version description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index ac970e1c4b0a..615c0995e8b1 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,8 +1,6 @@ [package] name = "clippy_utils" -# begin autogenerated version version = "0.1.89" -# end autogenerated version edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.fixed b/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed similarity index 100% rename from tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.fixed rename to tests/ui/skip_rustfmt/non_expressive_names_error_recovery.fixed diff --git a/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs b/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs similarity index 100% rename from tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs rename to tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs diff --git a/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.stderr b/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr similarity index 80% rename from tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.stderr rename to tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr index e334ca5241eb..4998b9bd2cc4 100644 --- a/tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.stderr +++ b/tests/ui/skip_rustfmt/non_expressive_names_error_recovery.stderr @@ -1,5 +1,5 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `)` - --> tests/ui/syntax-error-recovery/non_expressive_names_error_recovery.rs:6:19 + --> tests/ui/skip_rustfmt/non_expressive_names_error_recovery.rs:6:19 | LL | fn aa(a: Aa