Skip to content

Commit 2a8dc2f

Browse files
committed
rework cargo.toml reading
instead of using the `MetadataCommand`, we read the `Cargo.toml` as a toml file and parse the `rust-version` field out of it. Also moved the validation point of the clippy.toml rust version to an earlier point, because we need it now.
1 parent 66b304e commit 2a8dc2f

File tree

1 file changed

+45
-23
lines changed

1 file changed

+45
-23
lines changed

clippy_lints/src/lib.rs

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ extern crate rustc_typeck;
5050
#[macro_use]
5151
extern crate clippy_utils;
5252

53-
use cargo_metadata::MetadataCommand;
5453
use clippy_utils::parse_msrv;
5554
use rustc_data_structures::fx::FxHashSet;
5655
use rustc_lint::LintId;
5756
use rustc_session::Session;
57+
use std::fs::File;
58+
use std::io::Read;
59+
use toml::Value;
5860

5961
/// Macro used to declare a Clippy lint.
6062
///
@@ -444,6 +446,23 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
444446
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv }));
445447
}
446448

449+
fn cargo_toml_msrv() -> Option<String> {
450+
if_chain! {
451+
if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR");
452+
if let Ok(mut file) = File::open(format!("{manifest_dir}/Cargo.toml"));
453+
let mut cargo_content_str = String::new();
454+
if let Ok(_) = file.read_to_string(&mut cargo_content_str);
455+
if let Ok(cargo_content) = toml::from_str::<Value>(&cargo_content_str);
456+
if let Some(package) = cargo_content.get("package");
457+
if let Some(rust_version) = package.get("rust-version");
458+
then {
459+
rust_version.as_str().map(str::to_string)
460+
} else {
461+
None
462+
}
463+
}
464+
}
465+
447466
#[doc(hidden)]
448467
pub fn read_conf(sess: &Session) -> Conf {
449468
let file_name = match utils::conf::lookup_conf_file() {
@@ -459,23 +478,35 @@ pub fn read_conf(sess: &Session) -> Conf {
459478
let TryConf { mut conf, errors } = utils::conf::read(&file_name);
460479
// all conf errors are non-fatal, we just use the default conf in case of error
461480
for error in errors {
462-
sess.struct_err(&format!(
481+
sess.err(&format!(
463482
"error reading Clippy's configuration file `{}`: {}",
464483
file_name.display(),
465484
error
466-
))
467-
.emit();
485+
));
468486
}
469487

470-
if conf.msrv.is_none() {
471-
// let's try to get msrv from `Cargo.toml`s field `rust-version`
472-
if let Ok(metadata) = MetadataCommand::new().no_deps().exec() {
473-
conf.msrv = metadata
474-
.packages
475-
.get(0)
476-
.and_then(|x| x.rust_version.as_ref())
477-
.and_then(|r| r.comparators.get(0))
478-
.map(|v| format!("{}.{}.{}", v.major, v.minor.unwrap_or(0), v.patch.unwrap_or(0)));
488+
let clippy_msrv = conf.msrv.as_ref().and_then(|s| {
489+
parse_msrv(s, None, None).or_else(|| {
490+
sess.err(&format!(
491+
"error reading Clippy's configuration file. `{}` is not a valid Rust version",
492+
s
493+
));
494+
None
495+
})
496+
});
497+
if let Some(cargo_msrv) = cargo_toml_msrv() {
498+
if let Some(clippy_msrv) = clippy_msrv {
499+
// if both files have an msrv, let's compare them and emit a warning if they differ
500+
let cargo_msrv = parse_msrv(&cargo_msrv, None, None).unwrap(); // cargo already check this for us
501+
if clippy_msrv != cargo_msrv {
502+
sess.warn(&format!(
503+
"The MSRV in `clippy.toml` and `Cargo.toml` differ. Using `{}`",
504+
clippy_msrv
505+
));
506+
}
507+
} else {
508+
// assign msrv from cargo.toml if clippy.toml hasn't set one alreay
509+
conf.msrv = Some(cargo_msrv);
479510
}
480511
}
481512

@@ -584,16 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
584615
store.register_late_pass(|| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
585616
store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
586617

587-
let msrv = conf.msrv.as_ref().and_then(|s| {
588-
parse_msrv(s, None, None).or_else(|| {
589-
sess.err(&format!(
590-
"error reading Clippy's configuration file. `{}` is not a valid Rust version",
591-
s
592-
));
593-
None
594-
})
595-
});
596-
618+
let msrv = conf.msrv.as_ref().and_then(|s| parse_msrv(s, None, None));
597619
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
598620
store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv)));
599621
store.register_late_pass(move || Box::new(methods::Methods::new(avoid_breaking_exported_api, msrv)));

0 commit comments

Comments
 (0)