Skip to content

Commit aaeeaa5

Browse files
committed
Add internal lint compiler_lint_functions
1 parent f166b7d commit aaeeaa5

File tree

3 files changed

+82
-8
lines changed

3 files changed

+82
-8
lines changed

clippy_lints/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
293293

294294
reg.register_late_lint_pass(box serde_api::Serde);
295295
reg.register_early_lint_pass(box utils::internal_lints::Clippy);
296-
reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default());
296+
reg.register_late_lint_pass(box utils::internal_lints::CompilerLintFunctions::new());
297297
reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::default());
298+
reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default());
298299
reg.register_late_lint_pass(box utils::inspector::Pass);
299300
reg.register_late_lint_pass(box utils::author::Pass);
300301
reg.register_late_lint_pass(box types::TypePass);
@@ -494,8 +495,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
494495

495496
reg.register_lint_group("clippy::internal", Some("clippy_internal"), vec![
496497
utils::internal_lints::CLIPPY_LINTS_INTERNAL,
497-
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
498+
utils::internal_lints::COMPILER_LINT_FUNCTIONS,
498499
utils::internal_lints::DEFAULT_HASH_TYPES,
500+
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
499501
]);
500502

501503
reg.register_lint_group("clippy::all", Some("clippy"), vec![

clippy_lints/src/utils/internal_lints.rs

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, EarlyContext, EarlyLintPass};
2-
use crate::rustc::{declare_tool_lint, lint_array};
3-
use crate::rustc::hir::*;
1+
use crate::utils::{
2+
match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
3+
};
4+
use if_chain::if_chain;
45
use crate::rustc::hir;
56
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
7+
use crate::rustc::hir::*;
8+
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
9+
use crate::rustc::{declare_tool_lint, lint_array};
610
use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet};
7-
use crate::utils::{match_qpath, paths, span_lint, span_lint_and_sugg};
8-
use crate::syntax::symbol::LocalInternedString;
911
use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name};
1012
use crate::syntax::source_map::Span;
11-
13+
use crate::syntax::symbol::LocalInternedString;
1214

1315
/// **What it does:** Checks for various things we like to keep tidy in clippy.
1416
///
@@ -65,6 +67,29 @@ declare_clippy_lint! {
6567
"forbid HashMap and HashSet and suggest the FxHash* variants"
6668
}
6769

70+
/// **What it does:** Checks for calls to `cx.span_lint*` and suggests to use the `utils::*`
71+
/// variant of the function.
72+
///
73+
/// **Why is this bad?** The `utils::*` variants also add a link to the Clippy documentation to the
74+
/// warning/error messages.
75+
///
76+
/// **Known problems:** None.
77+
///
78+
/// **Example:**
79+
/// Bad:
80+
/// ```rust
81+
/// cx.span_lint(LINT_NAME, "message");
82+
/// ```
83+
///
84+
/// Good:
85+
/// ```rust
86+
/// utils::span_lint(cx, LINT_NAME, "message");
87+
/// ```
88+
declare_clippy_lint! {
89+
pub COMPILER_LINT_FUNCTIONS,
90+
internal,
91+
"usage of the lint functions of the compiler instead of the utils::* variant"
92+
}
6893

6994
#[derive(Copy, Clone)]
7095
pub struct Clippy;
@@ -245,3 +270,48 @@ impl EarlyLintPass for DefaultHashTypes {
245270
}
246271
}
247272
}
273+
274+
#[derive(Clone, Default)]
275+
pub struct CompilerLintFunctions {
276+
map: FxHashMap<String, String>,
277+
}
278+
279+
impl CompilerLintFunctions {
280+
pub fn new() -> Self {
281+
let mut map = FxHashMap::default();
282+
map.insert("span_lint".to_string(), "utils::span_lint".to_string());
283+
map.insert("struct_span_lint".to_string(), "utils::span_lint".to_string());
284+
map.insert("lint".to_string(), "utils::span_lint".to_string());
285+
map.insert("span_lint_note".to_string(), "utils::span_note_and_lint".to_string());
286+
map.insert("span_lint_help".to_string(), "utils::span_help_and_lint".to_string());
287+
Self { map }
288+
}
289+
}
290+
291+
impl LintPass for CompilerLintFunctions {
292+
fn get_lints(&self) -> LintArray {
293+
lint_array!(COMPILER_LINT_FUNCTIONS)
294+
}
295+
}
296+
297+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
298+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
299+
if_chain! {
300+
if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
301+
let fn_name = path.ident.as_str().to_string();
302+
if let Some(sugg) = self.map.get(&fn_name);
303+
let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
304+
if match_type(cx, ty, &paths::EARLY_CONTEXT)
305+
|| match_type(cx, ty, &paths::LATE_CONTEXT);
306+
then {
307+
span_help_and_lint(
308+
cx,
309+
COMPILER_LINT_FUNCTIONS,
310+
path.ident.span,
311+
"usage of a compiler lint function",
312+
&format!("Please use the Clippy variant of this function: `{}`", sugg),
313+
);
314+
}
315+
}
316+
}
317+
}

clippy_lints/src/utils/paths.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
2626
pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
2727
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
2828
pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
29+
pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"];
2930
pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
3031
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
3132
pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"];
@@ -41,6 +42,7 @@ pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"];
4142
pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
4243
pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
4344
pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"];
45+
pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"];
4446
pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
4547
pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"];
4648
pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"];

0 commit comments

Comments
 (0)