Skip to content

Commit ea079eb

Browse files
committed
Auto merge of #6081 - ilknarf:master, r=matthiaskrgr
New Lint: disallowed_method Fixes #6073 I added a `disallowed_method` lint that works similar to `blacklisted_name`, e.g allows config-defined disallowed method calls. This lint allows advanced users to patch in undesired method calls for specific projects. It basically uses the DefId of method calls and matches it to parsed strings. Is there an alternative approach that could use more easily digestible configuration strings? All tests pass as expected except for a linting error on `ui/redundant_pattern_matching_option`, which I am not sure how to resolve since I don't think I changed anything affecting it. changelog: Add disallowed_method lint to warn on user-defined method calls
2 parents b64d21d + 5f7b643 commit ea079eb

File tree

10 files changed

+121
-2
lines changed

10 files changed

+121
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,7 @@ Released 2018-09-13
15591559
[`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
15601560
[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
15611561
[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
1562+
[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
15621563
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
15631564
[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
15641565
[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
77

8-
[There are over 350 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
8+
[There are over 400 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
99

1010
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1111

clippy_lints/src/disallowed_method.rs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::utils::span_lint;
2+
3+
use rustc_data_structures::fx::FxHashSet;
4+
use rustc_hir::{Expr, ExprKind};
5+
use rustc_lint::{LateContext, LateLintPass};
6+
use rustc_session::{declare_tool_lint, impl_lint_pass};
7+
use rustc_span::Symbol;
8+
9+
declare_clippy_lint! {
10+
/// **What it does:** Lints for specific trait methods defined in clippy.toml
11+
///
12+
/// **Why is this bad?** Some methods are undesirable in certain contexts,
13+
/// and it would be beneficial to lint for them as needed.
14+
///
15+
/// **Known problems:** None.
16+
///
17+
/// **Example:**
18+
///
19+
/// ```rust,ignore
20+
/// // example code where clippy issues a warning
21+
/// foo.bad_method(); // Foo::bad_method is disallowed in the configuration
22+
/// ```
23+
/// Use instead:
24+
/// ```rust,ignore
25+
/// // example code which does not raise clippy warning
26+
/// goodStruct.bad_method(); // GoodStruct::bad_method is not disallowed
27+
/// ```
28+
pub DISALLOWED_METHOD,
29+
nursery,
30+
"use of a disallowed method call"
31+
}
32+
33+
#[derive(Clone, Debug)]
34+
pub struct DisallowedMethod {
35+
disallowed: FxHashSet<Vec<Symbol>>,
36+
}
37+
38+
impl DisallowedMethod {
39+
pub fn new(disallowed: &FxHashSet<String>) -> Self {
40+
Self {
41+
disallowed: disallowed
42+
.iter()
43+
.map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>())
44+
.collect(),
45+
}
46+
}
47+
}
48+
49+
impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]);
50+
51+
impl<'tcx> LateLintPass<'tcx> for DisallowedMethod {
52+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
53+
if let ExprKind::MethodCall(_path, _, _args, _) = &expr.kind {
54+
let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
55+
56+
let method_call = cx.get_def_path(def_id);
57+
if self.disallowed.contains(&method_call) {
58+
let method = method_call
59+
.iter()
60+
.map(|s| s.to_ident_string())
61+
.collect::<Vec<_>>()
62+
.join("::");
63+
64+
span_lint(
65+
cx,
66+
DISALLOWED_METHOD,
67+
expr.span,
68+
&format!("use of a disallowed method `{}`", method),
69+
);
70+
}
71+
}
72+
}
73+
}

clippy_lints/src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ mod dbg_macro;
175175
mod default_trait_access;
176176
mod dereference;
177177
mod derive;
178+
mod disallowed_method;
178179
mod doc;
179180
mod double_comparison;
180181
mod double_parens;
@@ -525,6 +526,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
525526
&derive::DERIVE_ORD_XOR_PARTIAL_ORD,
526527
&derive::EXPL_IMPL_CLONE_ON_COPY,
527528
&derive::UNSAFE_DERIVE_DESERIALIZE,
529+
&disallowed_method::DISALLOWED_METHOD,
528530
&doc::DOC_MARKDOWN,
529531
&doc::MISSING_ERRORS_DOC,
530532
&doc::MISSING_SAFETY_DOC,
@@ -1118,6 +1120,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11181120
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
11191121
store.register_late_pass(|| box manual_strip::ManualStrip);
11201122
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
1123+
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
1124+
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
1125+
11211126

11221127
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
11231128
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1807,6 +1812,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
18071812
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
18081813
LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
18091814
LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
1815+
LintId::of(&disallowed_method::DISALLOWED_METHOD),
18101816
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
18111817
LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
18121818
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),

clippy_lints/src/utils/conf.rs

+2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ define_Conf! {
164164
(max_fn_params_bools, "max_fn_params_bools": u64, 3),
165165
/// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
166166
(warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false),
167+
/// Lint: DISALLOWED_METHOD. The list of blacklisted methods to lint about. NB: `bar` is not here since it has legitimate uses
168+
(disallowed_methods, "disallowed_methods": Vec<String>, Vec::<String>::new()),
167169
}
168170

169171
impl Default for Conf {

src/lintlist/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
381381
deprecation: None,
382382
module: "derive",
383383
},
384+
Lint {
385+
name: "disallowed_method",
386+
group: "nursery",
387+
desc: "use of a disallowed method call",
388+
deprecation: None,
389+
module: "disallowed_method",
390+
},
384391
Lint {
385392
name: "diverging_sub_expression",
386393
group: "complexity",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
disallowed-methods = ["core::iter::traits::iterator::Iterator::sum", "regex::re_unicode::Regex::is_match"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![warn(clippy::disallowed_method)]
2+
3+
extern crate regex;
4+
use regex::Regex;
5+
6+
fn main() {
7+
let a = vec![1, 2, 3, 4];
8+
let re = Regex::new(r"ab.*c").unwrap();
9+
10+
re.is_match("abc");
11+
12+
a.iter().sum::<i32>();
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: use of a disallowed method `regex::re_unicode::Regex::is_match`
2+
--> $DIR/conf_disallowed_method.rs:10:5
3+
|
4+
LL | re.is_match("abc");
5+
| ^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::disallowed-method` implied by `-D warnings`
8+
9+
error: use of a disallowed method `core::iter::traits::iterator::Iterator::sum`
10+
--> $DIR/conf_disallowed_method.rs:12:5
11+
|
12+
LL | a.iter().sum::<i32>();
13+
| ^^^^^^^^^^^^^^^^^^^^^
14+
15+
error: aborting due to 2 previous errors
16+
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `third-party` at line 5 column 1
1+
error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `third-party` at line 5 column 1
22

33
error: aborting due to previous error
44

0 commit comments

Comments
 (0)