]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/cognitive_complexity.rs
Rollup merge of #88860 - nbdd0121:panic, r=m-ou-se
[rust.git] / clippy_lints / src / cognitive_complexity.rs
index d766d26dfd95bf8c14bf3ec21227162a4c2f8265..1ccb8c5d880f441388349d77e7475006182f117a 100644 (file)
@@ -1,28 +1,34 @@
 //! calculate cognitive complexity and warn about overly complex functions
 
-use rustc::hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
-use rustc::hir::*;
-use rustc::impl_lint_pass;
-use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass};
-use rustc_session::declare_tool_lint;
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::LimitStack;
+use rustc_ast::ast::Attribute;
+use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::hir::map::Map;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
-use rustc_span::BytePos;
-use syntax::ast::Attribute;
-
-use crate::utils::{match_type, paths, snippet_opt, span_help_and_lint, LimitStack};
+use rustc_span::{sym, BytePos};
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for methods with high cognitive complexity.
+    /// ### What it does
+    /// Checks for methods with high cognitive complexity.
     ///
-    /// **Why is this bad?** Methods of high cognitive complexity tend to be hard to
+    /// ### Why is this bad?
+    /// Methods of high cognitive complexity tend to be hard to
     /// both read and maintain. Also LLVM will tend to optimize small methods better.
     ///
-    /// **Known problems:** Sometimes it's hard to find a way to reduce the
+    /// ### Known problems
+    /// Sometimes it's hard to find a way to reduce the
     /// complexity.
     ///
-    /// **Example:** No. You'll see it when you get the warning.
+    /// ### Example
+    /// No. You'll see it when you get the warning.
     pub COGNITIVE_COMPLEXITY,
-    complexity,
+    nursery,
     "functions that should be split up into multiple functions"
 }
 
@@ -43,9 +49,9 @@ pub fn new(limit: u64) -> Self {
 
 impl CognitiveComplexity {
     #[allow(clippy::cast_possible_truncation)]
-    fn check<'a, 'tcx>(
+    fn check<'tcx>(
         &mut self,
-        cx: &'a LateContext<'a, 'tcx>,
+        cx: &LateContext<'tcx>,
         kind: FnKind<'tcx>,
         decl: &'tcx FnDecl<'_>,
         body: &'tcx Body<'_>,
@@ -57,11 +63,11 @@ fn check<'a, 'tcx>(
 
         let expr = &body.value;
 
-        let mut helper = CCHelper { cc: 1, returns: 0 };
+        let mut helper = CcHelper { cc: 1, returns: 0 };
         helper.visit_expr(expr);
-        let CCHelper { cc, returns } = helper;
-        let ret_ty = cx.tables.node_type(expr.hir_id);
-        let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
+        let CcHelper { cc, returns } = helper;
+        let ret_ty = cx.typeck_results().node_type(expr.hir_id);
+        let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::Result) {
             returns
         } else {
             #[allow(clippy::integer_division)]
@@ -76,8 +82,8 @@ fn check<'a, 'tcx>(
 
         if rust_cc > self.limit.limit() {
             let fn_span = match kind {
-                FnKind::ItemFn(ident, _, _, _, _) | FnKind::Method(ident, _, _, _) => ident.span,
-                FnKind::Closure(_) => {
+                FnKind::ItemFn(ident, _, _, _) | FnKind::Method(ident, _, _) => ident.span,
+                FnKind::Closure => {
                     let header_span = body_span.with_hi(decl.output.span().lo());
                     let pos = snippet_opt(cx, header_span).and_then(|snip| {
                         let low_offset = snip.find('|')?;
@@ -89,14 +95,14 @@ fn check<'a, 'tcx>(
                     });
 
                     if let Some((low, high)) = pos {
-                        Span::new(low, high, header_span.ctxt())
+                        Span::new(low, high, header_span.ctxt(), header_span.parent())
                     } else {
                         return;
                     }
                 },
             };
 
-            span_help_and_lint(
+            span_lint_and_help(
                 cx,
                 COGNITIVE_COMPLEXITY,
                 fn_span,
@@ -105,16 +111,17 @@ fn check<'a, 'tcx>(
                     rust_cc,
                     self.limit.limit()
                 ),
+                None,
                 "you could split it up into multiple smaller functions",
             );
         }
     }
 }
 
-impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CognitiveComplexity {
+impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
     fn check_fn(
         &mut self,
-        cx: &LateContext<'a, 'tcx>,
+        cx: &LateContext<'tcx>,
         kind: FnKind<'tcx>,
         decl: &'tcx FnDecl<'_>,
         body: &'tcx Body<'_>,
@@ -122,29 +129,34 @@ fn check_fn(
         hir_id: HirId,
     ) {
         let def_id = cx.tcx.hir().local_def_id(hir_id);
-        if !cx.tcx.has_attr(def_id, sym!(test)) {
+        if !cx.tcx.has_attr(def_id.to_def_id(), sym::test) {
             self.check(cx, kind, decl, body, span);
         }
     }
 
-    fn enter_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
+    fn enter_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
         self.limit.push_attrs(cx.sess(), attrs, "cognitive_complexity");
     }
-    fn exit_lint_attrs(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
+    fn exit_lint_attrs(&mut self, cx: &LateContext<'tcx>, attrs: &'tcx [Attribute]) {
         self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity");
     }
 }
 
-struct CCHelper {
+struct CcHelper {
     cc: u64,
     returns: u64,
 }
 
-impl<'tcx> Visitor<'tcx> for CCHelper {
+impl<'tcx> Visitor<'tcx> for CcHelper {
+    type Map = Map<'tcx>;
+
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         walk_expr(self, e);
         match e.kind {
-            ExprKind::Match(_, ref arms, _) => {
+            ExprKind::If(_, _, _) => {
+                self.cc += 1;
+            },
+            ExprKind::Match(_, arms, _) => {
                 if arms.len() > 1 {
                     self.cc += 1;
                 }
@@ -154,7 +166,7 @@ fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             _ => {},
         }
     }
-    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
         NestedVisitorMap::None
     }
 }