Index: clang-tidy/readability/FunctionSizeCheck.h =================================================================== --- clang-tidy/readability/FunctionSizeCheck.h +++ clang-tidy/readability/FunctionSizeCheck.h @@ -28,7 +28,9 @@ /// * `BranchThreshold` - flag functions exceeding this number of control /// statements. The default is `-1` (ignore the number of branches). /// * `ParameterThreshold` - flag functions having a high number of parameters. -/// The default is `6`. +/// The default is `-1`. +/// * `NestingThreshold` - flag compound statements which create next nesting +/// level after `NestingThreshold`. The default is `10`. class FunctionSizeCheck : public ClangTidyCheck { public: FunctionSizeCheck(StringRef Name, ClangTidyContext *Context); @@ -42,6 +44,7 @@ const unsigned StatementThreshold; const unsigned BranchThreshold; const unsigned ParameterThreshold; + const unsigned NestingThreshold; }; } // namespace readability Index: clang-tidy/readability/FunctionSizeCheck.cpp =================================================================== --- clang-tidy/readability/FunctionSizeCheck.cpp +++ clang-tidy/readability/FunctionSizeCheck.cpp @@ -38,6 +38,12 @@ ++Info.Branches; // fallthrough case Stmt::CompoundStmtClass: + // if this is the exact compount statement that is right above the + // threshold, record the position + if (std::count_if(TrackedParent.begin(), TrackedParent.end(), + [](bool Val) { return Val; }) == Info.NestingThreshold) + Info.NestingThresholders.push_back(Node->getLocStart()); + TrackedParent.push_back(true); break; default: @@ -59,10 +65,12 @@ } struct FunctionInfo { - FunctionInfo() : Lines(0), Statements(0), Branches(0) {} - unsigned Lines; - unsigned Statements; - unsigned Branches; + unsigned Lines = 0; + unsigned Statements = 0; + unsigned Branches = 0; + + unsigned NestingThreshold = 0; + std::vector NestingThresholders; }; FunctionInfo Info; std::vector TrackedParent; @@ -73,13 +81,15 @@ LineThreshold(Options.get("LineThreshold", -1U)), StatementThreshold(Options.get("StatementThreshold", 800U)), BranchThreshold(Options.get("BranchThreshold", -1U)), - ParameterThreshold(Options.get("ParameterThreshold", -1U)) {} + ParameterThreshold(Options.get("ParameterThreshold", -1U)), + NestingThreshold(Options.get("NestingThreshold", 10U)) {} void FunctionSizeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "LineThreshold", LineThreshold); Options.store(Opts, "StatementThreshold", StatementThreshold); Options.store(Opts, "BranchThreshold", BranchThreshold); Options.store(Opts, "ParameterThreshold", ParameterThreshold); + Options.store(Opts, "NestingThreshold", NestingThreshold); } void FunctionSizeCheck::registerMatchers(MatchFinder *Finder) { @@ -90,6 +100,7 @@ const auto *Func = Result.Nodes.getNodeAs("func"); FunctionASTVisitor Visitor; + Visitor.Info.NestingThreshold = NestingThreshold; Visitor.TraverseDecl(const_cast(Func)); auto &FI = Visitor.Info; @@ -138,6 +149,12 @@ DiagnosticIDs::Note) << ActualNumberParameters << ParameterThreshold; } + + for (const auto &CSPos : FI.NestingThresholders) { + diag(CSPos, "nesting level %0 starts here (threshold %1)", + DiagnosticIDs::Note) + << NestingThreshold + 1 << NestingThreshold; + } } } // namespace readability Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -95,6 +95,11 @@ Finds possible inefficient vector operations in for loops that may cause unnecessary memory reallocations. +- Added `NestingThreshold` to `readability-function-size + `_ check + + Finds compound statements which create next nesting level after `NestingThreshold` and emits a warning. + - Added `ParameterThreshold` to `readability-function-size `_ check Index: test/clang-tidy/readability-function-size.cpp =================================================================== --- test/clang-tidy/readability-function-size.cpp +++ test/clang-tidy/readability-function-size.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s readability-function-size %t -- -config='{CheckOptions: [{key: readability-function-size.LineThreshold, value: 0}, {key: readability-function-size.StatementThreshold, value: 0}, {key: readability-function-size.BranchThreshold, value: 0}, {key: readability-function-size.ParameterThreshold, value: 5}]}' -- -std=c++11 +// RUN: %check_clang_tidy %s readability-function-size %t -- -config='{CheckOptions: [{key: readability-function-size.LineThreshold, value: 0}, {key: readability-function-size.StatementThreshold, value: 0}, {key: readability-function-size.BranchThreshold, value: 0}, {key: readability-function-size.ParameterThreshold, value: 5}, {key: readability-function-size.NestingThreshold, value: 2}]}' -- -std=c++11 // Bad formatting is intentional, don't run clang-format over the whole file! @@ -59,3 +59,28 @@ // // CHECK-MESSAGES: :[[@LINE-4]]:30: warning: function 'barx' exceeds recommended size/complexity // CHECK-MESSAGES: :[[@LINE-5]]:30: note: 2 statements (threshold 0) + +void baz0() { // 1 + int a; + { // 2 + int b; + { // 3 + int c; + { // 4 + int d; + } + } + } + { // 2 + int e; + } + { // 2 + { // 3 + int j; + } + } +} +// CHECK-MESSAGES: :[[@LINE-20]]:6: warning: function 'baz0' exceeds recommended size/complexity +// CHECK-MESSAGES: :[[@LINE-21]]:6: note: 6 statements (threshold 0) +// CHECK-MESSAGES: :[[@LINE-18]]:5: note: nesting level 3 starts here (threshold 2) +// CHECK-MESSAGES: :[[@LINE-8]]:5: note: nesting level 3 starts here (threshold 2)