138 LineThreshold(Options.get(
"LineThreshold", DefaultLineThreshold)),
140 Options.get(
"StatementThreshold", DefaultStatementThreshold)),
141 BranchThreshold(Options.get(
"BranchThreshold", DefaultBranchThreshold)),
143 Options.get(
"ParameterThreshold", DefaultParameterThreshold)),
145 Options.get(
"NestingThreshold", DefaultNestingThreshold)),
147 Options.get(
"VariableThreshold", DefaultVariableThreshold)),
148 CountMemberInitAsStmt(
149 Options.get(
"CountMemberInitAsStmt", DefaultCountMemberInitAsStmt)) {}
171 const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
173 FunctionASTVisitor Visitor;
174 Visitor.Info.NestingThreshold = NestingThreshold.value_or(-1);
175 Visitor.CountMemberInitAsStmt = CountMemberInitAsStmt;
176 Visitor.TraverseDecl(
const_cast<FunctionDecl *
>(Func));
177 auto &FI = Visitor.Info;
179 if (FI.Statements == 0)
183 if (
const Stmt *Body = Func->getBody()) {
184 SourceManager *SM = Result.SourceManager;
185 if (SM->isWrittenInSameFile(Body->getBeginLoc(), Body->getEndLoc())) {
186 FI.Lines = SM->getSpellingLineNumber(Body->getEndLoc()) -
187 SM->getSpellingLineNumber(Body->getBeginLoc());
191 unsigned ActualNumberParameters = Func->getNumParams();
193 if ((LineThreshold && FI.Lines > LineThreshold) ||
194 (StatementThreshold && FI.Statements > StatementThreshold) ||
195 (BranchThreshold && FI.Branches > BranchThreshold) ||
196 (ParameterThreshold && ActualNumberParameters > ParameterThreshold) ||
197 !FI.NestingThresholders.empty() ||
198 (VariableThreshold && FI.Variables > VariableThreshold)) {
199 diag(Func->getLocation(),
200 "function %0 exceeds recommended size/complexity thresholds")
204 if (LineThreshold && FI.Lines > LineThreshold) {
205 diag(Func->getLocation(),
206 "%0 lines including whitespace and comments (threshold %1)",
208 << FI.Lines << LineThreshold.value();
211 if (StatementThreshold && FI.Statements > StatementThreshold) {
212 diag(Func->getLocation(),
"%0 statements (threshold %1)",
214 << FI.Statements << StatementThreshold.value();
217 if (BranchThreshold && FI.Branches > BranchThreshold) {
218 diag(Func->getLocation(),
"%0 branches (threshold %1)", DiagnosticIDs::Note)
219 << FI.Branches << BranchThreshold.value();
222 if (ParameterThreshold && ActualNumberParameters > ParameterThreshold) {
223 diag(Func->getLocation(),
"%0 parameters (threshold %1)",
225 << ActualNumberParameters << ParameterThreshold.value();
228 for (
const auto &CSPos : FI.NestingThresholders) {
229 diag(CSPos,
"nesting level %0 starts here (threshold %1)",
231 << NestingThreshold.value() + 1 << NestingThreshold.value();
234 if (VariableThreshold && FI.Variables > VariableThreshold) {
235 diag(Func->getLocation(),
"%0 variables (threshold %1)",
237 << FI.Variables << VariableThreshold.value();
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.