From aaeeaa5330258081a8463f0458e35b85df1beafb Mon Sep 17 00:00:00 2001 From: flip1995 <9744647+flip1995@users.noreply.github.com> Date: Fri, 14 Sep 2018 12:38:09 +0200 Subject: [PATCH] Add internal lint compiler_lint_functions --- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/utils/internal_lints.rs | 82 ++++++++++++++++++++++-- clippy_lints/src/utils/paths.rs | 2 + 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3937e5cb9..ec00a13c0 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -293,8 +293,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box serde_api::Serde); reg.register_early_lint_pass(box utils::internal_lints::Clippy); - reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); + reg.register_late_lint_pass(box utils::internal_lints::CompilerLintFunctions::new()); reg.register_early_lint_pass(box utils::internal_lints::DefaultHashTypes::default()); + reg.register_late_lint_pass(box utils::internal_lints::LintWithoutLintPass::default()); reg.register_late_lint_pass(box utils::inspector::Pass); reg.register_late_lint_pass(box utils::author::Pass); reg.register_late_lint_pass(box types::TypePass); @@ -494,8 +495,9 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_lint_group("clippy::internal", Some("clippy_internal"), vec![ utils::internal_lints::CLIPPY_LINTS_INTERNAL, - utils::internal_lints::LINT_WITHOUT_LINT_PASS, + utils::internal_lints::COMPILER_LINT_FUNCTIONS, utils::internal_lints::DEFAULT_HASH_TYPES, + utils::internal_lints::LINT_WITHOUT_LINT_PASS, ]); reg.register_lint_group("clippy::all", Some("clippy"), vec![ diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 97a6922d3..8b3e75159 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -1,14 +1,16 @@ -use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, EarlyContext, EarlyLintPass}; -use crate::rustc::{declare_tool_lint, lint_array}; -use crate::rustc::hir::*; +use crate::utils::{ + match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty, +}; +use if_chain::if_chain; use crate::rustc::hir; use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; +use crate::rustc::hir::*; +use crate::rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass}; +use crate::rustc::{declare_tool_lint, lint_array}; use crate::rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use crate::utils::{match_qpath, paths, span_lint, span_lint_and_sugg}; -use crate::syntax::symbol::LocalInternedString; use crate::syntax::ast::{Crate as AstCrate, Ident, ItemKind, Name}; use crate::syntax::source_map::Span; - +use crate::syntax::symbol::LocalInternedString; /// **What it does:** Checks for various things we like to keep tidy in clippy. /// @@ -65,6 +67,29 @@ declare_clippy_lint! { "forbid HashMap and HashSet and suggest the FxHash* variants" } +/// **What it does:** Checks for calls to `cx.span_lint*` and suggests to use the `utils::*` +/// variant of the function. +/// +/// **Why is this bad?** The `utils::*` variants also add a link to the Clippy documentation to the +/// warning/error messages. +/// +/// **Known problems:** None. +/// +/// **Example:** +/// Bad: +/// ```rust +/// cx.span_lint(LINT_NAME, "message"); +/// ``` +/// +/// Good: +/// ```rust +/// utils::span_lint(cx, LINT_NAME, "message"); +/// ``` +declare_clippy_lint! { + pub COMPILER_LINT_FUNCTIONS, + internal, + "usage of the lint functions of the compiler instead of the utils::* variant" +} #[derive(Copy, Clone)] pub struct Clippy; @@ -245,3 +270,48 @@ impl EarlyLintPass for DefaultHashTypes { } } } + +#[derive(Clone, Default)] +pub struct CompilerLintFunctions { + map: FxHashMap, +} + +impl CompilerLintFunctions { + pub fn new() -> Self { + let mut map = FxHashMap::default(); + map.insert("span_lint".to_string(), "utils::span_lint".to_string()); + map.insert("struct_span_lint".to_string(), "utils::span_lint".to_string()); + map.insert("lint".to_string(), "utils::span_lint".to_string()); + map.insert("span_lint_note".to_string(), "utils::span_note_and_lint".to_string()); + map.insert("span_lint_help".to_string(), "utils::span_help_and_lint".to_string()); + Self { map } + } +} + +impl LintPass for CompilerLintFunctions { + fn get_lints(&self) -> LintArray { + lint_array!(COMPILER_LINT_FUNCTIONS) + } +} + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if_chain! { + if let ExprKind::MethodCall(ref path, _, ref args) = expr.node; + let fn_name = path.ident.as_str().to_string(); + if let Some(sugg) = self.map.get(&fn_name); + let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0])); + if match_type(cx, ty, &paths::EARLY_CONTEXT) + || match_type(cx, ty, &paths::LATE_CONTEXT); + then { + span_help_and_lint( + cx, + COMPILER_LINT_FUNCTIONS, + path.ident.span, + "usage of a compiler lint function", + &format!("Please use the Clippy variant of this function: `{}`", sugg), + ); + } + } + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0dea0462d..850361089 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -26,6 +26,7 @@ pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"]; pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"]; pub const DROP: [&str; 3] = ["core", "mem", "drop"]; pub const DURATION: [&str; 3] = ["core", "time", "Duration"]; +pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"]; pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; @@ -41,6 +42,7 @@ pub const INTO_ITERATOR: [&str; 4] = ["core", "iter", "traits", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"]; pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"]; +pub const LATE_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "LateContext"]; pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"]; pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"]; pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"];