No worries, I don't think I will be very active this month either. -- Beren Minor
On Fri, Jul 3, 2015 at 10:28 AM, Alexander Kornienko <ale...@google.com> wrote: > Awesome! Waiting for the next patch. Please note though, that the next > week I'm OOO and won't be able to reply. > > -- Alexander Kornienko > On 3 Jul 2015 10:13, "Beren Minor" <beren.mi...@gmail.com> wrote: > >> Hi Alexander, >> >> Thanks for taking the time to review and reply, I wasn't sure of how to >> submit patches to clang-tools-extra. I will upload the diffs to phabricator >> from now on. >> >> I had in mind of the issue of fixing only declarations and the fact that >> it will break the code when one apply the fixes automatically. I will add a >> DeclRef matcher to fix the references as well and, for now, output a fix >> only if the declaration is in the TU main file and not in a macro expansion. >> >> Best, >> -- >> Beren Minor >> >> On Tue, Jun 30, 2015 at 4:55 PM, Alexander Kornienko <ale...@google.com> >> wrote: >> >>> Hi Beren, >>> >>> Sorry for the delay. You can put me to CC on clang-tidy related patches >>> to get faster reviews ;) It would also be more convenient to review patches >>> using Phabricator <http://reviews.llvm.org>, so I'd appreciate if you >>> could upload your patch there. >>> >>> Thanks for making the effort and implementing this as a clang-tidy >>> check. The check seems to be generic enough to cover many frequently used >>> styles, so it's really nice to have it. >>> >>> However, there's one issue with this check in its current form: applying >>> its fixes will break the code, because it only fixes declarations, not >>> usages. Fixing all usages of entities declared in headers may be >>> complicated, and it needs to be done in all translation units using this >>> header and also in all currently preprocessed-out code. So we may need to >>> limit the scope of automatic fixes to safe cases by default and only >>> perform unsafe replacements when specifically asked to do so. Clang-tidy >>> doesn't yet have a concept of "unsafe fixes", but we need something like >>> this for this check. >>> >>> A few other random comments: >>> >>> diff --git a/clang-tidy/readability/CMakeLists.txt >>>> b/clang-tidy/readability/CMakeLists.txt >>>> index 5248620..b3baaee 100644 >>>> --- a/clang-tidy/readability/CMakeLists.txt >>>> +++ b/clang-tidy/readability/CMakeLists.txt >>>> @@ -5,6 +5,7 @@ add_clang_library(clangTidyReadabilityModule >>>> ContainerSizeEmptyCheck.cpp >>>> ElseAfterReturnCheck.cpp >>>> FunctionSizeCheck.cpp >>>> + IdentifierCaseCheck.cpp >>>> NamedParameterCheck.cpp >>>> NamespaceCommentCheck.cpp >>>> ReadabilityTidyModule.cpp >>>> diff --git a/clang-tidy/readability/IdentifierCaseCheck.cpp >>>> b/clang-tidy/readability/IdentifierCaseCheck.cpp >>>> new file mode 100644 >>>> index 0000000..5172f58 >>>> --- /dev/null >>>> +++ b/clang-tidy/readability/IdentifierCaseCheck.cpp >>>> @@ -0,0 +1,606 @@ >>>> +//===--- FunctionSize.cpp - clang-tidy >>>> ------------------------------------===// >>>> +// >>>> +// The LLVM Compiler Infrastructure >>>> +// >>>> +// This file is distributed under the University of Illinois Open >>>> Source >>>> +// License. See LICENSE.TXT for details. >>>> +// >>>> >>>> +//===----------------------------------------------------------------------===// >>>> + >>>> +#include "IdentifierCaseCheck.h" >>>> +#include "clang/ASTMatchers/ASTMatchFinder.h" >>>> + >>>> +using namespace clang::ast_matchers; >>>> + >>>> +namespace clang { >>>> +namespace tidy { >>>> +namespace readability { >>>> + >>>> +static llvm::StringRef const CaseStyleKeys[] = { >>>> + "Namespace", >>>> + "InlineNamespace", >>>> + >>>> + "EnumConstant", >>>> + "ConstexprVariable", >>>> + "MemberConstant", >>>> + "MemberPrivate", >>>> + "MemberProtected", >>>> + "MemberPublic", >>>> + "Member", >>>> + "ClassConstant", >>>> + "ClassMember", >>>> + "GlobalConstant", >>>> + "GlobalVariable", >>>> + "LocalConstant", >>>> + "LocalVariable", >>>> + "StaticConstant", >>>> + "StaticVariable", >>>> + "Constant", >>>> + "Variable", >>>> + >>>> + "ParameterConstant", >>>> + "ParameterPack", >>>> + "Parameter", >>>> + >>>> + "Abstract", >>>> + "Struct", >>>> + "Class", >>>> + "Union", >>>> + "Enum", >>>> + >>>> + "GlobalFunction", >>>> + "ConstexprFunction", >>>> + "Function", >>>> + >>>> + "ConstexprMethod", >>>> + "VirtualMethod", >>>> + "ClassMethod", >>>> + "MethodPrivate", >>>> + "MethodProtected", >>>> + "MethodPublic", >>>> + "Method", >>>> + >>>> + "Typedef", >>>> + >>>> + "TypeTemplateParameter", >>>> + "ValueTemplateParameter", >>>> + "TemplateTemplateParameter", >>>> + "TemplateParameter", >>>> +}; >>>> + >>>> +IdentifierCaseCheck::IdentifierCaseCheck(StringRef Name, >>>> + ClangTidyContext *Context) >>>> + : ClangTidyCheck(Name, Context) { >>>> + auto const fromString = [](llvm::StringRef Str) { >>>> + if (Str.equals("any") || Str.equals("aNy_CasE")) { >>>> + return AnyCase; >>>> + } else if (Str.equals("lower") || Str.equals("lower_case")) { >>> >>> >>> Please no "else" after "return". >>> <http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return> >>> >>> + return LowerCase; >>>> + } else if (Str.equals("camelBack")) { >>>> + return CamelBack; >>>> + } else if (Str.equals("upper") || Str.equals("UPPER_CASE")) { >>>> + return UpperCase; >>>> + } else if (Str.equals("CamelCase")) { >>>> + return CamelCase; >>>> + } else { >>>> + return AnyCase; >>>> + } >>>> + }; >>>> + >>>> + for (const auto &Key : CaseStyleKeys) { >>>> + CaseConfigs[Key] = >>>> + CaseConfig(fromString(Options.get((Key + "Case").str(), >>>> "aNy_CasE")), >>>> + Options.get((Key + "Prefix").str(), ""), >>>> + Options.get((Key + "Suffix").str(), "")); >>>> + } >>>> + >>>> + IgnoreFailedSplit = Options.get("IgnoreFailedSplit", 0); >>>> +} >>>> + >>>> +void IdentifierCaseCheck::storeOptions(ClangTidyOptions::OptionMap >>>> &Opts) { >>>> + auto const toString = [](CaseType Type) { >>>> + switch (Type) { >>>> + default: >>>> + case AnyCase: >>>> + return "aNy_CasE"; >>>> + case LowerCase: >>>> + return "lower_case"; >>>> + case CamelBack: >>>> + return "camelBack"; >>>> + case UpperCase: >>>> + return "UPPER_CASE"; >>>> + case CamelCase: >>>> + return "CamelCase"; >>>> + } >>>> + }; >>>> + >>>> + for (const auto &Key : CaseStyleKeys) { >>>> + Options.store(Opts, (Key + "Case").str(), >>>> toString(CaseConfigs[Key].Case)); >>>> + Options.store(Opts, (Key + "Prefix").str(), >>>> CaseConfigs[Key].Prefix); >>>> + Options.store(Opts, (Key + "Suffix").str(), >>>> CaseConfigs[Key].Suffix); >>>> + } >>>> + >>>> + Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit); >>>> +} >>>> + >>>> +void IdentifierCaseCheck::registerMatchers(MatchFinder *Finder) { >>>> + Finder->addMatcher(namedDecl().bind("decl"), this); >>>> +} >>>> + >>>> +void IdentifierCaseCheck::check(const MatchFinder::MatchResult >>>> &Result) { >>>> + if (const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl")) { >>>> + if (!Decl->getIdentifier()) >>>> + return; >>>> + >>>> + if (Decl->getName().empty()) >>>> + return; >>>> + >>>> + if (Decl->isImplicit()) >>>> + return; >>>> + } >>>> + >>>> + auto KindName = "identifier"; >>>> >>> >>> Can we use an enumeration or at least string constants instead of string >>> literals? Compiler won't tell you if there's a typo in one of the literals. >>> >>> >>>> + auto Style = CaseConfig(); >>>> + >>>> + if (Result.Nodes.getNodeAs<TypedefDecl>("decl")) { >>>> + if (false) { >>>> + // >>>> >>> >>> Please remove this and other dead or commented out code. >>> >>> + } else if (CaseConfigs["Typedef"].isSet()) { >>>> + KindName = "typedef"; >>>> + Style = CaseConfigs["Typedef"]; >>>> + } >>>> + } >>>> + if (const auto *Decl = >>>> Result.Nodes.getNodeAs<NamespaceDecl>("decl")) { >>>> + if (Decl->isAnonymousNamespace()) >>>> + return; >>>> + >>>> + if (false) { >>>> + // >>>> >>> >>> ditto >>> >>> >>>> + } else if (Decl->isInline() && >>>> CaseConfigs["InlineNamespace"].isSet()) { >>>> + KindName = "inline namespace"; >>>> + Style = CaseConfigs["InlineNamespace"]; >>>> + } else if (CaseConfigs["Namespace"].isSet()) { >>>> + KindName = "namespace"; >>>> + Style = CaseConfigs["Namespace"]; >>>> + } >>>> + } >>>> + if (const auto *Decl = >>>> Result.Nodes.getNodeAs<CXXRecordDecl>("decl")) { >>>> + if (Decl->isAnonymousStructOrUnion()) >>>> + return; >>>> + >>>> + if (false) { >>> >>> + // } else if (Decl->isLambda() && CaseConfigs["Lambda"].isSet()) { >>>> + // } else if (Decl->isInterface() && >>>> CaseConfigs["Interface"].isSet()) { >>>> + } else if (Decl->hasDefinition() && Decl->isAbstract() && >>>> + CaseConfigs["Abstract"].isSet()) { >>>> + KindName = "abstract class"; >>>> + Style = CaseConfigs["Abstract"]; >>>> + } else if (Decl->isStruct() && CaseConfigs["Struct"].isSet()) { >>>> + KindName = "struct"; >>>> + Style = CaseConfigs["Struct"]; >>>> + } else if (Decl->isStruct() && CaseConfigs["Class"].isSet()) { >>>> + KindName = "struct"; >>>> + Style = CaseConfigs["Class"]; >>>> + } else if (Decl->isClass() && CaseConfigs["Class"].isSet()) { >>>> + KindName = "class"; >>>> + Style = CaseConfigs["Class"]; >>>> + } else if (Decl->isClass() && CaseConfigs["Struct"].isSet()) { >>>> + KindName = "class"; >>>> + Style = CaseConfigs["Struct"]; >>>> + } else if (Decl->isUnion() && CaseConfigs["Union"].isSet()) { >>>> + KindName = "union"; >>>> + Style = CaseConfigs["Union"]; >>>> + } else if (Decl->isEnum() && CaseConfigs["Enum"].isSet()) { >>>> + KindName = "enum"; >>>> + Style = CaseConfigs["Enum"]; >>>> + } >>>> + } >>>> + // if (Result.Nodes.getNodeAs<ClassTemplateDecl>("decl")); >>>> + // if >>>> (Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("decl")); >>> >>> + >>>> + if (const auto *Decl = Result.Nodes.getNodeAs<FieldDecl>("decl")) { >>>> + auto Type = Decl->getType(); >>>> + >>>> + if (false) { >>>> + // } else if (!Type.isNull() && Type.isLocalRestrictQualified()) >>>> { >>>> + // } else if (!Type.isNull() && Type.isLocalVolatileQualified()) >>>> { >>>> + // } else if (!Type.isNull() && Type.getAsString() == "") { >>> >>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + CaseConfigs["MemberConstant"].isSet()) { >>>> + KindName = "constant member"; >>>> + Style = CaseConfigs["MemberConstant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + CaseConfigs["Constant"].isSet()) { >>>> + KindName = "constant member"; >>>> + Style = CaseConfigs["Constant"]; >>>> + } else if (Decl->getAccess() == clang::AS_private && >>>> + CaseConfigs["MemberPrivate"].isSet()) { >>>> + KindName = "private member"; >>>> + Style = CaseConfigs["MemberPrivate"]; >>>> + } else if (Decl->getAccess() == clang::AS_protected && >>>> + CaseConfigs["MemberProtected"].isSet()) { >>>> + KindName = "protected member"; >>>> + Style = CaseConfigs["MemberProtected"]; >>>> + } else if (Decl->getAccess() == clang::AS_public && >>>> + CaseConfigs["MemberPublic"].isSet()) { >>>> + KindName = "public member"; >>>> + Style = CaseConfigs["MemberPublic"]; >>>> + } else if (CaseConfigs["Member"].isSet()) { >>>> + KindName = "member"; >>>> + Style = CaseConfigs["Member"]; >>>> + } >>>> + } else if (const auto *Decl = >>>> Result.Nodes.getNodeAs<ParmVarDecl>("decl")) { >>>> + auto Type = Decl->getType(); >>>> + >>>> + if (false) { >>>> + // } else if (!Type.isNull() && Type.isLocalRestrictQualified()) >>>> { >>>> + // } else if (!Type.isNull() && Type.isLocalVolatileQualified()) >>>> { >>>> + // } else if (!Type.isNull() && Type.getAsString() == "") { >>>> + } else if (Decl->isConstexpr() && >>>> + CaseConfigs["ConstexprVariable"].isSet()) { >>>> + KindName = "constexpr"; >>>> + Style = CaseConfigs["ConstexprVariable"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + CaseConfigs["ParameterConstant"].isSet()) { >>>> + KindName = "constant parameter"; >>>> + Style = CaseConfigs["Constant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + CaseConfigs["Constant"].isSet()) { >>>> + KindName = "constant parameter"; >>>> + Style = CaseConfigs["Constant"]; >>>> + } else if (Decl->isParameterPack() && >>>> + CaseConfigs["ParameterPack"].isSet()) { >>>> + KindName = "parameter pack"; >>>> + Style = CaseConfigs["ParameterPack"]; >>>> + } else if (CaseConfigs["Parameter"].isSet()) { >>>> + KindName = "parameter"; >>>> + Style = CaseConfigs["Parameter"]; >>>> + } >>>> + } else if (const auto *Decl = >>>> Result.Nodes.getNodeAs<VarDecl>("decl")) { >>>> + auto Type = Decl->getType(); >>>> + >>>> + if (false) { >>>> + // } else if (!Type.isNull() && Type.isLocalRestrictQualified()) >>>> { >>>> + // } else if (!Type.isNull() && Type.isLocalVolatileQualified()) >>>> { >>>> + // } else if (!Type.isNull() && Type.getAsString() == "") { >>>> + } else if (Decl->isConstexpr() && >>>> + CaseConfigs["ConstexprVariable"].isSet()) { >>>> + KindName = "constexpr"; >>>> + Style = CaseConfigs["ConstexprVariable"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + Decl->isStaticDataMember() && >>>> + CaseConfigs["ClassConstant"].isSet()) { >>>> + KindName = "class constant"; >>>> + Style = CaseConfigs["ClassConstant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + Decl->isFileVarDecl() && >>>> CaseConfigs["GlobalConstant"].isSet()) { >>>> + KindName = "global constant"; >>>> + Style = CaseConfigs["GlobalConstant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + Decl->isStaticLocal() && >>>> CaseConfigs["StaticConstant"].isSet()) { >>>> + KindName = "static constant"; >>>> + Style = CaseConfigs["StaticConstant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + Decl->isLocalVarDecl() && >>>> CaseConfigs["LocalConstant"].isSet()) { >>>> + KindName = "local constant"; >>>> + Style = CaseConfigs["LocalConstant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + Decl->isFunctionOrMethodVarDecl() && >>>> + CaseConfigs["LocalConstant"].isSet()) { >>>> + KindName = "local constant"; >>>> + Style = CaseConfigs["LocalConstant"]; >>>> + } else if (!Type.isNull() && Type.isLocalConstQualified() && >>>> + CaseConfigs["Constant"].isSet()) { >>>> + KindName = "constant"; >>>> + Style = CaseConfigs["Constant"]; >>>> + >>>> + // } else if (Decl->isWeak()) { >>>> + } else if (Decl->isStaticDataMember() && >>>> + CaseConfigs["ClassMember"].isSet()) { >>>> + KindName = "class member"; >>>> + Style = CaseConfigs["ClassMember"]; >>>> + } else if (Decl->isFileVarDecl() && >>>> CaseConfigs["GlobalVariable"].isSet()) { >>>> + KindName = "global variable"; >>>> + Style = CaseConfigs["GlobalVariable"]; >>>> + } else if (Decl->isStaticLocal() && >>>> CaseConfigs["StaticVariable"].isSet()) { >>>> + KindName = "static variable"; >>>> + Style = CaseConfigs["StaticVariable"]; >>>> + } else if (Decl->isLocalVarDecl() && >>>> CaseConfigs["LocalVariable"].isSet()) { >>>> + KindName = "local variable"; >>>> + Style = CaseConfigs["LocalVariable"]; >>>> + } else if (Decl->isFunctionOrMethodVarDecl() && >>>> + CaseConfigs["LocalVariable"].isSet()) { >>>> + KindName = "local variable"; >>>> + Style = CaseConfigs["LocalVariable"]; >>>> + >>>> + // } else if (Decl->isExceptionVariable() && >>>> + // CaseConfigs["ExceptionVariable"].isSet()) { >>>> + // } else if (Decl->isNRVOVariable()) { >>>> + // } else if (Decl->isCXXForRangeDecl()) { >>>> + } else if (CaseConfigs["Variable"].isSet()) { >>>> + KindName = "variable"; >>>> + Style = CaseConfigs["Variable"]; >>>> + } >>>> + } >>>> + >>>> + if (const auto *Decl = >>>> Result.Nodes.getNodeAs<CXXMethodDecl>("decl")) { >>>> + if (Decl->isMain()) >>>> + return; >>>> + >>>> + if (!Decl->isUserProvided()) >>>> + return; >>>> + >>>> + if (Decl->isUsualDeallocationFunction()) >>>> + return; >>>> + >>>> + if (Decl->isCopyAssignmentOperator()) >>>> + return; >>>> + >>>> + if (Decl->isMoveAssignmentOperator()) >>>> + return; >>>> + >>>> + if (Decl->size_overridden_methods() > 0) >>>> + return; >>>> >>> >>> I'd merge all above checks to one `if`. >>> >>> >>>> + >>>> + if (false) { >>>> + // } else if (Decl->isVariadic()) { >>>> + } else if (Decl->isConstexpr() && >>>> CaseConfigs["ConstexprMethod"].isSet()) { >>>> + KindName = "constexpr method"; >>>> + Style = CaseConfigs["ConstexprMethod"]; >>>> + } else if (Decl->isConstexpr() && >>>> + CaseConfigs["ConstexprFunction"].isSet()) { >>>> + KindName = "constexpr method"; >>>> + Style = CaseConfigs["ConstexprFunction"]; >>>> + >>>> + // } else if (Decl->isPure()) { >>>> + // } else if (Decl->isTrivial()) { >>>> + // } else if (Decl->isVirtualAsWritten()) { >>>> + // } else if (Decl->isGlobal()) { >>>> + // } else if (Decl->isInlineSpecified()) { >>>> + // } else if (Decl->isOverloadedOperator()) { >>>> + // } else if (Decl->isFunctionTemplateSpecialization()) { >>>> + >>>> + } else if (Decl->isStatic() && CaseConfigs["ClassMethod"].isSet()) >>>> { >>>> + KindName = "class method"; >>>> + Style = CaseConfigs["ClassMethod"]; >>>> + >>>> + // } else if (Decl->isConst()) { >>>> + // } else if (Decl->isVolatile()) { >>>> + } else if (Decl->isVirtual() && >>>> CaseConfigs["VirtualMethod"].isSet()) { >>>> + KindName = "virtual method"; >>>> + Style = CaseConfigs["VirtualMethod"]; >>>> + } else if (Decl->getAccess() == clang::AS_private && >>>> + CaseConfigs["MethodPrivate"].isSet()) { >>>> + KindName = "private method"; >>>> + Style = CaseConfigs["MethodPrivate"]; >>>> + } else if (Decl->getAccess() == clang::AS_protected && >>>> + CaseConfigs["MethodProtected"].isSet()) { >>>> + KindName = "protected method"; >>>> + Style = CaseConfigs["MethodProtected"]; >>>> + } else if (Decl->getAccess() == clang::AS_public && >>>> + CaseConfigs["MethodPublic"].isSet()) { >>>> + KindName = "public method"; >>>> + Style = CaseConfigs["MethodPublic"]; >>>> + } else if (CaseConfigs["Method"].isSet()) { >>>> + KindName = "method"; >>>> + Style = CaseConfigs["Method"]; >>>> + } else if (CaseConfigs["Function"].isSet()) { >>>> + KindName = "method"; >>>> + Style = CaseConfigs["Function"]; >>>> + } >>>> + } else if (const auto *Decl = >>>> Result.Nodes.getNodeAs<FunctionDecl>("decl")) { >>>> + if (Decl->isMain()) >>>> + return; >>>> + >>>> + if (false) { >>>> + // } else if (Decl->isVariadic()) { >>>> + } else if (Decl->isConstexpr() && >>>> + CaseConfigs["ConstexprFunction"].isSet()) { >>>> + KindName = "constexpr function"; >>>> + Style = CaseConfigs["ConstexprFunction"]; >>>> + >>>> + // } else if (Decl->isPure()) { >>>> + // } else if (Decl->isTrivial()) { >>>> + // } else if (Decl->isVirtualAsWritten()) { >>>> + } else if (Decl->isGlobal() && >>>> CaseConfigs["GlobalFunction"].isSet()) { >>>> + KindName = "global function"; >>>> + Style = CaseConfigs["GlobalFunction"]; >>>> + >>>> + // } else if (Decl->isInlineSpecified()) { >>>> + // } else if (Decl->isOverloadedOperator()) { >>>> + // } else if (Decl->isFunctionTemplateSpecialization()) { >>>> + } else if (CaseConfigs["Function"].isSet()) { >>>> + KindName = "function"; >>>> + Style = CaseConfigs["Function"]; >>>> + } >>>> + } >>>> + >>>> + // if (Result.Nodes.getNodeAs<FunctionTemplateDecl>("decl")); >>>> + // if (Result.Nodes.getNodeAs<UsingDecl>("decl")); >>>> + // if (Result.Nodes.getNodeAs<UsingDirectiveDecl>("decl")); >>>> + // if (Result.Nodes.getNodeAs<UnresolvedUsingValueDecl>("decl")); >>>> + >>>> + if (Result.Nodes.getNodeAs<EnumDecl>("decl")) { >>>> + if (false) { >>>> + // >>>> + } else if (CaseConfigs["Enum"].isSet()) { >>>> + KindName = "enum"; >>>> + Style = CaseConfigs["Enum"]; >>>> + } >>>> + } >>>> + if (Result.Nodes.getNodeAs<EnumConstantDecl>("decl")) { >>>> + if (false) { >>>> + // >>>> + } else if (CaseConfigs["EnumConstant"].isSet()) { >>>> + KindName = "enum constant"; >>>> + Style = CaseConfigs["EnumConstant"]; >>>> + } else if (CaseConfigs["Constant"].isSet()) { >>>> + KindName = "enum constant"; >>>> + Style = CaseConfigs["Constant"]; >>>> + } >>>> + } >>>> + >>>> + if (Result.Nodes.getNodeAs<TemplateTypeParmDecl>("decl")) { >>>> + if (false) { >>>> + // >>>> + } else if (CaseConfigs["TypeTemplateParameter"].isSet()) { >>>> + KindName = "type template parameter"; >>>> + Style = CaseConfigs["TypeTemplateParameter"]; >>>> + } else if (CaseConfigs["TemplateParameter"].isSet()) { >>>> + KindName = "template parameter"; >>>> + Style = CaseConfigs["TemplateParameter"]; >>>> + } >>>> + } else if (Result.Nodes.getNodeAs<NonTypeTemplateParmDecl>("decl")) { >>>> + if (false) { >>>> + // >>>> + } else if (CaseConfigs["ValueTemplateParameter"].isSet()) { >>>> + KindName = "value template parameter"; >>>> + Style = CaseConfigs["ValueTemplateParameter"]; >>>> + } else if (CaseConfigs["TemplateParameter"].isSet()) { >>>> + KindName = "template parameter"; >>>> + Style = CaseConfigs["TemplateParameter"]; >>>> + } >>>> + } else if (Result.Nodes.getNodeAs<TemplateTemplateParmDecl>("decl")) >>>> { >>>> + if (false) { >>>> + // >>>> + } else if (CaseConfigs["TemplateTemplateParameter"].isSet()) { >>>> + KindName = "template template parameter"; >>>> + Style = CaseConfigs["TemplateTemplateParameter"]; >>>> + } else if (CaseConfigs["TemplateParameter"].isSet()) { >>>> + KindName = "template parameter"; >>>> + Style = CaseConfigs["TemplateParameter"]; >>>> + } >>>> + } >>>> + >>>> + if (!Style.isSet()) >>>> + return; >>>> + >>>> + auto matchesStyle = [](llvm::StringRef Name, CaseConfig Style) { >>>> + static llvm::Regex Matchers[] = { >>>> + llvm::Regex(llvm::StringRef("^.*$")), >>>> + llvm::Regex(llvm::StringRef("^[a-z][a-z0-9_]*$")), >>>> + llvm::Regex(llvm::StringRef("^[a-z][a-zA-Z0-9]*$")), >>>> + llvm::Regex(llvm::StringRef("^[A-Z][A-Z0-9_]*$")), >>>> + llvm::Regex(llvm::StringRef("^[A-Z][a-zA-Z0-9]*$")), >>>> + }; >>>> + >>>> + bool Matches = true; >>>> + if (Name.startswith(Style.Prefix)) >>>> + Name = Name.drop_front(Style.Prefix.size()); >>>> + else >>>> + Matches = false; >>>> + >>>> + if (Name.endswith(Style.Suffix)) >>>> + Name = Name.drop_back(Style.Suffix.size()); >>>> + else >>>> + Matches = false; >>>> + >>>> + if (!Matchers[static_cast<size_t>(Style.Case)].match(Name)) >>>> + Matches = false; >>>> + >>>> + return Matches; >>>> + }; >>>> + >>>> + if (const auto *Decl = Result.Nodes.getNodeAs<NamedDecl>("decl")) { >>>> + if (matchesStyle(Decl->getName(), Style)) >>>> + return; >>>> + >>>> + auto fixupWithStyle = [](std::string Name, CaseConfig Style) { >>>> + static auto Splitter = llvm::Regex(llvm::StringRef( >>>> + >>>> "(([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$))")); >>>> + >>>> + auto Words = llvm::SmallVector<std::string, 8>(); >>>> + auto Substrs = llvm::SmallVector<llvm::StringRef, 8>(); >>>> + llvm::StringRef(Name).split(Substrs, "_", -1, false); >>>> + for (std::string Substr : Substrs) { >>>> + while (!Substr.empty()) { >>>> + auto Groups = llvm::SmallVector<llvm::StringRef, 8>(); >>>> + if (!Splitter.match(Substr, &Groups)) >>>> + break; >>>> + >>>> + if (Groups[3].size() > 0) { >>>> + Words.emplace_back(std::move(Groups[2])); >>>> + Substr = Substr.substr(Groups[0].size()); >>>> + >>>> + } else if (Groups[4].size() > 0) { >>>> + Words.emplace_back(std::move(Groups[4])); >>>> + Substr = Substr.substr(Groups[0].size() - >>>> Groups[5].size()); >>>> + >>>> + } else if (Groups[6].size() > 0) { >>>> + Words.emplace_back(std::move(Groups[6])); >>>> + Substr = Substr.substr(Groups[0].size() - >>>> Groups[7].size()); >>>> + } >>>> + } >>>> + } >>>> + >>>> + if (Words.empty()) { >>>> + return Name; >>>> + } >>>> + >>>> + std::string Fixup = Style.Prefix; >>>> + switch (Style.Case) { >>>> + case AnyCase: >>>> + Fixup += Name; >>>> + break; >>>> + >>>> + case LowerCase: >>>> + for (auto const &Word : Words) { >>>> + if (&Word != &Words.front()) >>>> + Fixup += "_"; >>>> + Fixup += llvm::StringRef(Word).lower(); >>>> + } >>>> + break; >>>> + >>>> + case UpperCase: >>>> + for (auto const &Word : Words) { >>>> + if (&Word != &Words.front()) >>>> + Fixup += "_"; >>>> + Fixup += llvm::StringRef(Word).upper(); >>>> + } >>>> + break; >>>> + >>>> + case CamelCase: >>>> + for (auto const &Word : Words) { >>>> + Fixup += llvm::StringRef(Word).substr(0, 1).upper(); >>>> + Fixup += llvm::StringRef(Word).substr(1).lower(); >>>> + } >>>> + break; >>>> + >>>> + case CamelBack: >>>> + for (auto const &Word : Words) { >>>> + if (&Word == &Words.front()) { >>>> + Fixup += llvm::StringRef(Word).lower(); >>>> + } else { >>>> + Fixup += llvm::StringRef(Word).substr(0, 1).upper(); >>>> + Fixup += llvm::StringRef(Word).substr(1).lower(); >>>> + } >>>> + } >>>> + break; >>>> + } >>>> + Fixup += Style.Suffix; >>>> + >>>> + return Fixup; >>>> + }; >>>> + >>>> + auto Name = Decl->getName(); >>>> + auto Fixup = fixupWithStyle(Name, Style); >>>> + if (llvm::StringRef(Fixup).equals(Name)) { >>>> >>> >>> No need for `llvm::` here. `StringRef` is visible in the `clang` >>> namespace. >>> >>> >>>> + if (!IgnoreFailedSplit) { >>>> + diag(Decl->getLocStart(), "unable to split words for %0 '%1'") >>>> + << KindName << Name; >>>> + } >>>> + } else { >>>> + auto Range = >>>> + clang::DeclarationNameInfo(Decl->getDeclName(), >>>> Decl->getLocation()) >>>> >>> >>> No need for `clang::` here. >>> >>> >>>> + .getSourceRange(); >>> >>> + auto Diagn = diag(Decl->getLocStart(), "invalid case style for %0 >>>> '%1'"); >>>> + Diagn << KindName << Decl->getName(); >>>> + Diagn << FixItHint::CreateReplacement( >>>> + CharSourceRange::getTokenRange(Range), Fixup); >>>> >>> >>> No need for the `Diagn` variable, just make these a single statement. >>> >>> >>>> + } >>>> + } >>>> +} >>>> + >>>> +} // namespace readability >>>> +} // namespace tidy >>>> +} // namespace clang >>>> diff --git a/clang-tidy/readability/IdentifierCaseCheck.h >>>> b/clang-tidy/readability/IdentifierCaseCheck.h >>>> new file mode 100644 >>>> index 0000000..a7c8aee >>>> --- /dev/null >>>> +++ b/clang-tidy/readability/IdentifierCaseCheck.h >>>> @@ -0,0 +1,61 @@ >>>> +//===--- IdentifierCaseCheck.h - clang-tidy -----------------------*- >>>> C++ >>>> +//-*-===// >>>> +// >>>> +// The LLVM Compiler Infrastructure >>>> +// >>>> +// This file is distributed under the University of Illinois Open >>>> Source >>>> +// License. See LICENSE.TXT for details. >>>> +// >>>> >>>> +//===----------------------------------------------------------------------===// >>>> + >>>> +#ifndef >>>> LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERCASECHECK_H >>>> +#define >>>> LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERCASECHECK_H >>>> + >>>> +#include "../ClangTidy.h" >>>> + >>>> +namespace clang { >>>> +namespace tidy { >>>> +namespace readability { >>>> + >>>> +/// \brief Checks for identifiers case mismatch. >>>> +class IdentifierCaseCheck : public ClangTidyCheck { >>>> +public: >>>> + IdentifierCaseCheck(StringRef Name, ClangTidyContext *Context); >>>> + >>>> + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; >>>> + void registerMatchers(ast_matchers::MatchFinder *Finder) override; >>>> + void check(const ast_matchers::MatchFinder::MatchResult &Result) >>>> override; >>>> + >>>> +private: >>>> + enum CaseType { >>>> + AnyCase = 0, >>>> + LowerCase, >>>> + CamelBack, >>>> + UpperCase, >>>> + CamelCase, >>>> + }; >>>> + >>>> + struct CaseConfig { >>>> + CaseConfig() : Case(CaseType::AnyCase), Prefix(""), Suffix("") {} >>>> >>> >>> No need to initialize std::string with "". >>> >>> >>>> + >>>> + CaseConfig(CaseType Case, std::string Prefix, std::string Suffix) >>>> + : Case(Case), Prefix(std::move(Prefix)), >>>> Suffix(std::move(Suffix)) {} >>>> + >>>> + CaseType Case; >>>> + std::string Prefix; >>>> + std::string Suffix; >>>> + >>>> + bool isSet() { >>>> + return !(Case == CaseType::AnyCase && Prefix.empty() && >>>> Suffix.empty()); >>>> + } >>>> + }; >>>> + >>>> + std::map<std::string, CaseConfig> CaseConfigs; >>>> + bool IgnoreFailedSplit; >>>> +}; >>>> + >>>> +} // namespace readability >>>> +} // namespace tidy >>>> +} // namespace clang >>>> + >>>> +#endif // >>>> LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERCASECHECK_H >>>> diff --git a/clang-tidy/readability/ReadabilityTidyModule.cpp >>>> b/clang-tidy/readability/ReadabilityTidyModule.cpp >>>> index bf118f8..7f1f71f 100644 >>>> --- a/clang-tidy/readability/ReadabilityTidyModule.cpp >>>> +++ b/clang-tidy/readability/ReadabilityTidyModule.cpp >>>> @@ -14,6 +14,7 @@ >>>> #include "ContainerSizeEmptyCheck.h" >>>> #include "ElseAfterReturnCheck.h" >>>> #include "FunctionSizeCheck.h" >>>> +#include "IdentifierCaseCheck.h" >>>> #include "NamedParameterCheck.h" >>>> #include "RedundantSmartptrGetCheck.h" >>>> #include "RedundantStringCStrCheck.h" >>>> @@ -35,6 +36,8 @@ public: >>>> "readability-else-after-return"); >>>> CheckFactories.registerCheck<FunctionSizeCheck>( >>>> "readability-function-size"); >>>> + CheckFactories.registerCheck<IdentifierCaseCheck>( >>>> + "readability-identifier-case"); >>>> >>> >>> The check is not only about case. I think, "readability-naming" or >>> "readability-identifier-naming" would be a better name. >>> >>> >>>> CheckFactories.registerCheck<readability::NamedParameterCheck>( >>>> "readability-named-parameter"); >>>> CheckFactories.registerCheck<RedundantSmartptrGetCheck>( >>>> diff --git a/test/clang-tidy/readability-identifier-case.cpp >>>> b/test/clang-tidy/readability-identifier-case.cpp >>>> new file mode 100644 >>>> index 0000000..f978639 >>>> --- /dev/null >>>> +++ b/test/clang-tidy/readability-identifier-case.cpp >>>> @@ -0,0 +1,185 @@ >>>> +// RUN: $(dirname %s)/check_clang_tidy.sh %s >>>> readability-identifier-case %t -config='{CheckOptions: [{key: >>>> readability-identifier-case.AbstractCase, value: CamelCase}, {key: >>>> readability-identifier-case.AbstractPrefix, value: 'A'}, {key: >>>> readability-identifier-case.ClassCase, value: CamelCase}, {key: >>>> readability-identifier-case.ClassPrefix, value: 'C'}, {key: >>>> readability-identifier-case.ClassConstantCase, value: CamelCase}, {key: >>>> readability-identifier-case.ClassConstantPrefix, value: 'k'}, {key: >>>> readability-identifier-case.ClassMemberCase, value: CamelCase}, {key: >>>> readability-identifier-case.ClassMethodCase, value: camelBack}, {key: >>>> readability-identifier-case.ConstantCase, value: UPPER_CASE}, {key: >>>> readability-identifier-case.ConstantSuffix, value: '_CST'}, {key: >>>> readability-identifier-case.ConstexprFunctionCase, value: lower_case}, >>>> {key: readability-identifier-case.ConstexprMethodCase, value: lower_case}, >>>> {key: readability-identifier-case.ConstexprVariableCase, value: >>>> lower_case}, {key: readability-identifier-case.EnumCase, value: CamelCase}, >>>> {key: readability-identifier-case.EnumPrefix, value: 'E'}, {key: >>>> readability-identifier-case.EnumConstantCase, value: UPPER_CASE}, {key: >>>> readability-identifier-case.FunctionCase, value: camelBack}, {key: >>>> readability-identifier-case.GlobalConstantCase, value: UPPER_CASE}, {key: >>>> readability-identifier-case.GlobalFunctionCase, value: CamelCase}, {key: >>>> readability-identifier-case.GlobalVariableCase, value: lower_case}, {key: >>>> readability-identifier-case.GlobalVariablePrefix, value: 'g_'}, {key: >>>> readability-identifier-case.InlineNamespaceCase, value: lower_case}, {key: >>>> readability-identifier-case.LocalConstantCase, value: CamelCase}, {key: >>>> readability-identifier-case.LocalConstantPrefix, value: 'k'}, {key: >>>> readability-identifier-case.LocalVariableCase, value: lower_case}, {key: >>>> readability-identifier-case.MemberCase, value: CamelCase}, {key: >>>> readability-identifier-case.MemberPrefix, value: 'm_'}, {key: >>>> readability-identifier-case.MemberConstantCase, value: lower_case}, {key: >>>> readability-identifier-case.MemberPrivatePrefix, value: '__'}, {key: >>>> readability-identifier-case.MemberProtectedPrefix, value: '_'}, {key: >>>> readability-identifier-case.MemberPublicCase, value: lower_case}, {key: >>>> readability-identifier-case.MethodCase, value: camelBack}, {key: >>>> readability-identifier-case.MethodPrivatePrefix, value: '__'}, {key: >>>> readability-identifier-case.MethodProtectedPrefix, value: '_'}, {key: >>>> readability-identifier-case.NamespaceCase, value: lower_case}, {key: >>>> readability-identifier-case.ParameterCase, value: camelBack}, {key: >>>> readability-identifier-case.ParameterPrefix, value: 'a_'}, {key: >>>> readability-identifier-case.ParameterConstantCase, value: camelBack}, {key: >>>> readability-identifier-case.ParameterConstantPrefix, value: 'i_'}, {key: >>>> readability-identifier-case.ParameterPackCase, value: camelBack}, {key: >>>> readability-identifier-case.PureFunctionCase, value: lower_case}, {key: >>>> readability-identifier-case.PureMethodCase, value: camelBack}, {key: >>>> readability-identifier-case.StaticConstantCase, value: UPPER_CASE}, {key: >>>> readability-identifier-case.StaticVariableCase, value: camelBack}, {key: >>>> readability-identifier-case.StaticVariablePrefix, value: 's_'}, {key: >>>> readability-identifier-case.StructCase, value: lower_case}, {key: >>>> readability-identifier-case.TemplateParameterCase, value: UPPER_CASE}, >>>> {key: readability-identifier-case.TemplateTemplateParameterCase, value: >>>> CamelCase}, {key: readability-identifier-case.TemplateUsingCase, value: >>>> lower_case}, {key: readability-identifier-case.TemplateUsingPrefix, value: >>>> 'u_'}, {key: readability-identifier-case.TypeTemplateParameterCase, value: >>>> camelBack}, {key: readability-identifier-case.TypeTemplateParameterSuffix, >>>> value: '_t'}, {key: readability-identifier-case.TypedefCase, value: >>>> lower_case}, {key: readability-identifier-case.TypedefSuffix, value: '_t'}, >>>> {key: readability-identifier-case.UnionCase, value: CamelCase}, {key: >>>> readability-identifier-case.UnionPrefix, value: 'U'}, {key: >>>> readability-identifier-case.UsingCase, value: lower_case}, {key: >>>> readability-identifier-case.ValueTemplateParameterCase, value: camelBack}, >>>> {key: readability-identifier-case.VariableCase, value: lower_case}, {key: >>>> readability-identifier-case.VirtualMethodCase, value: UPPER_CASE}, {key: >>>> readability-identifier-case.VirtualMethodPrefix, value: 'v_'}, {key: >>>> readability-identifier-case.IgnoreFailedSplit, value: 0}]}' -- -std=c++11 >>>> +// REQUIRES: shell >>>> + >>>> +namespace FOO_NS { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> namespace 'FOO_NS' [readability-identifier-case] >>>> +// CHECK-FIXES: foo_ns >>>> +inline namespace InlineNamespace { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> inline namespace 'InlineNamespace' [readability-identifier-case] >>>> +// CHECK-FIXES: inline_namespace >>>> + >>>> +enum my_enumeration { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> enum 'my_enumeration' [readability-identifier-case] >>>> +// CHECK-FIXES: EMyEnumeration >>>> + MyConstant = 1, >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> enum constant 'MyConstant' [readability-identifier-case] >>>> +// CHECK-FIXES: MY_CONSTANT >>>> + your_CONST = 1, >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> enum constant 'your_CONST' [readability-identifier-case] >>>> +// CHECK-FIXES: YOUR_CONST >>>> + THIS_ConstValue = 1, >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> enum constant 'THIS_ConstValue' [readability-identifier-case] >>>> +// CHECK-FIXES: THIS_CONST_VALUE >>>> +}; >>>> + >>>> +constexpr int ConstExpr_variable = 3; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> constexpr 'ConstExpr_variable' [readability-identifier-case] >>>> +// CHECK-FIXES: const_expr_variable >>>> + >>>> +class my_class { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> class 'my_class' [readability-identifier-case] >>>> +// CHECK-FIXES: CMyClass >>>> + my_class(); >>>> + >>>> + const int MEMBER_one_1 = 1; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: invalid case style for >>>> constant member 'MEMBER_one_1' [readability-identifier-case] >>>> +// CHECK-FIXES: member_one_1 >>>> + int member2 = 2; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: invalid case style for >>>> private member 'member2' [readability-identifier-case] >>>> +// CHECK-FIXES: __member2 >>>> + >>>> +private: >>>> + int private_member = 3; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> private member 'private_member' [readability-identifier-case] >>>> +// CHECK-FIXES: __private_member >>>> + >>>> +protected: >>>> + int ProtMember; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> protected member 'ProtMember' [readability-identifier-case] >>>> +// CHECK-FIXES: _ProtMember >>>> + >>>> +public: >>>> + int PubMem; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> public member 'PubMem' [readability-identifier-case] >>>> +// CHECK-FIXES: pub_mem >>>> + >>>> + static const int classConstant; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> class constant 'classConstant' [readability-identifier-case] >>>> +// CHECK-FIXES: kClassConstant >>>> + static int ClassMember_2; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> class member 'ClassMember_2' [readability-identifier-case] >>>> +// CHECK-FIXES: ClassMember2 >>>> +}; >>>> + >>>> +const int my_class::classConstant = 4; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> class constant 'classConstant' [readability-identifier-case] >>>> +// CHECK-FIXES: kClassConstant >>>> +int my_class::ClassMember_2 = 5; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> class member 'ClassMember_2' [readability-identifier-case] >>>> +// CHECK-FIXES: ClassMember2 >>>> + >>>> +const int global_Constant = 6; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> global constant 'global_Constant' [readability-identifier-case] >>>> +// CHECK-FIXES: GLOBAL_CONSTANT >>>> +int Global_variable = 7; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> global variable 'Global_variable' [readability-identifier-case] >>>> +// CHECK-FIXES: g_global_variable >>>> + >>>> +void global_function(int PARAMETER_1, int const CONST_parameter) { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> global function 'global_function' [readability-identifier-case] >>>> +// CHECK-FIXES: GlobalFunction >>>> +// CHECK-MESSAGES: :[[@LINE-3]]:22: warning: invalid case style for >>>> parameter 'PARAMETER_1' [readability-identifier-case] >>>> +// CHECK-FIXES: a_parameter1 >>>> +// CHECK-MESSAGES: :[[@LINE-5]]:39: warning: invalid case style for >>>> constant parameter 'CONST_parameter' [readability-identifier-case] >>>> +// CHECK-FIXES: CONST_PARAMETER_CST >>>> + static const int THIS_static_ConsTant = 4; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> static constant 'THIS_static_ConsTant' [readability-identifier-case] >>>> +// CHECK-FIXES: THIS_STATIC_CONS_TANT >>>> + static int THIS_static_variable; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> static variable 'THIS_static_variable' [readability-identifier-case] >>>> +// CHECK-FIXES: s_thisStaticVariable >>>> + int const local_Constant = 3; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> local constant 'local_Constant' [readability-identifier-case] >>>> +// CHECK-FIXES: kLocalConstant >>>> + int LOCAL_VARIABLE; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> local variable 'LOCAL_VARIABLE' [readability-identifier-case] >>>> +// CHECK-FIXES: local_variable >>>> + >>>> + int LOCAL_Array__[] = {0, 1, 2}; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> local variable 'LOCAL_Array__' [readability-identifier-case] >>>> +// CHECK-FIXES: local_array >>>> + >>>> + for (auto _ : LOCAL_Array__) { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: unable to split words for >>>> local variable '_' [readability-identifier-case] >>>> + } >>>> +} >>>> + >>>> +template<typename ... TYPE_parameters> >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for >>>> type template parameter 'TYPE_parameters' [readability-identifier-case] >>>> +// CHECK-FIXES: typeParameters_t >>>> +void Global_Fun(TYPE_parameters... PARAMETER_PACK) { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> global function 'Global_Fun' [readability-identifier-case] >>>> +// CHECK-FIXES: GlobalFun >>>> +// CHECK-MESSAGES: :[[@LINE-3]]:17: warning: invalid case style for >>>> parameter pack 'PARAMETER_PACK' [readability-identifier-case] >>>> +// CHECK-FIXES: parameterPack >>>> +} >>>> + >>>> +template<template<typename> class TPL_parameter, int COUNT_params, >>>> typename ... TYPE_parameters> >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for >>>> template template parameter 'TPL_parameter' [readability-identifier-case] >>>> +// CHECK-FIXES: TplParameter >>>> +// CHECK-MESSAGES: :[[@LINE-3]]:50: warning: invalid case style for >>>> value template parameter 'COUNT_params' [readability-identifier-case] >>>> +// CHECK-FIXES: countParams >>>> +// CHECK-MESSAGES: :[[@LINE-5]]:68: warning: invalid case style for >>>> type template parameter 'TYPE_parameters' [readability-identifier-case] >>>> +// CHECK-FIXES: typeParameters_t >>>> +class test_CLASS { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> class 'test_CLASS' [readability-identifier-case] >>>> +// CHECK-FIXES: CTestClass >>>> +}; >>>> + >>>> +class abstract_class { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> abstract class 'abstract_class' [readability-identifier-case] >>>> +// CHECK-FIXES: AAbstractClass >>>> + virtual ~abstract_class() = 0; >>>> + virtual void VIRTUAL_METHOD(); >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> virtual method 'VIRTUAL_METHOD' [readability-identifier-case] >>>> +// CHECK-FIXES: v_VIRTUAL_METHOD >>>> + void non_Virtual_METHOD() {} >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> private method 'non_Virtual_METHOD' [readability-identifier-case] >>>> +// CHECK-FIXES: __non_Virtual_METHOD >>>> + static void CLASS_METHOD() {} >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> class method 'CLASS_METHOD' [readability-identifier-case] >>>> +// CHECK-FIXES: classMethod >>>> + >>>> + constexpr int CST_expr_Method() { return 2; } >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> constexpr method 'CST_expr_Method' [readability-identifier-case] >>>> +// CHECK-FIXES: cst_expr_method >>>> + >>>> +private: >>>> + void PRIVate_Method(); >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> private method 'PRIVate_Method' [readability-identifier-case] >>>> +// CHECK-FIXES: __PRIVate_Method >>>> +protected: >>>> + void protected_Method(); >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> protected method 'protected_Method' [readability-identifier-case] >>>> +// CHECK-FIXES: _protected_Method >>>> +public: >>>> + void public_Method(); >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for >>>> method 'public_Method' [readability-identifier-case] >>>> +// CHECK-FIXES: publicMethod >>>> +}; >>>> + >>>> +constexpr int CE_function() { return 3; } >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> constexpr function 'CE_function' [readability-identifier-case] >>>> +// CHECK-FIXES: ce_function >>>> + >>>> +struct THIS___Structure { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> struct 'THIS___Structure' [readability-identifier-case] >>>> +// CHECK-FIXES: this_structure >>>> + THIS___Structure(); >>>> + >>>> + union __MyUnion_is_wonderful__ {}; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: invalid case style for >>>> union '__MyUnion_is_wonderful__' [readability-identifier-case] >>>> +// CHECK-FIXES: UMyUnionIsWonderful >>>> +}; >>>> + >>>> +typedef THIS___Structure struct_type; >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> typedef 'struct_type' [readability-identifier-case] >>>> +// CHECK-FIXES: struct_type_t >>>> + >>>> +static void static_Function() { >>>> +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for >>>> function 'static_Function' [readability-identifier-case] >>>> +// CHECK-FIXES: staticFunction >>>> +} >>>> + >>>> +} >>>> +} >>>> -- >>>> >>> >>> >>> >>> On Sat, Jun 27, 2015 at 12:01 PM, Beren Minor <beren.mi...@gmail.com> >>> wrote: >>> >>>> Hello, >>>> >>>> I have implemented a new check for clang-tidy, that some people might >>>> find useful >>>> and I would like to offer it for upstream integration. I'm not sure how >>>> I should proceed, >>>> so please tell me if this is not the right way to do. >>>> >>>> This check will try to enforce coding guidelines on the identifiers >>>> casing. >>>> It supports lower_case, UPPER_CASE, camelBack and CamelCase casing and >>>> tries to convert from one to another if a mismatch is detected. >>>> >>>> It also supports a fixed prefix and suffix that will be prepended or >>>> appended >>>> to the identifiers, regardless of the casing. >>>> >>>> Many configuration options are available, in order to be able to create >>>> different rules for different kind of identifier. In general, the >>>> rules are falling back to a more generic rule if the specific case is >>>> not >>>> configured. >>>> >>>> Best, >>>> -- >>>> Beren Minor >>>> >>>> _______________________________________________ >>>> cfe-commits mailing list >>>> cfe-commits@cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >>> >>> >>> -- Alexander Kornienko >>> >> >>
_______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits