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

source code of clang-tools-extra/clang-tidy/readability/IdentifierLengthCheck.cpp