[clang-tidy] Add options to describe individual core increments to readability-functi...
authorJens Massberg <massberg@google.com>
Thu, 4 Mar 2021 20:02:26 +0000 (21:02 +0100)
committerKirill Bobyrev <kbobyrev@google.com>
Thu, 4 Mar 2021 20:02:27 +0000 (21:02 +0100)
Often you are only interested in the overall cognitive complexity of a
function and not every individual increment. Thus the flag
'DescribeBasicIncrements' is added. If it is set to 'true', each increment
is flagged. Otherwise, only the complexity of function with complexity
of at least the threshold are flagged.

By default 'DescribeBasisIncrements' is set to 'true', which is the original behavior of the check.

Added a new test for different flag combinations.

(The option to ignore macros which was original part of this patch will be added in another path)

Reviewed By: lebedev.ri

Differential Revision: https://reviews.llvm.org/D96281

clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp
clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.h
clang-tools-extra/docs/clang-tidy/checks/readability-function-cognitive-complexity.rst
clang-tools-extra/test/clang-tidy/checkers/readability-function-cognitive-complexity-flags.cpp [new file with mode: 0644]

index 3a47583..94ff38d 100644 (file)
@@ -492,11 +492,13 @@ public:
 FunctionCognitiveComplexityCheck::FunctionCognitiveComplexityCheck(
     StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      Threshold(Options.get("Threshold", CognitiveComplexity::DefaultLimit)) {}
+      Threshold(Options.get("Threshold", CognitiveComplexity::DefaultLimit)),
+      DescribeBasicIncrements(Options.get("DescribeBasicIncrements", true)) {}
 
 void FunctionCognitiveComplexityCheck::storeOptions(
     ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "Threshold", Threshold);
+  Options.store(Opts, "DescribeBasicIncrements", DescribeBasicIncrements);
 }
 
 void FunctionCognitiveComplexityCheck::registerMatchers(MatchFinder *Finder) {
@@ -537,6 +539,9 @@ void FunctionCognitiveComplexityCheck::check(
     diag(Loc, "lambda has cognitive complexity of %0 (threshold %1)")
         << Visitor.CC.Total << Threshold;
 
+  if (!DescribeBasicIncrements)
+    return;
+
   // Output all the basic increments of complexity.
   for (const auto &Detail : Visitor.CC.Details) {
     unsigned MsgId;          // The id of the message to output.
index a21b844..01244ab 100644 (file)
@@ -17,10 +17,15 @@ namespace readability {
 
 /// Checks function Cognitive Complexity metric.
 ///
-/// There is only one configuration option:
+/// There are the following configuration option:
 ///
 ///   * `Threshold` - flag functions with Cognitive Complexity exceeding
 ///     this number. The default is `25`.
+///   * `DescribeBasicIncrements`- if set to `true`, then for each function
+///     exceeding the complexity threshold the check will issue additional
+///     diagnostics on every piece of code (loop, `if` statement, etc.) which
+///     contributes to that complexity.
+//      Default is `true`
 ///
 /// For the user-facing documentation see:
 /// http://clang.llvm.org/extra/clang-tidy/checks/readability-function-cognitive-complexity.html
@@ -37,6 +42,7 @@ public:
 
 private:
   const unsigned Threshold;
+  const bool DescribeBasicIncrements;
 };
 
 } // namespace readability
index b863357..b14c684 100644 (file)
@@ -17,6 +17,13 @@ Options
    Flag functions with Cognitive Complexity exceeding this number.
    The default is `25`.
 
+.. option:: DescribeBasicIncrements
+
+   If set to `true`, then for each function exceeding the complexity threshold
+   the check will issue additional diagnostics on every piece of code (loop,
+   `if` statement, etc.) which contributes to that complexity. See also the
+   examples below. Default is `true`.
+
 Building blocks
 ---------------
 
@@ -135,6 +142,11 @@ Full example. This function has Cognitive Complexity of `3`.
     return 0;
   }
 
+In the last example, the check will flag `function3` if the option Threshold is
+set to `2` or smaller. If the option DescribeBasicIncrements is set to `true`,
+it will additionally flag the two `if` statements with the amounts by which they
+increase to the complexity of the function and the current nesting level.
+
 Limitations
 -----------
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-function-cognitive-complexity-flags.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-function-cognitive-complexity-flags.cpp
new file mode 100644 (file)
index 0000000..c52e7bc
--- /dev/null
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s readability-function-cognitive-complexity %t -- \
+// RUN:   -config='{CheckOptions: \
+// RUN:             [{key: readability-function-cognitive-complexity.Threshold, \
+// RUN:               value: 0}, \
+// RUN:              {key: readability-function-cognitive-complexity.DescribeBasicIncrements, \
+// RUN:               value: "false"} ]}'
+// RUN: %check_clang_tidy -check-suffix=THRESHOLD5 %s readability-function-cognitive-complexity %t -- \
+// RUN:   -config='{CheckOptions: \
+// RUN:             [{key: readability-function-cognitive-complexity.Threshold, \
+// RUN:               value: 5}, \
+// RUN:              {key: readability-function-cognitive-complexity.DescribeBasicIncrements, \
+// RUN:               value: "false"} ]}'
+
+void func_of_complexity_4() {
+  // CHECK-NOTES: :[[@LINE-1]]:6: warning: function 'func_of_complexity_4' has cognitive complexity of 4 (threshold 0) [readability-function-cognitive-complexity]
+  if (1) {
+    if (1) {
+    }
+  }
+  if (1) {
+  }
+}
+
+#define MacroOfComplexity10 \
+  if (1) {                  \
+    if (1) {                \
+      if (1) {              \
+        if (1) {            \
+        }                   \
+      }                     \
+    }                       \
+  }
+
+void function_with_macro() {
+  // CHECK-NOTES: :[[@LINE-1]]:6: warning: function 'function_with_macro' has cognitive complexity of 11 (threshold 0) [readability-function-cognitive-complexity]
+  // CHECK-NOTES-THRESHOLD5: :[[@LINE-2]]:6: warning: function 'function_with_macro' has cognitive complexity of 11 (threshold 5) [readability-function-cognitive-complexity]
+
+  MacroOfComplexity10;
+
+  if (1) {
+  }
+}