clang-tools 24.0.0git
IdentifierNamingCheck.h
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
9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
11
13#include <optional>
14#include <string>
15namespace clang::tidy {
16namespace readability {
17
18enum StyleKind : int;
19
20/// Checks for identifiers naming style mismatch.
21///
22/// This check will try to enforce coding guidelines on the identifiers naming.
23/// It supports `lower_case`, `UPPER_CASE`, `camelBack` and `CamelCase` casing
24/// and tries to convert from one to another if a mismatch is detected.
25///
26/// It also supports a fixed prefix and suffix that will be prepended or
27/// appended to the identifiers, regardless of the casing.
28///
29/// Many configuration options are available, in order to be able to create
30/// different rules for different kind of identifier. In general, the
31/// rules are falling back to a more generic rule if the specific case is not
32/// configured.
34public:
35 IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context);
37
38 void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
39
50
57
60
61 std::optional<CaseType> Case;
63 llvm::StringMap<std::string> General;
64 llvm::StringMap<std::string> CString;
65 llvm::StringMap<std::string> PrimitiveType;
66 llvm::StringMap<std::string> UserDefinedType;
67 llvm::StringMap<std::string> DerivedType;
68 };
69
70 struct NamingStyle {
71 NamingStyle() = default;
72
73 NamingStyle(std::optional<CaseType> Case, StringRef Prefix,
74 StringRef Suffix, StringRef IgnoredRegexpStr,
76 NamingStyle(const NamingStyle &O) = delete;
78 NamingStyle(NamingStyle &&O) = default;
79
80 std::optional<CaseType> Case;
81 std::string Prefix;
82 std::string Suffix;
83 // Store both compiled and non-compiled forms so original value can be
84 // serialized
85 llvm::Regex IgnoredRegexp;
86 std::string IgnoredRegexpStr;
87
89 };
90
92 public:
93 bool checkOptionValid(int StyleKindIndex) const;
94 bool isOptionEnabled(StringRef OptionKey,
95 const llvm::StringMap<std::string> &StrMap) const;
96
97 size_t getAsteriskCount(const std::string &TypeName) const;
98 size_t getAsteriskCount(const std::string &TypeName,
99 const NamedDecl *ND) const;
100
103 void loadFileConfig(
104 const ClangTidyCheck::OptionsView &Options,
106
110
111 std::string getPrefix(
112 const Decl *D,
114
115 std::string getDataTypePrefix(
116 StringRef TypeName, const NamedDecl *ND,
118
119 StringRef getClassPrefix(
120 const CXXRecordDecl *CRD,
122
123 std::string getEnumPrefix(const EnumConstantDecl *ECD) const;
124 std::string getDeclTypeName(const NamedDecl *ND) const;
125 };
126
127 struct FileStyle {
129 : IsActive(false), IgnoreMainLikeFunctions(false),
130 TypedefInheritAnonTagConfig(false), AllowTrailingUnderscore(false) {}
131 FileStyle(SmallVectorImpl<std::optional<NamingStyle>> &&Styles,
132 HungarianNotationOption HNOption, bool IgnoreMainLike,
133 bool CheckAnonFieldInParent, bool TypedefInheritAnonTag,
134 bool AllowTrailingUnderscore)
135 : Styles(std::move(Styles)), HNOption(std::move(HNOption)),
136 IsActive(true), IgnoreMainLikeFunctions(IgnoreMainLike),
137 CheckAnonFieldInParentScope(CheckAnonFieldInParent),
138 TypedefInheritAnonTagConfig(TypedefInheritAnonTag),
139 AllowTrailingUnderscore(AllowTrailingUnderscore) {}
140
141 ArrayRef<std::optional<NamingStyle>> getStyles() const {
142 assert(IsActive);
143 return Styles;
144 }
145
147 assert(IsActive);
148 return HNOption;
149 }
150
151 bool isActive() const { return IsActive; }
152 bool isIgnoringMainLikeFunction() const { return IgnoreMainLikeFunctions; }
153
155 return CheckAnonFieldInParentScope;
156 }
157
159 return TypedefInheritAnonTagConfig;
160 }
161
163 return AllowTrailingUnderscore;
164 }
165
166 private:
169 bool IsActive;
170 bool IgnoreMainLikeFunctions;
171 bool CheckAnonFieldInParentScope;
172 bool TypedefInheritAnonTagConfig;
173 bool AllowTrailingUnderscore;
174 };
175
177 getFileStyleFromOptions(const ClangTidyCheck::OptionsView &Options) const;
178
179 bool
180 matchesStyle(StringRef Type, StringRef Name,
183 const NamedDecl *Decl, bool AllowTrailingUnderscore) const;
184
185 std::string
186 fixupWithCase(StringRef Type, StringRef Name, const Decl *D,
190
191 std::string
192 fixupWithStyle(StringRef Type, StringRef Name,
195 const Decl *D, bool AllowTrailingUnderscore) const;
196
198 const NamedDecl *D,
199 ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
200 bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope,
201 bool TypedefInheritAnonTagConfig) const;
202
203 std::optional<RenamerClangTidyCheck::FailureInfo> getFailureInfo(
204 StringRef Type, StringRef Name, const NamedDecl *ND,
205 SourceLocation Location,
206 ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
208 StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit,
209 bool AllowTrailingUnderscore) const;
210
211 bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl,
212 bool IncludeMainLike) const;
213
214private:
215 std::optional<FailureInfo>
216 getDeclFailureInfo(const NamedDecl *Decl,
217 const SourceManager &SM) const override;
218 std::optional<FailureInfo>
219 getMacroFailureInfo(const Token &MacroNameTok,
220 const SourceManager &SM) const override;
221 DiagInfo getDiagInfo(const NamingCheckId &ID,
222 const NamingCheckFailure &Failure) const override;
223
224 const FileStyle &getStyleForFile(StringRef FileName) const;
225 StringRef getRealFileName(StringRef FileName) const;
226
227 /// Find the style kind of a field in an anonymous record.
228 StyleKind findStyleKindForAnonField(
229 const FieldDecl *AnonField,
230 ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
231
232 StyleKind findStyleKindForField(
233 const FieldDecl *Field, QualType Type,
234 ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
235
236 /// Find the style kind configured for the kind of \p Tag, or \c SK_Invalid if
237 /// none is configured.
239 findStyleKindForTag(const TagDecl *Tag,
240 ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
241
243 findStyleKindForVar(const VarDecl *Var, QualType Type,
244 ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
245
247 undefinedStyle(ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
248
249 /// Stores the style options as a vector, indexed by the specified \ref
250 /// StyleKind, for a given directory.
251 mutable llvm::StringMap<FileStyle> NamingStylesCache;
252 mutable llvm::StringMap<SmallString<256U>> RealFileNameCache;
253 FileStyle *MainFileStyle;
254 ClangTidyContext *Context;
255 const bool GetConfigPerFile;
256 const bool IgnoreFailedSplit;
257 HungarianNotation HungarianNotation;
258};
259
260} // namespace readability
261template <>
262struct OptionEnumMapping<readability::IdentifierNamingCheck::CaseType> {
263 static llvm::ArrayRef<
264 std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>
266};
267} // namespace clang::tidy
268
269#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
std::pair< SourceLocation, StringRef > NamingCheckId
RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context)
IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context)
std::optional< RenamerClangTidyCheck::FailureInfo > getFailureInfo(StringRef Type, StringRef Name, const NamedDecl *ND, SourceLocation Location, ArrayRef< std::optional< IdentifierNamingCheck::NamingStyle > > NamingStyles, const IdentifierNamingCheck::HungarianNotationOption &HNOption, StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit, bool AllowTrailingUnderscore) const
bool matchesStyle(StringRef Type, StringRef Name, const IdentifierNamingCheck::NamingStyle &Style, const IdentifierNamingCheck::HungarianNotationOption &HNOption, const NamedDecl *Decl, bool AllowTrailingUnderscore) const
std::string fixupWithCase(StringRef Type, StringRef Name, const Decl *D, const IdentifierNamingCheck::NamingStyle &Style, const IdentifierNamingCheck::HungarianNotationOption &HNOption, IdentifierNamingCheck::CaseType Case) const
StyleKind findStyleKind(const NamedDecl *D, ArrayRef< std::optional< IdentifierNamingCheck::NamingStyle > > NamingStyles, bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope, bool TypedefInheritAnonTagConfig) const
IdentifierNamingCheck::FileStyle getFileStyleFromOptions(const ClangTidyCheck::OptionsView &Options) const
bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, bool IncludeMainLike) const
std::string fixupWithStyle(StringRef Type, StringRef Name, const IdentifierNamingCheck::NamingStyle &Style, const IdentifierNamingCheck::HungarianNotationOption &HNOption, const Decl *D, bool AllowTrailingUnderscore) const
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
llvm::StringMap< ClangTidyValue > OptionMap
This class should be specialized by any enum type that needs to be converted to and from an llvm::Str...
static ArrayRef< std::pair< T, StringRef > > getEnumMapping()=delete
ArrayRef< std::optional< NamingStyle > > getStyles() const
FileStyle(SmallVectorImpl< std::optional< NamingStyle > > &&Styles, HungarianNotationOption HNOption, bool IgnoreMainLike, bool CheckAnonFieldInParent, bool TypedefInheritAnonTag, bool AllowTrailingUnderscore)
bool isOptionEnabled(StringRef OptionKey, const llvm::StringMap< std::string > &StrMap) const
StringRef getClassPrefix(const CXXRecordDecl *CRD, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
bool removeDuplicatedPrefix(SmallVector< StringRef, 8 > &Words, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
void loadFileConfig(const ClangTidyCheck::OptionsView &Options, IdentifierNamingCheck::HungarianNotationOption &HNOption) const
void loadDefaultConfig(IdentifierNamingCheck::HungarianNotationOption &HNOption) const
std::string getPrefix(const Decl *D, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
std::string getDataTypePrefix(StringRef TypeName, const NamedDecl *ND, const IdentifierNamingCheck::HungarianNotationOption &HNOption) const
NamingStyle(std::optional< CaseType > Case, StringRef Prefix, StringRef Suffix, StringRef IgnoredRegexpStr, HungarianPrefixType HPType)
NamingStyle & operator=(NamingStyle &&O)=default