Add internal lint compiler_lint_functions

This commit is contained in:
flip1995 2018-09-14 12:38:09 +02:00
parent f166b7d2f4
commit aaeeaa5330
No known key found for this signature in database
GPG key ID: 9F184E1164831181
3 changed files with 82 additions and 8 deletions

View file

@ -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![

View file

@ -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<String, String>,
}
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),
);
}
}
}
}

View file

@ -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"];