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