Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clippy_config/src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,8 @@ define_Conf! {
/// Use the Cognitive Complexity lint instead.
#[conf_deprecated("Please use `cognitive-complexity-threshold` instead", cognitive_complexity_threshold)]
cyclomatic_complexity_threshold: u64 = 25,
/// Lints to disable in tests.
disabled_in_tests: Vec<String> = Vec::new(),
/// The list of disallowed macros, written as fully qualified paths.
///
/// **Fields:**
Expand Down
53 changes: 51 additions & 2 deletions src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_span;
Expand All @@ -18,15 +20,19 @@ extern crate rustc_span;
#[cfg(feature = "jemalloc")]
extern crate tikv_jemalloc_sys as jemalloc_sys;

use clippy_config::Conf;
use clippy_utils::sym;
use declare_clippy_lint::LintListBuilder;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagInner;
use rustc_interface::interface;
use rustc_session::EarlyDiagCtxt;
use rustc_session::config::ErrorOutputType;
use rustc_session::parse::ParseSess;
use rustc_session::{EarlyDiagCtxt, Session};
use rustc_span::symbol::Symbol;

use std::env;
use std::fmt::Write;
use std::fs::read_to_string;
use std::path::Path;
use std::process::exit;
Expand Down Expand Up @@ -156,11 +162,14 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
(previous)(sess, lint_store);
}

let conf = clippy_config::Conf::read(sess, &conf_path);
let disabled = build_disabled_set(sess, conf);
set_post_expect_filter(sess, disabled);

let mut list_builder = LintListBuilder::default();
list_builder.insert(clippy_lints::declared_lints::LINTS);
list_builder.register(lint_store);

let conf = clippy_config::Conf::read(sess, &conf_path);
clippy_lints::register_lint_passes(lint_store, conf);

#[cfg(feature = "internal")]
Expand All @@ -181,6 +190,46 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
}
}

fn build_disabled_set(sess: &Session, conf: &'static Conf) -> FxHashSet<&'static str> {
if !sess.is_test_crate() {
return FxHashSet::default();
}
let disabled = conf
.disabled_in_tests
.iter()
.map(String::as_str)
.collect::<FxHashSet<_>>();
let declared_lint_names = clippy_lints::declared_lints::LINTS
.iter()
.map(|lint| lint.name_lower())
.collect::<FxHashSet<_>>();
#[allow(rustc::potential_query_instability)]
for &name in &disabled {
if !declared_lint_names.contains(name) {
let mut msg = format!("unknown lint `{name}`");
let replaced = name.replace('-', "_");
if declared_lint_names.contains(&replaced) {
writeln!(msg, ". Did you mean `{replaced}`?").unwrap();
}
sess.dcx().warn(msg);
}
}
disabled
}

#[allow(clippy::implicit_hasher)]
pub fn set_post_expect_filter(sess: &Session, disabled: FxHashSet<&'static str>) {
if !disabled.is_empty() {
sess.dcx().set_post_expect_filter(Box::new(move |diag: &DiagInner| {
diag.lint_name().is_some_and(|name| {
let name = name.strip_prefix("clippy::").unwrap_or(name);
disabled.contains(name)
})
}));
}
}

#[allow(clippy::ignored_unit_patterns)]
fn display_help() {
println!("{}", help_message());
}
Expand Down
1 change: 1 addition & 0 deletions tests/ui-toml/disabled_in_tests_expect/clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
disabled-in-tests = ["unwrap_used"]
17 changes: 17 additions & 0 deletions tests/ui-toml/disabled_in_tests_expect/expect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//@check-pass
//@compile-flags: --test

#![allow(clippy::unnecessary_literal_unwrap)]
#![warn(clippy::unwrap_used)]

fn main() {}

fn foo(opt: Option<i32>) {
#[expect(clippy::unwrap_used)]
opt.unwrap();
}

#[test]
fn unwrap_some() {
Some(()).unwrap();
}
Empty file.
1 change: 1 addition & 0 deletions tests/ui-toml/disabled_in_tests_typo/clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
disabled-in-tests = ["unwrap-used"]
4 changes: 4 additions & 0 deletions tests/ui-toml/disabled_in_tests_typo/typo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//@check-pass
//@compile-flags: --test

fn main() {}
4 changes: 4 additions & 0 deletions tests/ui-toml/disabled_in_tests_typo/typo.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
warning: unknown lint `unwrap-used`. Did you mean `unwrap_used`?

warning: 1 warning emitted

1 change: 1 addition & 0 deletions tests/ui-toml/disabled_in_tests_unwrap_used/clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
disabled-in-tests = ["unwrap_used"]
34 changes: 34 additions & 0 deletions tests/ui-toml/disabled_in_tests_unwrap_used/unwrap_used.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//@compile-flags: --test

#![warn(clippy::unwrap_used)]
#![warn(clippy::get_unwrap)]

fn main() {}

#[test]
fn test() {
let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
let _ = &boxed_slice[1];
//~^ get_unwrap
}

#[cfg(test)]
mod issue9612 {
// should not lint in `#[cfg(test)]` modules
#[test]
fn test_fn() {
let _a: u8 = 2.try_into().unwrap();
let _a: u8 = 3.try_into().expect("");

util();
}

#[allow(unconditional_panic)]
fn util() {
let _a: u8 = 4.try_into().unwrap();
let _a: u8 = 5.try_into().expect("");
// should still warn
let _ = &Box::new([0])[1];
//~^ get_unwrap
}
}
34 changes: 34 additions & 0 deletions tests/ui-toml/disabled_in_tests_unwrap_used/unwrap_used.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//@compile-flags: --test

#![warn(clippy::unwrap_used)]
#![warn(clippy::get_unwrap)]

fn main() {}

#[test]
fn test() {
let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
let _ = boxed_slice.get(1).unwrap();
//~^ get_unwrap
}

#[cfg(test)]
mod issue9612 {
// should not lint in `#[cfg(test)]` modules
#[test]
fn test_fn() {
let _a: u8 = 2.try_into().unwrap();
let _a: u8 = 3.try_into().expect("");

util();
}

#[allow(unconditional_panic)]
fn util() {
let _a: u8 = 4.try_into().unwrap();
let _a: u8 = 5.try_into().expect("");
// should still warn
let _ = Box::new([0]).get(1).unwrap();
//~^ get_unwrap
}
}
28 changes: 28 additions & 0 deletions tests/ui-toml/disabled_in_tests_unwrap_used/unwrap_used.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error: called `.get().unwrap()` on a slice
--> tests/ui-toml/disabled_in_tests_unwrap_used/unwrap_used.rs:11:13
|
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::get-unwrap` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::get_unwrap)]`
help: using `[]` is clearer and more concise
|
LL - let _ = boxed_slice.get(1).unwrap();
LL + let _ = &boxed_slice[1];
|

error: called `.get().unwrap()` on a slice
--> tests/ui-toml/disabled_in_tests_unwrap_used/unwrap_used.rs:31:17
|
LL | let _ = Box::new([0]).get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: using `[]` is clearer and more concise
|
LL - let _ = Box::new([0]).get(1).unwrap();
LL + let _ = &Box::new([0])[1];
|

error: aborting due to 2 previous errors

3 changes: 3 additions & 0 deletions tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
check-private-items
cognitive-complexity-threshold
const-literal-digits-threshold
disabled-in-tests
disallowed-macros
disallowed-methods
disallowed-names
Expand Down Expand Up @@ -131,6 +132,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
check-private-items
cognitive-complexity-threshold
const-literal-digits-threshold
disabled-in-tests
disallowed-macros
disallowed-methods
disallowed-names
Expand Down Expand Up @@ -226,6 +228,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
check-private-items
cognitive-complexity-threshold
const-literal-digits-threshold
disabled-in-tests
disallowed-macros
disallowed-methods
disallowed-names
Expand Down
Loading