mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 07:00:55 +00:00
Merge pull request #3187 from flip1995/internal_fn
New internal lint: compiler_lint_functions
This commit is contained in:
commit
b6707ffc42
4 changed files with 100 additions and 21 deletions
|
@ -1,6 +1,7 @@
|
||||||
use crate::syntax::ast::*;
|
use crate::syntax::ast::*;
|
||||||
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass};
|
use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
|
||||||
use crate::rustc::{declare_tool_lint, lint_array};
|
use crate::rustc::{declare_tool_lint, lint_array};
|
||||||
|
use crate::utils::span_lint;
|
||||||
|
|
||||||
/// **What it does:** Checks for unnecessary double parentheses.
|
/// **What it does:** Checks for unnecessary double parentheses.
|
||||||
///
|
///
|
||||||
|
@ -35,20 +36,20 @@ impl EarlyLintPass for DoubleParens {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprKind::Paren(ref in_paren) => match in_paren.node {
|
ExprKind::Paren(ref in_paren) => match in_paren.node {
|
||||||
ExprKind::Paren(_) | ExprKind::Tup(_) => {
|
ExprKind::Paren(_) | ExprKind::Tup(_) => {
|
||||||
cx.span_lint(DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses");
|
span_lint(cx, DOUBLE_PARENS, expr.span, "Consider removing unnecessary double parentheses");
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
ExprKind::Call(_, ref params) => if params.len() == 1 {
|
ExprKind::Call(_, ref params) => if params.len() == 1 {
|
||||||
let param = ¶ms[0];
|
let param = ¶ms[0];
|
||||||
if let ExprKind::Paren(_) = param.node {
|
if let ExprKind::Paren(_) = param.node {
|
||||||
cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses");
|
span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::MethodCall(_, ref params) => if params.len() == 2 {
|
ExprKind::MethodCall(_, ref params) => if params.len() == 2 {
|
||||||
let param = ¶ms[1];
|
let param = ¶ms[1];
|
||||||
if let ExprKind::Paren(_) = param.node {
|
if let ExprKind::Paren(_) = param.node {
|
||||||
cx.span_lint(DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses");
|
span_lint(cx, DOUBLE_PARENS, param.span, "Consider removing unnecessary double parentheses");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
|
|
@ -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_late_lint_pass(box serde_api::Serde);
|
||||||
reg.register_early_lint_pass(box utils::internal_lints::Clippy);
|
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_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::inspector::Pass);
|
||||||
reg.register_late_lint_pass(box utils::author::Pass);
|
reg.register_late_lint_pass(box utils::author::Pass);
|
||||||
reg.register_late_lint_pass(box types::TypePass);
|
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![
|
reg.register_lint_group("clippy::internal", Some("clippy_internal"), vec![
|
||||||
utils::internal_lints::CLIPPY_LINTS_INTERNAL,
|
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::DEFAULT_HASH_TYPES,
|
||||||
|
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
reg.register_lint_group("clippy::all", Some("clippy"), vec![
|
reg.register_lint_group("clippy::all", Some("clippy"), vec![
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass, EarlyContext, EarlyLintPass};
|
use crate::utils::{
|
||||||
use crate::rustc::{declare_tool_lint, lint_array};
|
match_qpath, match_type, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
|
||||||
use crate::rustc::hir::*;
|
};
|
||||||
|
use if_chain::if_chain;
|
||||||
use crate::rustc::hir;
|
use crate::rustc::hir;
|
||||||
use crate::rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
|
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::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::ast::{Crate as AstCrate, Ident, ItemKind, Name};
|
||||||
use crate::syntax::source_map::Span;
|
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.
|
/// **What it does:** Checks for various things we like to keep tidy in clippy.
|
||||||
///
|
///
|
||||||
|
@ -23,7 +25,6 @@ declare_clippy_lint! {
|
||||||
"various things that will negatively affect your clippy experience"
|
"various things that will negatively affect your clippy experience"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// **What it does:** Ensures every lint is associated to a `LintPass`.
|
/// **What it does:** Ensures every lint is associated to a `LintPass`.
|
||||||
///
|
///
|
||||||
/// **Why is this bad?** The compiler only knows lints via a `LintPass`. Without
|
/// **Why is this bad?** The compiler only knows lints via a `LintPass`. Without
|
||||||
|
@ -53,7 +54,6 @@ declare_clippy_lint! {
|
||||||
"declaring a lint without associating it in a LintPass"
|
"declaring a lint without associating it in a LintPass"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// **What it does:** Checks for the presence of the default hash types "HashMap" or "HashSet"
|
/// **What it does:** Checks for the presence of the default hash types "HashMap" or "HashSet"
|
||||||
/// and recommends the FxHash* variants.
|
/// and recommends the FxHash* variants.
|
||||||
///
|
///
|
||||||
|
@ -65,6 +65,29 @@ declare_clippy_lint! {
|
||||||
"forbid HashMap and HashSet and suggest the FxHash* variants"
|
"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)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Clippy;
|
pub struct Clippy;
|
||||||
|
@ -119,7 +142,6 @@ pub struct LintWithoutLintPass {
|
||||||
registered_lints: FxHashSet<Name>,
|
registered_lints: FxHashSet<Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl LintPass for LintWithoutLintPass {
|
impl LintPass for LintWithoutLintPass {
|
||||||
fn get_lints(&self) -> LintArray {
|
fn get_lints(&self) -> LintArray {
|
||||||
lint_array!(LINT_WITHOUT_LINT_PASS)
|
lint_array!(LINT_WITHOUT_LINT_PASS)
|
||||||
|
@ -171,7 +193,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn is_lint_ref_type(ty: &Ty) -> bool {
|
fn is_lint_ref_type(ty: &Ty) -> bool {
|
||||||
if let TyKind::Rptr(
|
if let TyKind::Rptr(
|
||||||
_,
|
_,
|
||||||
|
@ -188,7 +209,6 @@ fn is_lint_ref_type(ty: &Ty) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn is_lint_array_type(ty: &Ty) -> bool {
|
fn is_lint_array_type(ty: &Ty) -> bool {
|
||||||
if let TyKind::Path(ref path) = ty.node {
|
if let TyKind::Path(ref path) = ty.node {
|
||||||
match_qpath(path, &paths::LINT_ARRAY)
|
match_qpath(path, &paths::LINT_ARRAY)
|
||||||
|
@ -224,8 +244,8 @@ pub struct DefaultHashTypes {
|
||||||
impl DefaultHashTypes {
|
impl DefaultHashTypes {
|
||||||
pub fn default() -> Self {
|
pub fn default() -> Self {
|
||||||
let mut map = FxHashMap::default();
|
let mut map = FxHashMap::default();
|
||||||
map.insert("HashMap".to_owned(), "FxHashMap".to_owned());
|
map.insert("HashMap".to_string(), "FxHashMap".to_string());
|
||||||
map.insert("HashSet".to_owned(), "FxHashSet".to_owned());
|
map.insert("HashSet".to_string(), "FxHashSet".to_string());
|
||||||
Self { map }
|
Self { map }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,8 +260,62 @@ impl EarlyLintPass for DefaultHashTypes {
|
||||||
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
|
fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
|
||||||
let ident_string = ident.to_string();
|
let ident_string = ident.to_string();
|
||||||
if let Some(replace) = self.map.get(&ident_string) {
|
if let Some(replace) = self.map.get(&ident_string) {
|
||||||
let msg = format!("Prefer {} over {}, it has better performance and we don't need any collision prevention in clippy", replace, ident_string);
|
let msg = format!("Prefer {} over {}, it has better performance \
|
||||||
span_lint_and_sugg(cx, DEFAULT_HASH_TYPES, ident.span, &msg, "use", replace.to_owned());
|
and we don't need any collision prevention in clippy",
|
||||||
|
replace, ident_string);
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
DEFAULT_HASH_TYPES,
|
||||||
|
ident.span,
|
||||||
|
&msg,
|
||||||
|
"use",
|
||||||
|
replace.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
|
||||||
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
|
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
|
||||||
pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
|
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 FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
|
||||||
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
|
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
|
||||||
pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "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_READ: [&str; 3] = ["std", "io", "Read"];
|
||||||
pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
|
pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
|
||||||
pub const ITERATOR: [&str; 4] = ["core", "iter", "iterator", "Iterator"];
|
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 LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
|
||||||
pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"];
|
pub const LINT: [&str; 3] = ["rustc", "lint", "Lint"];
|
||||||
pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"];
|
pub const LINT_ARRAY: [&str; 3] = ["rustc", "lint", "LintArray"];
|
||||||
|
|
Loading…
Reference in a new issue