11 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 using namespace clang::ast_matchers;
17 namespace readability {
21 LineThreshold(Options.get(
"LineThreshold", -1U)),
22 StatementThreshold(Options.get(
"StatementThreshold", 800U)),
23 BranchThreshold(Options.get(
"BranchThreshold", -1U)) {}
27 Options.
store(Opts,
"StatementThreshold", StatementThreshold);
34 unless(isInstantiated()),
36 stmt(unless(compoundStmt()),
37 hasParent(stmt(anyOf(compoundStmt(), ifStmt(),
38 anyOf(whileStmt(), doStmt(),
39 cxxForRangeStmt(), forStmt())))))
40 .bind(
"stmt"))).bind(
"func"),
45 const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
47 FunctionInfo &FI = FunctionInfos[Func];
51 if (
const Stmt *Body = Func->getBody()) {
52 SourceManager *
SM = Result.SourceManager;
53 if (SM->isWrittenInSameFile(Body->getLocStart(), Body->getLocEnd())) {
54 FI.Lines = SM->getSpellingLineNumber(Body->getLocEnd()) -
55 SM->getSpellingLineNumber(Body->getLocStart());
60 const auto *Statement = Result.Nodes.getNodeAs<Stmt>(
"stmt");
64 if (isa<IfStmt>(Statement) || isa<WhileStmt>(Statement) ||
65 isa<ForStmt>(Statement) || isa<SwitchStmt>(Statement) ||
66 isa<DoStmt>(Statement) || isa<CXXForRangeStmt>(Statement))
72 for (
const auto &P : FunctionInfos) {
73 const FunctionInfo &FI = P.second;
74 if (FI.Lines > LineThreshold || FI.Statements > StatementThreshold ||
75 FI.Branches > BranchThreshold) {
76 diag(P.first->getLocation(),
77 "function '%0' exceeds recommended size/complexity thresholds")
78 << P.first->getNameAsString();
81 if (FI.Lines > LineThreshold) {
82 diag(P.first->getLocation(),
83 "%0 lines including whitespace and comments (threshold %1)",
85 << FI.Lines << LineThreshold;
88 if (FI.Statements > StatementThreshold) {
89 diag(P.first->getLocation(),
"%0 statements (threshold %1)",
91 << FI.Statements << StatementThreshold;
94 if (FI.Branches > BranchThreshold) {
95 diag(P.first->getLocation(),
"%0 branches (threshold %1)",
97 << FI.Branches << BranchThreshold;
101 FunctionInfos.clear();
std::unique_ptr< ast_matchers::MatchFinder > Finder
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
Base class for all clang-tidy checks.
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
std::map< std::string, std::string > OptionMap
ClangTidyContext & Context
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register ASTMatchers with Finder.
void onEndOfTranslationUnit() override
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.