Auto merge of #9707 - Alexendoo:file-depinfo, r=flip1995
Track `clippy.toml` and `Cargo.toml` in `file_depinfo` Causes cargo to re-run clippy when those paths are modified Also tracks the path to `clippy-driver` in debug mode to remove the workarounds in `cargo dev lint` and `lintcheck` (cc `@matthiaskrgr)` changelog: Automatically re-run Clippy if `Cargo.toml` or `clippy.toml` are modified Fixes #2130 Fixes #8512 r? `@flip1995`
This commit is contained in:
commit
5e298706f4
@ -10,7 +10,6 @@ indoc = "1.0"
|
||||
itertools = "0.10.1"
|
||||
opener = "0.5"
|
||||
shell-escape = "0.1"
|
||||
tempfile = "3.2"
|
||||
walkdir = "2.3"
|
||||
|
||||
[features]
|
||||
|
@ -36,20 +36,12 @@ pub fn run<'a>(path: &str, args: impl Iterator<Item = &'a String>) {
|
||||
} else {
|
||||
exit_if_err(Command::new("cargo").arg("build").status());
|
||||
|
||||
// Run in a tempdir as changes to clippy do not retrigger linting
|
||||
let target = tempfile::Builder::new()
|
||||
.prefix("clippy")
|
||||
.tempdir()
|
||||
.expect("failed to create tempdir");
|
||||
|
||||
let status = Command::new(cargo_clippy_path())
|
||||
.arg("clippy")
|
||||
.args(args)
|
||||
.current_dir(path)
|
||||
.env("CARGO_TARGET_DIR", target.as_ref())
|
||||
.status();
|
||||
|
||||
target.close().expect("failed to remove tempdir");
|
||||
exit_if_err(status);
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,9 @@
|
||||
#[macro_use]
|
||||
extern crate declare_clippy_lint;
|
||||
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clippy_utils::parse_msrv;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_lint::{Lint, LintId};
|
||||
@ -304,8 +307,8 @@
|
||||
mod zero_sized_map_values;
|
||||
// end lints modules, do not remove this comment, it’s used in `update_lints`
|
||||
|
||||
pub use crate::utils::conf::Conf;
|
||||
use crate::utils::conf::{format_error, TryConf};
|
||||
pub use crate::utils::conf::{lookup_conf_file, Conf};
|
||||
|
||||
/// Register all pre expansion lints
|
||||
///
|
||||
@ -362,8 +365,8 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn read_conf(sess: &Session) -> Conf {
|
||||
let file_name = match utils::conf::lookup_conf_file() {
|
||||
pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
|
||||
let file_name = match path {
|
||||
Ok(Some(path)) => path,
|
||||
Ok(None) => return Conf::default(),
|
||||
Err(error) => {
|
||||
@ -373,7 +376,7 @@ pub fn read_conf(sess: &Session) -> Conf {
|
||||
},
|
||||
};
|
||||
|
||||
let TryConf { conf, errors, warnings } = utils::conf::read(&file_name);
|
||||
let TryConf { conf, errors, warnings } = utils::conf::read(file_name);
|
||||
// all conf errors are non-fatal, we just use the default conf in case of error
|
||||
for error in errors {
|
||||
sess.err(format!(
|
||||
|
@ -401,6 +401,10 @@ pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
|
||||
}
|
||||
|
||||
/// Search for the configuration file.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns any unexpected filesystem error encountered when searching for the config file
|
||||
pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
|
||||
/// Possible filename to search for.
|
||||
const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"];
|
||||
|
@ -544,34 +544,6 @@ fn gather_stats(clippy_warnings: &[ClippyWarning]) -> (String, HashMap<&String,
|
||||
(stats_string, counter)
|
||||
}
|
||||
|
||||
/// check if the latest modification of the logfile is older than the modification date of the
|
||||
/// clippy binary, if this is true, we should clean the lintchec shared target directory and recheck
|
||||
fn lintcheck_needs_rerun(lintcheck_logs_path: &Path, paths: [&Path; 2]) -> bool {
|
||||
if !lintcheck_logs_path.exists() {
|
||||
return true;
|
||||
}
|
||||
|
||||
let clippy_modified: std::time::SystemTime = {
|
||||
let [cargo, driver] = paths.map(|p| {
|
||||
std::fs::metadata(p)
|
||||
.expect("failed to get metadata of file")
|
||||
.modified()
|
||||
.expect("failed to get modification date")
|
||||
});
|
||||
// the oldest modification of either of the binaries
|
||||
std::cmp::max(cargo, driver)
|
||||
};
|
||||
|
||||
let logs_modified: std::time::SystemTime = std::fs::metadata(lintcheck_logs_path)
|
||||
.expect("failed to get metadata of file")
|
||||
.modified()
|
||||
.expect("failed to get modification date");
|
||||
|
||||
// time is represented in seconds since X
|
||||
// logs_modified 2 and clippy_modified 5 means clippy binary is older and we need to recheck
|
||||
logs_modified < clippy_modified
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn main() {
|
||||
// We're being executed as a `RUSTC_WRAPPER` as part of `--recursive`
|
||||
@ -594,23 +566,6 @@ fn main() {
|
||||
let cargo_clippy_path = fs::canonicalize(format!("target/debug/cargo-clippy{EXE_SUFFIX}")).unwrap();
|
||||
let clippy_driver_path = fs::canonicalize(format!("target/debug/clippy-driver{EXE_SUFFIX}")).unwrap();
|
||||
|
||||
// if the clippy bin is newer than our logs, throw away target dirs to force clippy to
|
||||
// refresh the logs
|
||||
if lintcheck_needs_rerun(
|
||||
&config.lintcheck_results_path,
|
||||
[&cargo_clippy_path, &clippy_driver_path],
|
||||
) {
|
||||
let shared_target_dir = "target/lintcheck/shared_target_dir";
|
||||
// if we get an Err here, the shared target dir probably does simply not exist
|
||||
if let Ok(metadata) = std::fs::metadata(shared_target_dir) {
|
||||
if metadata.is_dir() {
|
||||
println!("Clippy is newer than lint check logs, clearing lintcheck shared target dir...");
|
||||
std::fs::remove_dir_all(shared_target_dir)
|
||||
.expect("failed to remove target/lintcheck/shared_target_dir");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assert that clippy is found
|
||||
assert!(
|
||||
cargo_clippy_path.is_file(),
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![feature(rustc_private)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(once_cell)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||
@ -71,6 +72,32 @@ fn track_clippy_args(parse_sess: &mut ParseSess, args_env_var: &Option<String>)
|
||||
));
|
||||
}
|
||||
|
||||
/// Track files that may be accessed at runtime in `file_depinfo` so that cargo will re-run clippy
|
||||
/// when any of them are modified
|
||||
fn track_files(parse_sess: &mut ParseSess, conf_path_string: Option<String>) {
|
||||
let file_depinfo = parse_sess.file_depinfo.get_mut();
|
||||
|
||||
// Used by `clippy::cargo` lints and to determine the MSRV. `cargo clippy` executes `clippy-driver`
|
||||
// with the current directory set to `CARGO_MANIFEST_DIR` so a relative path is fine
|
||||
if Path::new("Cargo.toml").exists() {
|
||||
file_depinfo.insert(Symbol::intern("Cargo.toml"));
|
||||
}
|
||||
|
||||
// `clippy.toml`
|
||||
if let Some(path) = conf_path_string {
|
||||
file_depinfo.insert(Symbol::intern(&path));
|
||||
}
|
||||
|
||||
// During development track the `clippy-driver` executable so that cargo will re-run clippy whenever
|
||||
// it is rebuilt
|
||||
if cfg!(debug_assertions)
|
||||
&& let Ok(current_exe) = env::current_exe()
|
||||
&& let Some(current_exe) = current_exe.to_str()
|
||||
{
|
||||
file_depinfo.insert(Symbol::intern(current_exe));
|
||||
}
|
||||
}
|
||||
|
||||
struct DefaultCallbacks;
|
||||
impl rustc_driver::Callbacks for DefaultCallbacks {}
|
||||
|
||||
@ -97,10 +124,18 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
|
||||
// JUSTIFICATION: necessary in clippy driver to set `mir_opt_level`
|
||||
#[allow(rustc::bad_opt_access)]
|
||||
fn config(&mut self, config: &mut interface::Config) {
|
||||
let conf_path = clippy_lints::lookup_conf_file();
|
||||
let conf_path_string = if let Ok(Some(path)) = &conf_path {
|
||||
path.to_str().map(String::from)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let previous = config.register_lints.take();
|
||||
let clippy_args_var = self.clippy_args_var.take();
|
||||
config.parse_sess_created = Some(Box::new(move |parse_sess| {
|
||||
track_clippy_args(parse_sess, &clippy_args_var);
|
||||
track_files(parse_sess, conf_path_string);
|
||||
}));
|
||||
config.register_lints = Some(Box::new(move |sess, lint_store| {
|
||||
// technically we're ~guaranteed that this is none but might as well call anything that
|
||||
@ -109,7 +144,7 @@ fn config(&mut self, config: &mut interface::Config) {
|
||||
(previous)(sess, lint_store);
|
||||
}
|
||||
|
||||
let conf = clippy_lints::read_conf(sess);
|
||||
let conf = clippy_lints::read_conf(sess, &conf_path);
|
||||
clippy_lints::register_plugins(lint_store, sess, &conf);
|
||||
clippy_lints::register_pre_expansion_lints(lint_store, sess, &conf);
|
||||
clippy_lints::register_renamed(lint_store);
|
||||
|
Loading…
Reference in New Issue
Block a user