mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 21:23:56 +00:00
add disallowed_method lint
This commit is contained in:
parent
cc1998f7b3
commit
1479c18396
10 changed files with 199 additions and 0 deletions
|
@ -1559,6 +1559,7 @@ Released 2018-09-13
|
|||
[`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
|
||||
[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
|
||||
[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
|
||||
[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
|
||||
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
|
||||
[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
|
||||
[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
|
||||
|
|
75
clippy_lints/src/disallowed_method.rs
Normal file
75
clippy_lints/src/disallowed_method.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use crate::utils::span_lint;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_lint::{LateLintPass, LateContext};
|
||||
use rustc_session::{impl_lint_pass, declare_tool_lint};
|
||||
use rustc_hir::*;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Lints for specific trait methods defined in clippy.toml
|
||||
///
|
||||
/// **Why is this bad?** Some methods are undesirable in certain contexts,
|
||||
/// and it would be beneficial to lint for them as needed.
|
||||
///
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
/// // example code where clippy issues a warning
|
||||
/// foo.bad_method(); // Foo is disallowed
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// // example code which does not raise clippy warning
|
||||
/// GoodStruct.bad_method(); // not disallowed
|
||||
/// ```
|
||||
pub DISALLOWED_METHOD,
|
||||
nursery,
|
||||
"used disallowed method call"
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DisallowedMethod {
|
||||
disallowed: FxHashSet<Vec<Symbol>>,
|
||||
}
|
||||
|
||||
impl DisallowedMethod {
|
||||
pub fn new(disallowed: FxHashSet<String>) -> Self {
|
||||
Self {
|
||||
disallowed: disallowed.iter()
|
||||
.map(|s| {
|
||||
s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>()
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]);
|
||||
|
||||
impl <'tcx> LateLintPass<'tcx> for DisallowedMethod {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if let ExprKind::MethodCall(path, _, _args, _) = &expr.kind {
|
||||
let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
|
||||
|
||||
let method_call = cx.get_def_path(def_id);
|
||||
if self.disallowed.contains(&method_call) {
|
||||
span_lint(
|
||||
cx,
|
||||
DISALLOWED_METHOD,
|
||||
expr.span,
|
||||
&format!(
|
||||
"Use of a disallowed method `{}`",
|
||||
method_call
|
||||
.iter()
|
||||
.map(|s| s.to_ident_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("::"),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -175,6 +175,7 @@ mod dbg_macro;
|
|||
mod default_trait_access;
|
||||
mod dereference;
|
||||
mod derive;
|
||||
mod disallowed_method;
|
||||
mod doc;
|
||||
mod double_comparison;
|
||||
mod double_parens;
|
||||
|
@ -525,6 +526,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&derive::DERIVE_ORD_XOR_PARTIAL_ORD,
|
||||
&derive::EXPL_IMPL_CLONE_ON_COPY,
|
||||
&derive::UNSAFE_DERIVE_DESERIALIZE,
|
||||
&disallowed_method::DISALLOWED_METHOD,
|
||||
&doc::DOC_MARKDOWN,
|
||||
&doc::MISSING_ERRORS_DOC,
|
||||
&doc::MISSING_SAFETY_DOC,
|
||||
|
@ -1118,6 +1120,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
|
||||
store.register_late_pass(|| box manual_strip::ManualStrip);
|
||||
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
|
||||
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
|
||||
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(disallowed_methods.clone()));
|
||||
|
||||
|
||||
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
|
||||
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
|
||||
|
@ -1807,6 +1812,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
|
||||
LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
|
||||
LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
|
||||
LintId::of(&disallowed_method::DISALLOWED_METHOD),
|
||||
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
|
||||
LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
|
||||
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
|
||||
|
|
|
@ -164,6 +164,8 @@ define_Conf! {
|
|||
(max_fn_params_bools, "max_fn_params_bools": u64, 3),
|
||||
/// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
|
||||
(warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false),
|
||||
/// Lint: DISALLOWED_METHOD. The list of blacklisted methods to lint about. NB: `bar` is not here since it has legitimate uses
|
||||
(disallowed_methods, "disallowed_methods": Vec<String>, ["disallowed_method::Foo::bad_method", "disallowed_method::Baz::bad_method", "disallowed_method::Quux::bad_method"].iter().map(ToString::to_string).collect()),
|
||||
}
|
||||
|
||||
impl Default for Conf {
|
||||
|
|
|
@ -381,6 +381,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
|
|||
deprecation: None,
|
||||
module: "derive",
|
||||
},
|
||||
Lint {
|
||||
name: "disallowed_method",
|
||||
group: "nursery",
|
||||
desc: "default lint description",
|
||||
deprecation: None,
|
||||
module: "disallowed_method",
|
||||
},
|
||||
Lint {
|
||||
name: "diverging_sub_expression",
|
||||
group: "complexity",
|
||||
|
|
1
tests/ui-toml/toml_disallowed_method/clippy.toml
Normal file
1
tests/ui-toml/toml_disallowed_method/clippy.toml
Normal file
|
@ -0,0 +1 @@
|
|||
disallowed-methods = ["core::iter::traits::iterator::Iterator::sum", "regex::re_unicode::Regex::is_match"]
|
|
@ -0,0 +1,13 @@
|
|||
#![warn(clippy::disallowed_method)]
|
||||
|
||||
extern crate regex;
|
||||
use regex::Regex;
|
||||
|
||||
fn main() {
|
||||
let a = vec![1, 2, 3, 4];
|
||||
let re = Regex::new(r"ab.*c").unwrap();
|
||||
|
||||
re.is_match("abc");
|
||||
|
||||
a.iter().sum::<i32>();
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
error: Use of a disallowed method `regex::re_unicode::Regex::is_match`
|
||||
--> $DIR/conf_disallowed_method.rs:10:5
|
||||
|
|
||||
LL | re.is_match("abc");
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::disallowed-method` implied by `-D warnings`
|
||||
|
||||
error: Use of a disallowed method `core::iter::traits::iterator::Iterator::sum`
|
||||
--> $DIR/conf_disallowed_method.rs:12:5
|
||||
|
|
||||
LL | a.iter().sum::<i32>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
56
tests/ui/disallowed_method.rs
Normal file
56
tests/ui/disallowed_method.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
#![warn(clippy::disallowed_method)]
|
||||
#![allow(clippy::no_effect, clippy::many_single_char_names)]
|
||||
|
||||
struct ImplStruct;
|
||||
|
||||
trait Baz {
|
||||
fn bad_method(self);
|
||||
}
|
||||
|
||||
impl Baz for ImplStruct {
|
||||
fn bad_method(self) {}
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn bad_method(self) {}
|
||||
}
|
||||
|
||||
struct StaticStruct;
|
||||
|
||||
trait Quux {
|
||||
fn bad_method();
|
||||
}
|
||||
|
||||
impl Quux for StaticStruct {
|
||||
fn bad_method() {}
|
||||
}
|
||||
|
||||
struct NormalStruct;
|
||||
|
||||
impl NormalStruct {
|
||||
fn bad_method(self) {}
|
||||
}
|
||||
|
||||
struct AttrStruct {
|
||||
bad_method: i32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = ImplStruct;
|
||||
let f = Foo;
|
||||
let c = ImplStruct;
|
||||
let n = NormalStruct;
|
||||
let a = AttrStruct{ bad_method: 5 };
|
||||
|
||||
// lint these
|
||||
b.bad_method();
|
||||
c.bad_method();
|
||||
f.bad_method();
|
||||
// these are good
|
||||
// good because not a method call (ExprKind => Call)
|
||||
StaticStruct::bad_method();
|
||||
n.bad_method();
|
||||
a.bad_method;
|
||||
}
|
22
tests/ui/disallowed_method.stderr
Normal file
22
tests/ui/disallowed_method.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error: Use of a disallowed method `disallowed_method::Baz::bad_method`
|
||||
--> $DIR/disallowed_method.rs:48:5
|
||||
|
|
||||
LL | b.bad_method();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::disallowed-method` implied by `-D warnings`
|
||||
|
||||
error: Use of a disallowed method `disallowed_method::Baz::bad_method`
|
||||
--> $DIR/disallowed_method.rs:49:5
|
||||
|
|
||||
LL | c.bad_method();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: Use of a disallowed method `disallowed_method::Foo::bad_method`
|
||||
--> $DIR/disallowed_method.rs:50:5
|
||||
|
|
||||
LL | f.bad_method();
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in a new issue