about summary refs log tree commit diff
path: root/clippy_lints/src/utils/internal_lints.rs
diff options
context:
space:
mode:
Diffstat (limited to 'clippy_lints/src/utils/internal_lints.rs')
-rw-r--r--clippy_lints/src/utils/internal_lints.rs107
1 files changed, 87 insertions, 20 deletions
diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs
index b885e5132f1..a94f0357977 100644
--- a/clippy_lints/src/utils/internal_lints.rs
+++ b/clippy_lints/src/utils/internal_lints.rs
@@ -1,3 +1,4 @@
+use crate::utils::internal_lints::metadata_collector::is_deprecated_lint;
 use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::macros::root_macro_call_first_node;
@@ -338,6 +339,46 @@ declare_clippy_lint! {
     "checking if all necessary steps were taken when adding a MSRV to a lint"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for cases of an auto-generated deprecated lint without an updated reason,
+    /// i.e. `"default deprecation note"`.
+    ///
+    /// ### Why is this bad?
+    /// Indicates that the documentation is incomplete.
+    ///
+    /// ### Example
+    /// ```rust,ignore
+    /// declare_deprecated_lint! {
+    ///     /// ### What it does
+    ///     /// Nothing. This lint has been deprecated.
+    ///     ///
+    ///     /// ### Deprecation reason
+    ///     /// TODO
+    ///     #[clippy::version = "1.63.0"]
+    ///     pub COOL_LINT,
+    ///     "default deprecation note"
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust,ignore
+    /// declare_deprecated_lint! {
+    ///     /// ### What it does
+    ///     /// Nothing. This lint has been deprecated.
+    ///     ///
+    ///     /// ### Deprecation reason
+    ///     /// This lint has been replaced by `cooler_lint`
+    ///     #[clippy::version = "1.63.0"]
+    ///     pub COOL_LINT,
+    ///     "this lint has been replaced by `cooler_lint`"
+    /// }
+    /// ```
+    pub DEFAULT_DEPRECATION_REASON,
+    internal,
+    "found 'default deprecation note' in a deprecated lint declaration"
+}
+
 declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
 
 impl EarlyLintPass for ClippyLintsInternal {
@@ -375,42 +416,67 @@ pub struct LintWithoutLintPass {
     registered_lints: FxHashSet<Symbol>,
 }
 
-impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE]);
+impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE, DEFAULT_DEPRECATION_REASON]);
 
 impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id()) {
+        if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id())
+            || is_lint_allowed(cx, DEFAULT_DEPRECATION_REASON, item.hir_id())
+        {
             return;
         }
 
         if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
-            if is_lint_ref_type(cx, ty) {
+            let is_lint_ref_ty = is_lint_ref_type(cx, ty);
+            if is_deprecated_lint(cx, ty) || is_lint_ref_ty {
                 check_invalid_clippy_version_attribute(cx, item);
 
                 let expr = &cx.tcx.hir().body(body_id).value;
-                if_chain! {
-                    if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind;
-                    if let ExprKind::Struct(_, fields, _) = inner_exp.kind;
-                    let field = fields
-                        .iter()
-                        .find(|f| f.ident.as_str() == "desc")
-                        .expect("lints must have a description field");
-                    if let ExprKind::Lit(Spanned {
-                        node: LitKind::Str(ref sym, _),
-                        ..
-                    }) = field.expr.kind;
-                    if sym.as_str() == "default lint description";
-
-                    then {
+                let fields;
+                if is_lint_ref_ty {
+                    if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
+                        && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind {
+                            fields = struct_fields;
+                    } else {
+                        return;
+                    }
+                } else if let ExprKind::Struct(_, struct_fields, _) = expr.kind {
+                    fields = struct_fields;
+                } else {
+                    return;
+                }
+
+                let field = fields
+                    .iter()
+                    .find(|f| f.ident.as_str() == "desc")
+                    .expect("lints must have a description field");
+
+                if let ExprKind::Lit(Spanned {
+                    node: LitKind::Str(ref sym, _),
+                    ..
+                }) = field.expr.kind
+                {
+                    let sym_str = sym.as_str();
+                    if is_lint_ref_ty {
+                        if sym_str == "default lint description" {
+                            span_lint(
+                                cx,
+                                DEFAULT_LINT,
+                                item.span,
+                                &format!("the lint `{}` has the default lint description", item.ident.name),
+                            );
+                        }
+
+                        self.declared_lints.insert(item.ident.name, item.span);
+                    } else if sym_str == "default deprecation note" {
                         span_lint(
                             cx,
-                            DEFAULT_LINT,
+                            DEFAULT_DEPRECATION_REASON,
                             item.span,
-                            &format!("the lint `{}` has the default lint description", item.ident.name),
+                            &format!("the lint `{}` has the default deprecation reason", item.ident.name),
                         );
                     }
                 }
-                self.declared_lints.insert(item.ident.name, item.span);
             }
         } else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
             if !matches!(
@@ -668,6 +734,7 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
             let body = cx.tcx.hir().body(*body);
             let only_expr = peel_blocks_with_stmt(&body.value);
             if let ExprKind::MethodCall(ps, span_call_args, _) = &only_expr.kind;
+            if let ExprKind::Path(..) = span_call_args[0].kind;
             then {
                 let and_then_snippets = get_and_then_snippets(cx, and_then_args);
                 let mut sle = SpanlessEq::new(cx).deny_side_effects();