clang-tools 22.0.0git
IdentifierLengthCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/ASTMatchers/ASTMatchFinder.h"
11
12using namespace clang::ast_matchers;
13
15
20const char DefaultIgnoredLoopCounterNames[] = "^[ijk_]$";
23const char DefaultIgnoredParameterNames[] = "^[n]$";
24
25const char ErrorMessage[] =
26 "%select{variable|exception variable|loop variable|"
27 "parameter}0 name %1 is too short, expected at least %2 characters";
28
30 ClangTidyContext *Context)
31 : ClangTidyCheck(Name, Context),
32 MinimumVariableNameLength(Options.get("MinimumVariableNameLength",
34 MinimumLoopCounterNameLength(Options.get(
35 "MinimumLoopCounterNameLength", DefaultMinimumLoopCounterNameLength)),
36 MinimumExceptionNameLength(Options.get(
37 "MinimumExceptionNameLength", DefaultMinimumExceptionNameLength)),
38 MinimumParameterNameLength(Options.get(
39 "MinimumParameterNameLength", DefaultMinimumParameterNameLength)),
40 IgnoredVariableNamesInput(
41 Options.get("IgnoredVariableNames", DefaultIgnoredVariableNames)),
42 IgnoredVariableNames(IgnoredVariableNamesInput),
43 IgnoredLoopCounterNamesInput(Options.get("IgnoredLoopCounterNames",
45 IgnoredLoopCounterNames(IgnoredLoopCounterNamesInput),
46 IgnoredExceptionVariableNamesInput(
47 Options.get("IgnoredExceptionVariableNames",
49 IgnoredExceptionVariableNames(IgnoredExceptionVariableNamesInput),
50 IgnoredParameterNamesInput(
51 Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames)),
52 IgnoredParameterNames(IgnoredParameterNamesInput) {}
53
55 Options.store(Opts, "MinimumVariableNameLength", MinimumVariableNameLength);
56 Options.store(Opts, "MinimumLoopCounterNameLength",
57 MinimumLoopCounterNameLength);
58 Options.store(Opts, "MinimumExceptionNameLength", MinimumExceptionNameLength);
59 Options.store(Opts, "MinimumParameterNameLength", MinimumParameterNameLength);
60 Options.store(Opts, "IgnoredLoopCounterNames", IgnoredLoopCounterNamesInput);
61 Options.store(Opts, "IgnoredVariableNames", IgnoredVariableNamesInput);
62 Options.store(Opts, "IgnoredExceptionVariableNames",
63 IgnoredExceptionVariableNamesInput);
64 Options.store(Opts, "IgnoredParameterNames", IgnoredParameterNamesInput);
65}
66
67void IdentifierLengthCheck::registerMatchers(MatchFinder *Finder) {
68 if (MinimumLoopCounterNameLength > 1)
69 Finder->addMatcher(
70 forStmt(hasLoopInit(declStmt(forEach(varDecl().bind("loopVar"))))),
71 this);
72
73 if (MinimumExceptionNameLength > 1)
74 Finder->addMatcher(varDecl(hasParent(cxxCatchStmt())).bind("exceptionVar"),
75 this);
76
77 if (MinimumParameterNameLength > 1)
78 Finder->addMatcher(parmVarDecl().bind("paramVar"), this);
79
80 if (MinimumVariableNameLength > 1)
81 Finder->addMatcher(
82 varDecl(unless(anyOf(hasParent(declStmt(hasParent(forStmt()))),
83 hasParent(cxxCatchStmt()), parmVarDecl())))
84 .bind("standaloneVar"),
85 this);
86}
87
88void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) {
89 const auto *StandaloneVar = Result.Nodes.getNodeAs<VarDecl>("standaloneVar");
90 if (StandaloneVar) {
91 if (!StandaloneVar->getIdentifier())
92 return;
93
94 StringRef VarName = StandaloneVar->getName();
95
96 if (VarName.size() >= MinimumVariableNameLength ||
97 IgnoredVariableNames.match(VarName))
98 return;
99
100 diag(StandaloneVar->getLocation(), ErrorMessage)
101 << 0 << StandaloneVar << MinimumVariableNameLength;
102 }
103
104 auto *ExceptionVarName = Result.Nodes.getNodeAs<VarDecl>("exceptionVar");
105 if (ExceptionVarName) {
106 if (!ExceptionVarName->getIdentifier())
107 return;
108
109 StringRef VarName = ExceptionVarName->getName();
110 if (VarName.size() >= MinimumExceptionNameLength ||
111 IgnoredExceptionVariableNames.match(VarName))
112 return;
113
114 diag(ExceptionVarName->getLocation(), ErrorMessage)
115 << 1 << ExceptionVarName << MinimumExceptionNameLength;
116 }
117
118 const auto *LoopVar = Result.Nodes.getNodeAs<VarDecl>("loopVar");
119 if (LoopVar) {
120 if (!LoopVar->getIdentifier())
121 return;
122
123 StringRef VarName = LoopVar->getName();
124
125 if (VarName.size() >= MinimumLoopCounterNameLength ||
126 IgnoredLoopCounterNames.match(VarName))
127 return;
128
129 diag(LoopVar->getLocation(), ErrorMessage)
130 << 2 << LoopVar << MinimumLoopCounterNameLength;
131 }
132
133 const auto *ParamVar = Result.Nodes.getNodeAs<VarDecl>("paramVar");
134 if (ParamVar) {
135 if (!ParamVar->getIdentifier())
136 return;
137
138 StringRef VarName = ParamVar->getName();
139
140 if (VarName.size() >= MinimumParameterNameLength ||
141 IgnoredParameterNames.match(VarName))
142 return;
143
144 diag(ParamVar->getLocation(), ErrorMessage)
145 << 3 << ParamVar << MinimumParameterNameLength;
146 }
147}
148
149} // namespace clang::tidy::readability
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
IdentifierLengthCheck(StringRef Name, ClangTidyContext *Context)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
const char DefaultIgnoredExceptionVariableNames[]
const unsigned DefaultMinimumParameterNameLength
const unsigned DefaultMinimumExceptionNameLength
const unsigned DefaultMinimumLoopCounterNameLength
const unsigned DefaultMinimumVariableNameLength
llvm::StringMap< ClangTidyValue > OptionMap