150 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "IdentifierLengthCheck.h"10#include "clang/ASTMatchers/ASTMatchFinder.h"11 12using namespace clang::ast_matchers;13 14namespace clang::tidy::readability {15 16const unsigned DefaultMinimumVariableNameLength = 3;17const unsigned DefaultMinimumLoopCounterNameLength = 2;18const unsigned DefaultMinimumExceptionNameLength = 2;19const unsigned DefaultMinimumParameterNameLength = 3;20const char DefaultIgnoredLoopCounterNames[] = "^[ijk_]$";21const char DefaultIgnoredVariableNames[] = "";22const char DefaultIgnoredExceptionVariableNames[] = "^[e]$";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 29IdentifierLengthCheck::IdentifierLengthCheck(StringRef Name,30 ClangTidyContext *Context)31 : ClangTidyCheck(Name, Context),32 MinimumVariableNameLength(Options.get("MinimumVariableNameLength",33 DefaultMinimumVariableNameLength)),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",44 DefaultIgnoredLoopCounterNames)),45 IgnoredLoopCounterNames(IgnoredLoopCounterNamesInput),46 IgnoredExceptionVariableNamesInput(47 Options.get("IgnoredExceptionVariableNames",48 DefaultIgnoredExceptionVariableNames)),49 IgnoredExceptionVariableNames(IgnoredExceptionVariableNamesInput),50 IgnoredParameterNamesInput(51 Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames)),52 IgnoredParameterNames(IgnoredParameterNamesInput) {}53 54void IdentifierLengthCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {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 const 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 const 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 const 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 const 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::readability150