1 //===--- IdentifierLengthCheck.cpp - clang-tidy
2 //-----------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #include "IdentifierLengthCheck.h"
11 #include "../utils/OptionsUtils.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 using namespace clang::ast_matchers
;
17 namespace clang::tidy::readability
{
19 const unsigned DefaultMinimumVariableNameLength
= 3;
20 const unsigned DefaultMinimumLoopCounterNameLength
= 2;
21 const unsigned DefaultMinimumExceptionNameLength
= 2;
22 const unsigned DefaultMinimumParameterNameLength
= 3;
23 const char DefaultIgnoredLoopCounterNames
[] = "^[ijk_]$";
24 const char DefaultIgnoredVariableNames
[] = "";
25 const char DefaultIgnoredExceptionVariableNames
[] = "^[e]$";
26 const char DefaultIgnoredParameterNames
[] = "^[n]$";
28 const char ErrorMessage
[] =
29 "%select{variable|exception variable|loop variable|"
30 "parameter}0 name %1 is too short, expected at least %2 characters";
32 IdentifierLengthCheck::IdentifierLengthCheck(StringRef Name
,
33 ClangTidyContext
*Context
)
34 : ClangTidyCheck(Name
, Context
),
35 MinimumVariableNameLength(Options
.get("MinimumVariableNameLength",
36 DefaultMinimumVariableNameLength
)),
37 MinimumLoopCounterNameLength(Options
.get(
38 "MinimumLoopCounterNameLength", DefaultMinimumLoopCounterNameLength
)),
39 MinimumExceptionNameLength(Options
.get(
40 "MinimumExceptionNameLength", DefaultMinimumExceptionNameLength
)),
41 MinimumParameterNameLength(Options
.get(
42 "MinimumParameterNameLength", DefaultMinimumParameterNameLength
)),
43 IgnoredVariableNamesInput(
44 Options
.get("IgnoredVariableNames", DefaultIgnoredVariableNames
)),
45 IgnoredVariableNames(IgnoredVariableNamesInput
),
46 IgnoredLoopCounterNamesInput(Options
.get("IgnoredLoopCounterNames",
47 DefaultIgnoredLoopCounterNames
)),
48 IgnoredLoopCounterNames(IgnoredLoopCounterNamesInput
),
49 IgnoredExceptionVariableNamesInput(
50 Options
.get("IgnoredExceptionVariableNames",
51 DefaultIgnoredExceptionVariableNames
)),
52 IgnoredExceptionVariableNames(IgnoredExceptionVariableNamesInput
),
53 IgnoredParameterNamesInput(
54 Options
.get("IgnoredParameterNames", DefaultIgnoredParameterNames
)),
55 IgnoredParameterNames(IgnoredParameterNamesInput
) {}
57 void IdentifierLengthCheck::storeOptions(ClangTidyOptions::OptionMap
&Opts
) {
58 Options
.store(Opts
, "MinimumVariableNameLength", MinimumVariableNameLength
);
59 Options
.store(Opts
, "MinimumLoopCounterNameLength",
60 MinimumLoopCounterNameLength
);
61 Options
.store(Opts
, "MinimumExceptionNameLength", MinimumExceptionNameLength
);
62 Options
.store(Opts
, "MinimumParameterNameLength", MinimumParameterNameLength
);
63 Options
.store(Opts
, "IgnoredLoopCounterNames", IgnoredLoopCounterNamesInput
);
64 Options
.store(Opts
, "IgnoredVariableNames", IgnoredVariableNamesInput
);
65 Options
.store(Opts
, "IgnoredExceptionVariableNames",
66 IgnoredExceptionVariableNamesInput
);
67 Options
.store(Opts
, "IgnoredParameterNames", IgnoredParameterNamesInput
);
70 void IdentifierLengthCheck::registerMatchers(MatchFinder
*Finder
) {
71 if (MinimumLoopCounterNameLength
> 1)
73 forStmt(hasLoopInit(declStmt(forEach(varDecl().bind("loopVar"))))),
76 if (MinimumExceptionNameLength
> 1)
77 Finder
->addMatcher(varDecl(hasParent(cxxCatchStmt())).bind("exceptionVar"),
80 if (MinimumParameterNameLength
> 1)
81 Finder
->addMatcher(parmVarDecl().bind("paramVar"), this);
83 if (MinimumVariableNameLength
> 1)
85 varDecl(unless(anyOf(hasParent(declStmt(hasParent(forStmt()))),
86 hasParent(cxxCatchStmt()), parmVarDecl())))
87 .bind("standaloneVar"),
91 void IdentifierLengthCheck::check(const MatchFinder::MatchResult
&Result
) {
92 const auto *StandaloneVar
= Result
.Nodes
.getNodeAs
<VarDecl
>("standaloneVar");
94 if (!StandaloneVar
->getIdentifier())
97 StringRef VarName
= StandaloneVar
->getName();
99 if (VarName
.size() >= MinimumVariableNameLength
||
100 IgnoredVariableNames
.match(VarName
))
103 diag(StandaloneVar
->getLocation(), ErrorMessage
)
104 << 0 << StandaloneVar
<< MinimumVariableNameLength
;
107 auto *ExceptionVarName
= Result
.Nodes
.getNodeAs
<VarDecl
>("exceptionVar");
108 if (ExceptionVarName
) {
109 if (!ExceptionVarName
->getIdentifier())
112 StringRef VarName
= ExceptionVarName
->getName();
113 if (VarName
.size() >= MinimumExceptionNameLength
||
114 IgnoredExceptionVariableNames
.match(VarName
))
117 diag(ExceptionVarName
->getLocation(), ErrorMessage
)
118 << 1 << ExceptionVarName
<< MinimumExceptionNameLength
;
121 const auto *LoopVar
= Result
.Nodes
.getNodeAs
<VarDecl
>("loopVar");
123 if (!LoopVar
->getIdentifier())
126 StringRef VarName
= LoopVar
->getName();
128 if (VarName
.size() >= MinimumLoopCounterNameLength
||
129 IgnoredLoopCounterNames
.match(VarName
))
132 diag(LoopVar
->getLocation(), ErrorMessage
)
133 << 2 << LoopVar
<< MinimumLoopCounterNameLength
;
136 const auto *ParamVar
= Result
.Nodes
.getNodeAs
<VarDecl
>("paramVar");
138 if (!ParamVar
->getIdentifier())
141 StringRef VarName
= ParamVar
->getName();
143 if (VarName
.size() >= MinimumParameterNameLength
||
144 IgnoredParameterNames
.match(VarName
))
147 diag(ParamVar
->getLocation(), ErrorMessage
)
148 << 3 << ParamVar
<< MinimumParameterNameLength
;
152 } // namespace clang::tidy::readability