Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -5,6 +5,7 @@ ContainerSizeEmptyCheck.cpp ElseAfterReturnCheck.cpp FunctionSizeCheck.cpp + IdentifierNamingCheck.cpp NamedParameterCheck.cpp NamespaceCommentCheck.cpp ReadabilityTidyModule.cpp Index: clang-tidy/readability/IdentifierNamingCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/IdentifierNamingCheck.h @@ -0,0 +1,73 @@ +//===--- IdentifierNamingCheck.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_IDENTIFIERNAMINGCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// \brief Checks for identifiers naming style mismatch. +class IdentifierNamingCheck : public ClangTidyCheck { +public: + IdentifierNamingCheck(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; + void onEndOfTranslationUnit() override; + + enum CaseType { + CT_AnyCase = 0, + CT_LowerCase, + CT_CamelBack, + CT_UpperCase, + CT_CamelCase, + }; + + struct NamingStyle { + NamingStyle() : Case(CT_AnyCase) {} + + NamingStyle(CaseType Case, const std::string &Prefix, + const std::string &Suffix) + : Case(Case), Prefix(Prefix), Suffix(Suffix) {} + + CaseType Case; + std::string Prefix; + std::string Suffix; + + bool isSet() const { + return !(Case == CT_AnyCase && Prefix.empty() && Suffix.empty()); + } + }; + +private: + std::vector NamingStyles; + bool IgnoreFailedSplit; + + struct NamingCheckFailure { + std::string KindName; + std::string Fixup; + bool ShouldFix; + std::vector Usages; + + NamingCheckFailure() : ShouldFix(true) {} + }; + + llvm::DenseMap NamingCheckFailures; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H Index: clang-tidy/readability/IdentifierNamingCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/IdentifierNamingCheck.cpp @@ -0,0 +1,585 @@ +//===--- IdentifierNamingCheck.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 "IdentifierNamingCheck.h" + +#include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +#define NAMING_KEYS(m) \ + m(Namespace) \ + m(InlineNamespace) \ + m(EnumConstant) \ + m(ConstexprVariable) \ + m(ConstantMember) \ + m(PrivateMember) \ + m(ProtectedMember) \ + m(PublicMember) \ + m(Member) \ + m(ClassConstant) \ + m(ClassMember) \ + m(GlobalConstant) \ + m(GlobalVariable) \ + m(LocalConstant) \ + m(LocalVariable) \ + m(StaticConstant) \ + m(StaticVariable) \ + m(Constant) \ + m(Variable) \ + m(ConstantParameter) \ + m(ParameterPack) \ + m(Parameter) \ + m(AbstractClass) \ + m(Struct) \ + m(Class) \ + m(Union) \ + m(Enum) \ + m(GlobalFunction) \ + m(ConstexprFunction) \ + m(Function) \ + m(ConstexprMethod) \ + m(VirtualMethod) \ + m(ClassMethod) \ + m(PrivateMethod) \ + m(ProtectedMethod) \ + m(PublicMethod) \ + m(Method) \ + m(Typedef) \ + m(TypeTemplateParameter) \ + m(ValueTemplateParameter) \ + m(TemplateTemplateParameter) \ + m(TemplateParameter) \ + +enum StyleKind { +#define ENUMERATE(v) SK_ ## v, + NAMING_KEYS(ENUMERATE) +#undef ENUMERATE + SK_Count, + SK_Invalid +}; + +static StringRef const StyleNames[] = { +#define STRINGIZE(v) #v, + NAMING_KEYS(STRINGIZE) +#undef STRINGIZE +}; + +#undef NAMING_KEYS + +IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) { + auto const fromString = [](StringRef Str) { + return llvm::StringSwitch(Str) + .Case("lower_case", CT_LowerCase) + .Case("UPPER_CASE", CT_UpperCase) + .Case("camelBack", CT_CamelBack) + .Case("CamelCase", CT_CamelCase) + .Default(CT_AnyCase); + }; + + for (auto const &Name : StyleNames) { + NamingStyles.push_back( + NamingStyle(fromString(Options.get((Name + "Case").str(), "")), + Options.get((Name + "Prefix").str(), ""), + Options.get((Name + "Suffix").str(), ""))); + } + + IgnoreFailedSplit = Options.get("IgnoreFailedSplit", 0); +} + +void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + auto const toString = [](CaseType Type) { + switch (Type) { + case CT_AnyCase: + return "aNy_CasE"; + case CT_LowerCase: + return "lower_case"; + case CT_CamelBack: + return "camelBack"; + case CT_UpperCase: + return "UPPER_CASE"; + case CT_CamelCase: + return "CamelCase"; + } + + llvm_unreachable("Unknown Case Type"); + }; + + for (size_t i = 0; i < SK_Count; ++i) { + Options.store(Opts, (StyleNames[i] + "Case").str(), + toString(NamingStyles[i].Case)); + Options.store(Opts, (StyleNames[i] + "Prefix").str(), + NamingStyles[i].Prefix); + Options.store(Opts, (StyleNames[i] + "Suffix").str(), + NamingStyles[i].Suffix); + } + + Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit); +} + +void IdentifierNamingCheck::registerMatchers(MatchFinder *Finder) { +// FIXME: For now, only Decl and DeclRefExpr nodes are visited for checking and +// replacement. There is a lot of missing cases, such as references to a class +// name (as in 'const int CMyClass::kClassConstant = 4;'), to an enclosing +// context (namespace, class, etc). + + Finder->addMatcher(namedDecl().bind("decl"), this); + Finder->addMatcher(declRefExpr().bind("declref"), this); +} + +static bool matchesStyle(StringRef Name, + IdentifierNamingCheck::NamingStyle Style) { + static llvm::Regex Matchers[] = { + llvm::Regex("^.*$"), + llvm::Regex("^[a-z][a-z0-9_]*$"), + llvm::Regex("^[a-z][a-zA-Z0-9]*$"), + llvm::Regex("^[A-Z][A-Z0-9_]*$"), + llvm::Regex("^[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(Style.Case)].match(Name)) + Matches = false; + + return Matches; +} + +static std::string fixupWithCase(StringRef Name, + IdentifierNamingCheck::CaseType Case) { + static llvm::Regex Splitter( + "([a-z0-9A-Z]*)(_+)|([A-Z]?[a-z0-9]+)([A-Z]|$)|([A-Z]+)([A-Z]|$)"); + + SmallVector Substrs; + Name.split(Substrs, "_", -1, false); + + SmallVector Words; + for (auto Substr : Substrs) { + while (!Substr.empty()) { + SmallVector Groups; + if (!Splitter.match(Substr, &Groups)) + break; + + if (Groups[2].size() > 0) { + Words.push_back(Groups[1]); + Substr = Substr.substr(Groups[0].size()); + } else if (Groups[3].size() > 0) { + Words.push_back(Groups[3]); + Substr = Substr.substr(Groups[0].size() - Groups[4].size()); + } else if (Groups[5].size() > 0) { + Words.push_back(Groups[5]); + Substr = Substr.substr(Groups[0].size() - Groups[6].size()); + } + } + } + + if (Words.empty()) + return Name; + + std::string Fixup; + switch (Case) { + case IdentifierNamingCheck::CT_AnyCase: + Fixup += Name; + break; + + case IdentifierNamingCheck::CT_LowerCase: + for (auto const &Word : Words) { + if (&Word != &Words.front()) + Fixup += "_"; + Fixup += Word.lower(); + } + break; + + case IdentifierNamingCheck::CT_UpperCase: + for (auto const &Word : Words) { + if (&Word != &Words.front()) + Fixup += "_"; + Fixup += Word.upper(); + } + break; + + case IdentifierNamingCheck::CT_CamelCase: + for (auto const &Word : Words) { + Fixup += Word.substr(0, 1).upper(); + Fixup += Word.substr(1).lower(); + } + break; + + case IdentifierNamingCheck::CT_CamelBack: + for (auto const &Word : Words) { + if (&Word == &Words.front()) { + Fixup += Word.lower(); + } else { + Fixup += Word.substr(0, 1).upper(); + Fixup += Word.substr(1).lower(); + } + } + break; + } + + return Fixup; +} + +static std::string fixupWithStyle(StringRef Name, + IdentifierNamingCheck::NamingStyle Style) { + return Style.Prefix + fixupWithCase(Name, Style.Case) + Style.Suffix; +} + +static StyleKind findStyleKind( + const NamedDecl *D, + const std::vector &NamingStyles) { + if (isa(D) && NamingStyles[SK_Typedef].isSet()) + return SK_Typedef; + + if (const auto *Decl = dyn_cast(D)) { + if (Decl->isAnonymousNamespace()) + return SK_Invalid; + + if (Decl->isInline() && NamingStyles[SK_InlineNamespace].isSet()) + return SK_InlineNamespace; + + if (NamingStyles[SK_Namespace].isSet()) + return SK_Namespace; + } + + if (isa(D) && NamingStyles[SK_Enum].isSet()) + return SK_Enum; + + if (isa(D)) { + if (NamingStyles[SK_EnumConstant].isSet()) + return SK_EnumConstant; + + if (NamingStyles[SK_Constant].isSet()) + return SK_Constant; + + return SK_Invalid; + } + + if (const auto *Decl = dyn_cast(D)) { + if (Decl->isAnonymousStructOrUnion()) + return SK_Invalid; + + if (Decl->hasDefinition() && Decl->isAbstract() && + NamingStyles[SK_AbstractClass].isSet()) + return SK_AbstractClass; + + if (Decl->isStruct() && NamingStyles[SK_Struct].isSet()) + return SK_Struct; + + if (Decl->isStruct() && NamingStyles[SK_Class].isSet()) + return SK_Class; + + if (Decl->isClass() && NamingStyles[SK_Class].isSet()) + return SK_Class; + + if (Decl->isClass() && NamingStyles[SK_Struct].isSet()) + return SK_Struct; + + if (Decl->isUnion() && NamingStyles[SK_Union].isSet()) + return SK_Union; + + if (Decl->isEnum() && NamingStyles[SK_Enum].isSet()) + return SK_Enum; + + return SK_Invalid; + } + + if (const auto *Decl = dyn_cast(D)) { + QualType Type = Decl->getType(); + + if (!Type.isNull() && Type.isLocalConstQualified() && + NamingStyles[SK_ConstantMember].isSet()) + return SK_ConstantMember; + + if (!Type.isNull() && Type.isLocalConstQualified() && + NamingStyles[SK_Constant].isSet()) + return SK_Constant; + + if (Decl->getAccess() == AS_private && + NamingStyles[SK_PrivateMember].isSet()) + return SK_PrivateMember; + + if (Decl->getAccess() == AS_protected && + NamingStyles[SK_ProtectedMember].isSet()) + return SK_ProtectedMember; + + if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember].isSet()) + return SK_PublicMember; + + if (NamingStyles[SK_Member].isSet()) + return SK_Member; + + return SK_Invalid; + } + + if (const auto *Decl = dyn_cast(D)) { + QualType Type = Decl->getType(); + + if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable].isSet()) + return SK_ConstexprVariable; + + if (!Type.isNull() && Type.isLocalConstQualified() && + NamingStyles[SK_ConstantParameter].isSet()) + return SK_ConstantParameter; + + if (!Type.isNull() && Type.isLocalConstQualified() && + NamingStyles[SK_Constant].isSet()) + return SK_Constant; + + if (Decl->isParameterPack() && NamingStyles[SK_ParameterPack].isSet()) + return SK_ParameterPack; + + if (NamingStyles[SK_Parameter].isSet()) + return SK_Parameter; + + return SK_Invalid; + } + + if (const auto *Decl = dyn_cast(D)) { + QualType Type = Decl->getType(); + + if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable].isSet()) + return SK_ConstexprVariable; + + if (!Type.isNull() && Type.isLocalConstQualified() && + Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant].isSet()) + return SK_ClassConstant; + + if (!Type.isNull() && Type.isLocalConstQualified() && + Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant].isSet()) + return SK_GlobalConstant; + + if (!Type.isNull() && Type.isLocalConstQualified() && + Decl->isStaticLocal() && NamingStyles[SK_StaticConstant].isSet()) + return SK_StaticConstant; + + if (!Type.isNull() && Type.isLocalConstQualified() && + Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant].isSet()) + return SK_LocalConstant; + + if (!Type.isNull() && Type.isLocalConstQualified() && + Decl->isFunctionOrMethodVarDecl() && + NamingStyles[SK_LocalConstant].isSet()) + return SK_LocalConstant; + + if (!Type.isNull() && Type.isLocalConstQualified() && + NamingStyles[SK_Constant].isSet()) + return SK_Constant; + + if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember].isSet()) + return SK_ClassMember; + + if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable].isSet()) + return SK_GlobalVariable; + + if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable].isSet()) + return SK_StaticVariable; + + if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable].isSet()) + return SK_LocalVariable; + + if (Decl->isFunctionOrMethodVarDecl() && + NamingStyles[SK_LocalVariable].isSet()) + return SK_LocalVariable; + + if (NamingStyles[SK_Variable].isSet()) + return SK_Variable; + + return SK_Invalid; + } + + if (const auto *Decl = dyn_cast(D)) { + if (Decl->isMain() || !Decl->isUserProvided() || + Decl->isUsualDeallocationFunction() || + Decl->isCopyAssignmentOperator() || Decl->isMoveAssignmentOperator() || + Decl->size_overridden_methods() > 0) + return SK_Invalid; + + if (Decl->isConstexpr() && NamingStyles[SK_ConstexprMethod].isSet()) + return SK_ConstexprMethod; + + if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction].isSet()) + return SK_ConstexprFunction; + + if (Decl->isStatic() && NamingStyles[SK_ClassMethod].isSet()) + return SK_ClassMethod; + + if (Decl->isVirtual() && NamingStyles[SK_VirtualMethod].isSet()) + return SK_VirtualMethod; + + if (Decl->getAccess() == AS_private && + NamingStyles[SK_PrivateMethod].isSet()) + return SK_PrivateMethod; + + if (Decl->getAccess() == AS_protected && + NamingStyles[SK_ProtectedMethod].isSet()) + return SK_ProtectedMethod; + + if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMethod].isSet()) + return SK_PublicMethod; + + if (NamingStyles[SK_Method].isSet()) + return SK_Method; + + if (NamingStyles[SK_Function].isSet()) + return SK_Function; + + return SK_Invalid; + } + + if (const auto *Decl = dyn_cast(D)) { + if (Decl->isMain()) + return SK_Invalid; + + if (Decl->isConstexpr() && NamingStyles[SK_ConstexprFunction].isSet()) + return SK_ConstexprFunction; + + if (Decl->isGlobal() && NamingStyles[SK_GlobalFunction].isSet()) + return SK_GlobalFunction; + + if (NamingStyles[SK_Function].isSet()) + return SK_Function; + } + + if (isa(D)) { + if (NamingStyles[SK_TypeTemplateParameter].isSet()) + return SK_TypeTemplateParameter; + + if (NamingStyles[SK_TemplateParameter].isSet()) + return SK_TemplateParameter; + + return SK_Invalid; + } + + if (isa(D)) { + if (NamingStyles[SK_ValueTemplateParameter].isSet()) + return SK_ValueTemplateParameter; + + if (NamingStyles[SK_TemplateParameter].isSet()) + return SK_TemplateParameter; + + return SK_Invalid; + } + + if (isa(D)) { + if (NamingStyles[SK_TemplateTemplateParameter].isSet()) + return SK_TemplateTemplateParameter; + + if (NamingStyles[SK_TemplateParameter].isSet()) + return SK_TemplateParameter; + + return SK_Invalid; + } + + return SK_Invalid; +} + +void IdentifierNamingCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *DeclRef = Result.Nodes.getNodeAs("declref")) { + auto It = NamingCheckFailures.find(DeclRef->getDecl()); + if (It == NamingCheckFailures.end()) + return; + + NamingCheckFailure &Failure = It->second; + SourceRange Range = DeclRef->getNameInfo().getSourceRange(); + + Failure.Usages.push_back(Range); + Failure.ShouldFix = Failure.ShouldFix && + Result.SourceManager->isInMainFile(Range.getBegin()) && + Result.SourceManager->isInMainFile(Range.getEnd()) && + !Range.getBegin().isMacroID() && + !Range.getEnd().isMacroID(); + + return; + } + + if (const auto *Decl = Result.Nodes.getNodeAs("decl")) { + if (!Decl->getIdentifier() || Decl->getName().empty() || Decl->isImplicit()) + return; + + StyleKind SK = findStyleKind(Decl, NamingStyles); + if (SK == SK_Invalid) + return; + + NamingStyle Style = NamingStyles[SK]; + StringRef Name = Decl->getName(); + if (matchesStyle(Name, Style)) + return; + + std::string KindName = fixupWithCase(StyleNames[SK], CT_LowerCase); + std::replace(KindName.begin(), KindName.end(), '_', ' '); + + std::string Fixup = fixupWithStyle(Name, Style); + if (StringRef(Fixup).equals(Name)) { + if (!IgnoreFailedSplit) { + DEBUG(llvm::dbgs() << Decl->getLocStart().printToString( + *Result.SourceManager) + << format(": unable to split words for %s '%s'\n", + KindName.c_str(), Name)); + } + } else { + NamingCheckFailure &Failure = NamingCheckFailures[Decl]; + SourceRange Range = + DeclarationNameInfo(Decl->getDeclName(), Decl->getLocation()) + .getSourceRange(); + + Failure.Fixup = std::move(Fixup); + Failure.KindName = std::move(KindName); + Failure.ShouldFix = + Failure.ShouldFix && + Result.SourceManager->isInMainFile(Range.getBegin()) && + Result.SourceManager->isInMainFile(Range.getEnd()) && + !Range.getBegin().isMacroID() && !Range.getEnd().isMacroID(); + } + } +} + +void IdentifierNamingCheck::onEndOfTranslationUnit() { + for (const auto &Pair : NamingCheckFailures) { + const NamedDecl &Decl = *Pair.first; + const NamingCheckFailure &Failure = Pair.second; + + SourceRange DeclRange = + DeclarationNameInfo(Decl.getDeclName(), Decl.getLocation()) + .getSourceRange(); + auto Diag = diag(Decl.getLocStart(), "invalid case style for %0 '%1'") + << Failure.KindName << Decl.getName(); + + if (Failure.ShouldFix) { + Diag << FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(DeclRange), Failure.Fixup); + + for (const auto &Range : Failure.Usages) { + Diag << FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(Range), Failure.Fixup); + } + } + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -14,6 +14,7 @@ #include "ContainerSizeEmptyCheck.h" #include "ElseAfterReturnCheck.h" #include "FunctionSizeCheck.h" +#include "IdentifierNamingCheck.h" #include "NamedParameterCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" @@ -35,6 +36,8 @@ "readability-else-after-return"); CheckFactories.registerCheck( "readability-function-size"); + CheckFactories.registerCheck( + "readability-identifier-naming"); CheckFactories.registerCheck( "readability-named-parameter"); CheckFactories.registerCheck( Index: test/clang-tidy/readability-identifier-naming.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-identifier-naming.cpp @@ -0,0 +1,266 @@ +// RUN: $(dirname %s)/check_clang_tidy.sh %s readability-identifier-naming %t \ +// RUN: -config='{CheckOptions: [ \ +// RUN: {key: readability-identifier-naming.AbstractClassCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.AbstractClassPrefix, value: 'A'}, \ +// RUN: {key: readability-identifier-naming.ClassCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.ClassPrefix, value: 'C'}, \ +// RUN: {key: readability-identifier-naming.ClassConstantCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.ClassConstantPrefix, value: 'k'}, \ +// RUN: {key: readability-identifier-naming.ClassMemberCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.ClassMethodCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.ConstantCase, value: UPPER_CASE}, \ +// RUN: {key: readability-identifier-naming.ConstantSuffix, value: '_CST'}, \ +// RUN: {key: readability-identifier-naming.ConstexprFunctionCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.ConstexprMethodCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.ConstexprVariableCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.EnumCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.EnumPrefix, value: 'E'}, \ +// RUN: {key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE}, \ +// RUN: {key: readability-identifier-naming.FunctionCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE}, \ +// RUN: {key: readability-identifier-naming.GlobalFunctionCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.GlobalVariableCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.GlobalVariablePrefix, value: 'g_'}, \ +// RUN: {key: readability-identifier-naming.InlineNamespaceCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.LocalConstantCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.LocalConstantPrefix, value: 'k'}, \ +// RUN: {key: readability-identifier-naming.LocalVariableCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.MemberCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.MemberPrefix, value: 'm_'}, \ +// RUN: {key: readability-identifier-naming.ConstantMemberCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.PrivateMemberPrefix, value: '__'}, \ +// RUN: {key: readability-identifier-naming.ProtectedMemberPrefix, value: '_'}, \ +// RUN: {key: readability-identifier-naming.PublicMemberCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.MethodCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.PrivateMethodPrefix, value: '__'}, \ +// RUN: {key: readability-identifier-naming.ProtectedMethodPrefix, value: '_'}, \ +// RUN: {key: readability-identifier-naming.NamespaceCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.ParameterCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.ParameterPrefix, value: 'a_'}, \ +// RUN: {key: readability-identifier-naming.ConstantParameterCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.ConstantParameterPrefix, value: 'i_'}, \ +// RUN: {key: readability-identifier-naming.ParameterPackCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.PureFunctionCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.PureMethodCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE}, \ +// RUN: {key: readability-identifier-naming.StaticVariableCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.StaticVariablePrefix, value: 's_'}, \ +// RUN: {key: readability-identifier-naming.StructCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.TemplateParameterCase, value: UPPER_CASE}, \ +// RUN: {key: readability-identifier-naming.TemplateTemplateParameterCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.TemplateUsingCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.TemplateUsingPrefix, value: 'u_'}, \ +// RUN: {key: readability-identifier-naming.TypeTemplateParameterCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.TypeTemplateParameterSuffix, value: '_t'}, \ +// RUN: {key: readability-identifier-naming.TypedefCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.TypedefSuffix, value: '_t'}, \ +// RUN: {key: readability-identifier-naming.UnionCase, value: CamelCase}, \ +// RUN: {key: readability-identifier-naming.UnionPrefix, value: 'U'}, \ +// RUN: {key: readability-identifier-naming.UsingCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.ValueTemplateParameterCase, value: camelBack}, \ +// RUN: {key: readability-identifier-naming.VariableCase, value: lower_case}, \ +// RUN: {key: readability-identifier-naming.VirtualMethodCase, value: UPPER_CASE}, \ +// RUN: {key: readability-identifier-naming.VirtualMethodPrefix, value: 'v_'}, \ +// RUN: {key: readability-identifier-naming.IgnoreFailedSplit, value: 0} \ +// RUN: ]}' -- -std=c++11 +// REQUIRES: shell + +// FIXME: There should be more test cases for checking that references to class +// FIXME: name, declaration contexts, forward declarations, etc, are correctly +// FIXME: checked and renamed + +namespace FOO_NS { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for namespace 'FOO_NS' [readability-identifier-naming] +// CHECK-FIXES: {{^}}namespace foo_ns {{{$}} +inline namespace InlineNamespace { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for inline namespace 'InlineNamespace' +// CHECK-FIXES: {{^}}inline namespace inline_namespace {{{$}} + +#define BLA int FOO_bar +BLA; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for global variable 'FOO_bar' +// NO fix expected as FOO_bar is from macro expansion + +enum my_enumeration { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for enum 'my_enumeration' +// CHECK-FIXES: {{^}}enum EMyEnumeration {{{$}} + MyConstant = 1, +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'MyConstant' +// CHECK-FIXES: {{^}} MY_CONSTANT = 1,{{$}} + your_CONST = 1, +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'your_CONST' +// CHECK-FIXES: {{^}} YOUR_CONST = 1,{{$}} + THIS_ConstValue = 1, +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for enum constant 'THIS_ConstValue' +// CHECK-FIXES: {{^}} THIS_CONST_VALUE = 1,{{$}} +}; + +constexpr int ConstExpr_variable = MyConstant; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for constexpr variable 'ConstExpr_variable' +// CHECK-FIXES: {{^}}constexpr int const_expr_variable = MY_CONSTANT;{{$}} + +class my_class { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for class 'my_class' +// CHECK-FIXES: {{^}}class CMyClass {{{$}} + my_class(); + + const int MEMBER_one_1 = ConstExpr_variable; +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: invalid case style for constant member 'MEMBER_one_1' +// CHECK-FIXES: {{^}} const int member_one_1 = const_expr_variable;{{$}} + int member2 = 2; +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: invalid case style for private member 'member2' +// CHECK-FIXES: {{^}} int __member2 = 2;{{$}} + +private: + int private_member = 3; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for private member 'private_member' +// CHECK-FIXES: {{^}} int __private_member = 3;{{$}} + +protected: + int ProtMember; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for protected member 'ProtMember' +// CHECK-FIXES: {{^}} int _ProtMember;{{$}} + +public: + int PubMem; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for public member 'PubMem' +// CHECK-FIXES: {{^}} int pub_mem;{{$}} + + static const int classConstant; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for class constant 'classConstant' +// CHECK-FIXES: {{^}} static const int kClassConstant;{{$}} + static int ClassMember_2; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for class member 'ClassMember_2' +// CHECK-FIXES: {{^}} static int ClassMember2;{{$}} +}; + +const int my_class::classConstant = 4; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for class constant 'classConstant' +// CHECK-FIXES: {{^}}const int my_class::kClassConstant = 4;{{$}} +// FIXME: The fixup should reflect class name fixups as well: +// FIXME: {{^}}const int CMyClass::kClassConstant = 4;{{$}} + +int my_class::ClassMember_2 = 5; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for class member 'ClassMember_2' +// CHECK-FIXES: {{^}}int my_class::ClassMember2 = 5;{{$}} +// FIXME: The fixup should reflect class name fixups as well: +// FIXME: {{^}}int CMyClass::ClassMember2 = 5;{{$}} + +const int global_Constant = 6; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for global constant 'global_Constant' +// CHECK-FIXES: {{^}}const int GLOBAL_CONSTANT = 6;{{$}} +int Global_variable = 7; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for global variable 'Global_variable' +// CHECK-FIXES: {{^}}int g_global_variable = 7;{{$}} + +void global_function(int PARAMETER_1, int const CONST_parameter) { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for global function 'global_function' +// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: invalid case style for parameter 'PARAMETER_1' +// CHECK-MESSAGES: :[[@LINE-3]]:39: warning: invalid case style for constant parameter 'CONST_parameter' +// CHECK-FIXES: {{^}}void GlobalFunction(int a_parameter1, int const i_constParameter) {{{$}} + static const int THIS_static_ConsTant = 4; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for static constant 'THIS_static_ConsTant' +// CHECK-FIXES: {{^}} static const int THIS_STATIC_CONS_TANT = 4;{{$}} + static int THIS_static_variable; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for static variable 'THIS_static_variable' +// CHECK-FIXES: {{^}} static int s_thisStaticVariable;{{$}} + int const local_Constant = 3; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for local constant 'local_Constant' +// CHECK-FIXES: {{^}} int const kLocalConstant = 3;{{$}} + int LOCAL_VARIABLE; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for local variable 'LOCAL_VARIABLE' +// CHECK-FIXES: {{^}} int local_variable;{{$}} + + int LOCAL_Array__[] = {0, 1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for local variable 'LOCAL_Array__' +// CHECK-FIXES: {{^}} int local_array[] = {0, 1, 2};{{$}} + + for (auto _ : LOCAL_Array__) { + } +} + +template +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for type template parameter 'TYPE_parameters' +// CHECK-FIXES: {{^}}template{{$}} +void Global_Fun(TYPE_parameters... PARAMETER_PACK) { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for global function 'Global_Fun' +// CHECK-MESSAGES: :[[@LINE-2]]:17: warning: invalid case style for parameter pack 'PARAMETER_PACK' +// CHECK-FIXES: {{^}}void GlobalFun(TYPE_parameters... parameterPack) {{{$}} + global_function(1, 2); +// CHECK-FIXES: {{^}} GlobalFunction(1, 2);{{$}} + FOO_bar = Global_variable; +// CHECK-FIXES: {{^}} FOO_bar = g_global_variable;{{$}} +// NO fix expected for FOO_bar declared in macro expansion +} + +template class TPL_parameter, int COUNT_params, typename ... TYPE_parameters> +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for template template parameter 'TPL_parameter' +// CHECK-MESSAGES: :[[@LINE-2]]:50: warning: invalid case style for value template parameter 'COUNT_params' +// CHECK-MESSAGES: :[[@LINE-3]]:68: warning: invalid case style for type template parameter 'TYPE_parameters' +// CHECK-FIXES: {{^}}template class TplParameter, int countParams, typename ... typeParameters_t>{{$}} +class test_CLASS { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for class 'test_CLASS' +// CHECK-FIXES: {{^}}class CTestClass {{{$}} +}; + +class abstract_class { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for abstract class 'abstract_class' +// CHECK-FIXES: {{^}}class AAbstractClass {{{$}} + virtual ~abstract_class() = 0; + virtual void VIRTUAL_METHOD(); +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for virtual method 'VIRTUAL_METHOD' +// CHECK-FIXES: {{^}} virtual void v_VIRTUAL_METHOD();{{$}} + void non_Virtual_METHOD() {} +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for private method 'non_Virtual_METHOD' +// CHECK-FIXES: {{^}} void __non_Virtual_METHOD() {}{{$}} + static void CLASS_METHOD() {} +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for class method 'CLASS_METHOD' +// CHECK-FIXES: {{^}} static void classMethod() {}{{$}} + + constexpr int CST_expr_Method() { return 2; } +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for constexpr method 'CST_expr_Method' +// CHECK-FIXES: {{^}} constexpr int cst_expr_method() { return 2; }{{$}} + +private: + void PRIVate_Method(); +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for private method 'PRIVate_Method' +// CHECK-FIXES: {{^}} void __PRIVate_Method();{{$}} +protected: + void protected_Method(); +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for protected method 'protected_Method' +// CHECK-FIXES: {{^}} void _protected_Method();{{$}} +public: + void public_Method(); +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: invalid case style for method 'public_Method' +// CHECK-FIXES: {{^}} void publicMethod();{{$}} +}; + +constexpr int CE_function() { return 3; } +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for constexpr function 'CE_function' +// CHECK-FIXES: {{^}}constexpr int ce_function() { return 3; }{{$}} + +struct THIS___Structure { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for struct 'THIS___Structure' +// CHECK-FIXES: {{^}}struct this_structure {{{$}} + THIS___Structure(); +// FIXME: There should be a fixup for the constructor as well +// FIXME: {{^}} this_structure();{{$}} + + union __MyUnion_is_wonderful__ {}; +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: invalid case style for union '__MyUnion_is_wonderful__' +// CHECK-FIXES: {{^}} union UMyUnionIsWonderful {};{{$}} +}; + +typedef THIS___Structure struct_type; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for typedef 'struct_type' +// CHECK-FIXES: {{^}}typedef THIS___Structure struct_type_t;{{$}} +// FIXME: The fixup should reflect structure name fixups as well: +// FIXME: {{^}}typedef this_structure struct_type_t;{{$}} + +static void static_Function() { +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: invalid case style for function 'static_Function' +// CHECK-FIXES: {{^}}static void staticFunction() {{{$}} +} + +} +}