1 //===--- IdentifierNamingCheck.h - clang-tidy -------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H
12 #include "../utils/RenamerClangTidyCheck.h"
15 namespace clang::tidy
{
16 namespace readability
{
20 /// Checks for identifiers naming style mismatch.
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.
26 /// It also supports a fixed prefix and suffix that will be prepended or
27 /// appended to the identifiers, regardless of the casing.
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
33 class IdentifierNamingCheck final
: public RenamerClangTidyCheck
{
35 IdentifierNamingCheck(StringRef Name
, ClangTidyContext
*Context
);
36 ~IdentifierNamingCheck();
38 void storeOptions(ClangTidyOptions::OptionMap
&Opts
) override
;
48 CT_LeadingUpperSnakeCase
51 enum HungarianPrefixType
{
58 struct HungarianNotationOption
{
59 HungarianNotationOption() = default;
61 std::optional
<CaseType
> Case
;
62 HungarianPrefixType HPType
= HungarianPrefixType::HPT_Off
;
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
;
71 NamingStyle() = default;
73 NamingStyle(std::optional
<CaseType
> Case
, StringRef Prefix
,
74 StringRef Suffix
, StringRef IgnoredRegexpStr
,
75 HungarianPrefixType HPType
);
76 NamingStyle(const NamingStyle
&O
) = delete;
77 NamingStyle
&operator=(NamingStyle
&&O
) = default;
78 NamingStyle(NamingStyle
&&O
) = default;
80 std::optional
<CaseType
> Case
;
83 // Store both compiled and non-compiled forms so original value can be
85 llvm::Regex IgnoredRegexp
;
86 std::string IgnoredRegexpStr
;
88 HungarianPrefixType HPType
;
91 struct HungarianNotation
{
93 bool checkOptionValid(int StyleKindIndex
) const;
94 bool isOptionEnabled(StringRef OptionKey
,
95 const llvm::StringMap
<std::string
> &StrMap
) const;
97 size_t getAsteriskCount(const std::string
&TypeName
) const;
98 size_t getAsteriskCount(const std::string
&TypeName
,
99 const NamedDecl
*ND
) const;
101 void loadDefaultConfig(
102 IdentifierNamingCheck::HungarianNotationOption
&HNOption
) const;
104 const ClangTidyCheck::OptionsView
&Options
,
105 IdentifierNamingCheck::HungarianNotationOption
&HNOption
) const;
107 bool removeDuplicatedPrefix(
108 SmallVector
<StringRef
, 8> &Words
,
109 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
) const;
111 std::string
getPrefix(
113 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
) const;
115 std::string
getDataTypePrefix(
116 StringRef TypeName
, const NamedDecl
*ND
,
117 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
) const;
119 std::string
getClassPrefix(
120 const CXXRecordDecl
*CRD
,
121 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
) const;
123 std::string
getEnumPrefix(const EnumConstantDecl
*ECD
) const;
124 std::string
getDeclTypeName(const NamedDecl
*ND
) const;
128 FileStyle() : IsActive(false), IgnoreMainLikeFunctions(false) {}
129 FileStyle(SmallVectorImpl
<std::optional
<NamingStyle
>> &&Styles
,
130 HungarianNotationOption HNOption
, bool IgnoreMainLike
,
131 bool CheckAnonFieldInParent
)
132 : Styles(std::move(Styles
)), HNOption(std::move(HNOption
)),
133 IsActive(true), IgnoreMainLikeFunctions(IgnoreMainLike
),
134 CheckAnonFieldInParentScope(CheckAnonFieldInParent
) {}
136 ArrayRef
<std::optional
<NamingStyle
>> getStyles() const {
141 const HungarianNotationOption
&getHNOption() const {
146 bool isActive() const { return IsActive
; }
147 bool isIgnoringMainLikeFunction() const { return IgnoreMainLikeFunctions
; }
149 bool isCheckingAnonFieldInParentScope() const {
150 return CheckAnonFieldInParentScope
;
154 SmallVector
<std::optional
<NamingStyle
>, 0> Styles
;
155 HungarianNotationOption HNOption
;
157 bool IgnoreMainLikeFunctions
;
158 bool CheckAnonFieldInParentScope
;
161 IdentifierNamingCheck::FileStyle
162 getFileStyleFromOptions(const ClangTidyCheck::OptionsView
&Options
) const;
165 matchesStyle(StringRef Type
, StringRef Name
,
166 const IdentifierNamingCheck::NamingStyle
&Style
,
167 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
,
168 const NamedDecl
*Decl
) const;
171 fixupWithCase(StringRef Type
, StringRef Name
, const Decl
*D
,
172 const IdentifierNamingCheck::NamingStyle
&Style
,
173 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
,
174 IdentifierNamingCheck::CaseType Case
) const;
177 fixupWithStyle(StringRef Type
, StringRef Name
,
178 const IdentifierNamingCheck::NamingStyle
&Style
,
179 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
,
180 const Decl
*D
) const;
182 StyleKind
findStyleKind(
184 ArrayRef
<std::optional
<IdentifierNamingCheck::NamingStyle
>> NamingStyles
,
185 bool IgnoreMainLikeFunctions
, bool CheckAnonFieldInParentScope
) const;
187 std::optional
<RenamerClangTidyCheck::FailureInfo
> getFailureInfo(
188 StringRef Type
, StringRef Name
, const NamedDecl
*ND
,
189 SourceLocation Location
,
190 ArrayRef
<std::optional
<IdentifierNamingCheck::NamingStyle
>> NamingStyles
,
191 const IdentifierNamingCheck::HungarianNotationOption
&HNOption
,
192 StyleKind SK
, const SourceManager
&SM
, bool IgnoreFailedSplit
) const;
194 bool isParamInMainLikeFunction(const ParmVarDecl
&ParmDecl
,
195 bool IncludeMainLike
) const;
198 std::optional
<FailureInfo
>
199 getDeclFailureInfo(const NamedDecl
*Decl
,
200 const SourceManager
&SM
) const override
;
201 std::optional
<FailureInfo
>
202 getMacroFailureInfo(const Token
&MacroNameTok
,
203 const SourceManager
&SM
) const override
;
204 DiagInfo
getDiagInfo(const NamingCheckId
&ID
,
205 const NamingCheckFailure
&Failure
) const override
;
207 const FileStyle
&getStyleForFile(StringRef FileName
) const;
208 StringRef
getRealFileName(StringRef FileName
) const;
210 /// Find the style kind of a field in an anonymous record.
211 StyleKind
findStyleKindForAnonField(
212 const FieldDecl
*AnonField
,
213 ArrayRef
<std::optional
<NamingStyle
>> NamingStyles
) const;
215 StyleKind
findStyleKindForField(
216 const FieldDecl
*Field
, QualType Type
,
217 ArrayRef
<std::optional
<NamingStyle
>> NamingStyles
) const;
220 findStyleKindForVar(const VarDecl
*Var
, QualType Type
,
221 ArrayRef
<std::optional
<NamingStyle
>> NamingStyles
) const;
223 /// Stores the style options as a vector, indexed by the specified \ref
224 /// StyleKind, for a given directory.
225 mutable llvm::StringMap
<FileStyle
> NamingStylesCache
;
226 mutable llvm::StringMap
<SmallString
<256U>> RealFileNameCache
;
227 FileStyle
*MainFileStyle
;
228 ClangTidyContext
*Context
;
229 const bool GetConfigPerFile
;
230 const bool IgnoreFailedSplit
;
231 HungarianNotation HungarianNotation
;
234 } // namespace readability
236 struct OptionEnumMapping
<readability::IdentifierNamingCheck::CaseType
> {
237 static llvm::ArrayRef
<
238 std::pair
<readability::IdentifierNamingCheck::CaseType
, StringRef
>>
241 } // namespace clang::tidy
243 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H