diff --git a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.h b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.h --- a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.h +++ b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.h @@ -17,10 +17,15 @@ /// 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 @@ private: const unsigned Threshold; + const bool DescribeBasicIncrements; }; } // namespace readability diff --git a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/FunctionCognitiveComplexityCheck.cpp @@ -492,11 +492,13 @@ 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 @@ 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. diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-function-cognitive-complexity.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-function-cognitive-complexity.rst --- a/clang-tools-extra/docs/clang-tidy/checks/readability-function-cognitive-complexity.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-function-cognitive-complexity.rst @@ -17,6 +17,13 @@ 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 @@ 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 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability-function-cognitive-complexity-flags.cpp @@ -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) { + } +}