1 | //===--- IdentifierLengthCheck.cpp - clang-tidy |
---|---|
2 | //-----------------------------===// |
3 | // |
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 |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #include "IdentifierLengthCheck.h" |
11 | #include "clang/ASTMatchers/ASTMatchFinder.h" |
12 | |
13 | using namespace clang::ast_matchers; |
14 | |
15 | namespace clang::tidy::readability { |
16 | |
17 | const unsigned DefaultMinimumVariableNameLength = 3; |
18 | const unsigned DefaultMinimumLoopCounterNameLength = 2; |
19 | const unsigned DefaultMinimumExceptionNameLength = 2; |
20 | const unsigned DefaultMinimumParameterNameLength = 3; |
21 | const char DefaultIgnoredLoopCounterNames[] = "^[ijk_]$"; |
22 | const char DefaultIgnoredVariableNames[] = ""; |
23 | const char DefaultIgnoredExceptionVariableNames[] = "^[e]$"; |
24 | const char DefaultIgnoredParameterNames[] = "^[n]$"; |
25 | |
26 | const char ErrorMessage[] = |
27 | "%select{variable|exception variable|loop variable|" |
28 | "parameter}0 name %1 is too short, expected at least %2 characters"; |
29 | |
30 | IdentifierLengthCheck::IdentifierLengthCheck(StringRef Name, |
31 | ClangTidyContext *Context) |
32 | : ClangTidyCheck(Name, Context), |
33 | MinimumVariableNameLength(Options.get(LocalName: "MinimumVariableNameLength", |
34 | Default: DefaultMinimumVariableNameLength)), |
35 | MinimumLoopCounterNameLength(Options.get( |
36 | LocalName: "MinimumLoopCounterNameLength", Default: DefaultMinimumLoopCounterNameLength)), |
37 | MinimumExceptionNameLength(Options.get( |
38 | LocalName: "MinimumExceptionNameLength", Default: DefaultMinimumExceptionNameLength)), |
39 | MinimumParameterNameLength(Options.get( |
40 | LocalName: "MinimumParameterNameLength", Default: DefaultMinimumParameterNameLength)), |
41 | IgnoredVariableNamesInput( |
42 | Options.get(LocalName: "IgnoredVariableNames", Default: DefaultIgnoredVariableNames)), |
43 | IgnoredVariableNames(IgnoredVariableNamesInput), |
44 | IgnoredLoopCounterNamesInput(Options.get(LocalName: "IgnoredLoopCounterNames", |
45 | Default: DefaultIgnoredLoopCounterNames)), |
46 | IgnoredLoopCounterNames(IgnoredLoopCounterNamesInput), |
47 | IgnoredExceptionVariableNamesInput( |
48 | Options.get(LocalName: "IgnoredExceptionVariableNames", |
49 | Default: DefaultIgnoredExceptionVariableNames)), |
50 | IgnoredExceptionVariableNames(IgnoredExceptionVariableNamesInput), |
51 | IgnoredParameterNamesInput( |
52 | Options.get(LocalName: "IgnoredParameterNames", Default: DefaultIgnoredParameterNames)), |
53 | IgnoredParameterNames(IgnoredParameterNamesInput) {} |
54 | |
55 | void IdentifierLengthCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { |
56 | Options.store(Options&: Opts, LocalName: "MinimumVariableNameLength", Value: MinimumVariableNameLength); |
57 | Options.store(Options&: Opts, LocalName: "MinimumLoopCounterNameLength", |
58 | Value: MinimumLoopCounterNameLength); |
59 | Options.store(Options&: Opts, LocalName: "MinimumExceptionNameLength", Value: MinimumExceptionNameLength); |
60 | Options.store(Options&: Opts, LocalName: "MinimumParameterNameLength", Value: MinimumParameterNameLength); |
61 | Options.store(Options&: Opts, LocalName: "IgnoredLoopCounterNames", Value: IgnoredLoopCounterNamesInput); |
62 | Options.store(Options&: Opts, LocalName: "IgnoredVariableNames", Value: IgnoredVariableNamesInput); |
63 | Options.store(Options&: Opts, LocalName: "IgnoredExceptionVariableNames", |
64 | Value: IgnoredExceptionVariableNamesInput); |
65 | Options.store(Options&: Opts, LocalName: "IgnoredParameterNames", Value: IgnoredParameterNamesInput); |
66 | } |
67 | |
68 | void IdentifierLengthCheck::registerMatchers(MatchFinder *Finder) { |
69 | if (MinimumLoopCounterNameLength > 1) |
70 | Finder->addMatcher( |
71 | NodeMatch: forStmt(hasLoopInit(InnerMatcher: declStmt(forEach(varDecl().bind(ID: "loopVar"))))), |
72 | Action: this); |
73 | |
74 | if (MinimumExceptionNameLength > 1) |
75 | Finder->addMatcher(NodeMatch: varDecl(hasParent(cxxCatchStmt())).bind(ID: "exceptionVar"), |
76 | Action: this); |
77 | |
78 | if (MinimumParameterNameLength > 1) |
79 | Finder->addMatcher(NodeMatch: parmVarDecl().bind(ID: "paramVar"), Action: this); |
80 | |
81 | if (MinimumVariableNameLength > 1) |
82 | Finder->addMatcher( |
83 | NodeMatch: varDecl(unless(anyOf(hasParent(declStmt(hasParent(forStmt()))), |
84 | hasParent(cxxCatchStmt()), parmVarDecl()))) |
85 | .bind(ID: "standaloneVar"), |
86 | Action: this); |
87 | } |
88 | |
89 | void IdentifierLengthCheck::check(const MatchFinder::MatchResult &Result) { |
90 | const auto *StandaloneVar = Result.Nodes.getNodeAs<VarDecl>(ID: "standaloneVar"); |
91 | if (StandaloneVar) { |
92 | if (!StandaloneVar->getIdentifier()) |
93 | return; |
94 | |
95 | StringRef VarName = StandaloneVar->getName(); |
96 | |
97 | if (VarName.size() >= MinimumVariableNameLength || |
98 | IgnoredVariableNames.match(String: VarName)) |
99 | return; |
100 | |
101 | diag(StandaloneVar->getLocation(), ErrorMessage) |
102 | << 0 << StandaloneVar << MinimumVariableNameLength; |
103 | } |
104 | |
105 | auto *ExceptionVarName = Result.Nodes.getNodeAs<VarDecl>(ID: "exceptionVar"); |
106 | if (ExceptionVarName) { |
107 | if (!ExceptionVarName->getIdentifier()) |
108 | return; |
109 | |
110 | StringRef VarName = ExceptionVarName->getName(); |
111 | if (VarName.size() >= MinimumExceptionNameLength || |
112 | IgnoredExceptionVariableNames.match(String: VarName)) |
113 | return; |
114 | |
115 | diag(ExceptionVarName->getLocation(), ErrorMessage) |
116 | << 1 << ExceptionVarName << MinimumExceptionNameLength; |
117 | } |
118 | |
119 | const auto *LoopVar = Result.Nodes.getNodeAs<VarDecl>(ID: "loopVar"); |
120 | if (LoopVar) { |
121 | if (!LoopVar->getIdentifier()) |
122 | return; |
123 | |
124 | StringRef VarName = LoopVar->getName(); |
125 | |
126 | if (VarName.size() >= MinimumLoopCounterNameLength || |
127 | IgnoredLoopCounterNames.match(String: VarName)) |
128 | return; |
129 | |
130 | diag(LoopVar->getLocation(), ErrorMessage) |
131 | << 2 << LoopVar << MinimumLoopCounterNameLength; |
132 | } |
133 | |
134 | const auto *ParamVar = Result.Nodes.getNodeAs<VarDecl>(ID: "paramVar"); |
135 | if (ParamVar) { |
136 | if (!ParamVar->getIdentifier()) |
137 | return; |
138 | |
139 | StringRef VarName = ParamVar->getName(); |
140 | |
141 | if (VarName.size() >= MinimumParameterNameLength || |
142 | IgnoredParameterNames.match(String: VarName)) |
143 | return; |
144 | |
145 | diag(ParamVar->getLocation(), ErrorMessage) |
146 | << 3 << ParamVar << MinimumParameterNameLength; |
147 | } |
148 | } |
149 | |
150 | } // namespace clang::tidy::readability |
151 |
Definitions
- DefaultMinimumVariableNameLength
- DefaultMinimumLoopCounterNameLength
- DefaultMinimumExceptionNameLength
- DefaultMinimumParameterNameLength
- DefaultIgnoredLoopCounterNames
- DefaultIgnoredVariableNames
- DefaultIgnoredExceptionVariableNames
- DefaultIgnoredParameterNames
- ErrorMessage
- IdentifierLengthCheck
- storeOptions
- registerMatchers
Improve your Profiling and Debugging skills
Find out more