brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.6 KiB · 0b17af8 Raw
244 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H11 12#include "../utils/RenamerClangTidyCheck.h"13#include <optional>14#include <string>15namespace clang::tidy {16namespace readability {17 18enum StyleKind : int;19 20/// Checks for identifiers naming style mismatch.21///22/// This check will try to enforce coding guidelines on the identifiers naming.23/// It supports `lower_case`, `UPPER_CASE`, `camelBack` and `CamelCase` casing24/// and tries to convert from one to another if a mismatch is detected.25///26/// It also supports a fixed prefix and suffix that will be prepended or27/// appended to the identifiers, regardless of the casing.28///29/// Many configuration options are available, in order to be able to create30/// different rules for different kind of identifier. In general, the31/// rules are falling back to a more generic rule if the specific case is not32/// configured.33class IdentifierNamingCheck final : public RenamerClangTidyCheck {34public:35  IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context);36  ~IdentifierNamingCheck() override;37 38  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;39 40  enum CaseType {41    CT_AnyCase = 0,42    CT_LowerCase,43    CT_CamelBack,44    CT_UpperCase,45    CT_CamelCase,46    CT_CamelSnakeCase,47    CT_CamelSnakeBack,48    CT_LeadingUpperSnakeCase49  };50 51  enum HungarianPrefixType {52    HPT_Off = 0,53    HPT_On,54    HPT_LowerCase,55    HPT_CamelCase,56  };57 58  struct HungarianNotationOption {59    HungarianNotationOption() = default;60 61    std::optional<CaseType> Case;62    HungarianPrefixType HPType = HungarianPrefixType::HPT_Off;63    llvm::StringMap<std::string> General;64    llvm::StringMap<std::string> CString;65    llvm::StringMap<std::string> PrimitiveType;66    llvm::StringMap<std::string> UserDefinedType;67    llvm::StringMap<std::string> DerivedType;68  };69 70  struct NamingStyle {71    NamingStyle() = default;72 73    NamingStyle(std::optional<CaseType> Case, StringRef Prefix,74                StringRef Suffix, StringRef IgnoredRegexpStr,75                HungarianPrefixType HPType);76    NamingStyle(const NamingStyle &O) = delete;77    NamingStyle &operator=(NamingStyle &&O) = default;78    NamingStyle(NamingStyle &&O) = default;79 80    std::optional<CaseType> Case;81    std::string Prefix;82    std::string Suffix;83    // Store both compiled and non-compiled forms so original value can be84    // serialized85    llvm::Regex IgnoredRegexp;86    std::string IgnoredRegexpStr;87 88    HungarianPrefixType HPType;89  };90 91  struct HungarianNotation {92  public:93    bool checkOptionValid(int StyleKindIndex) const;94    bool isOptionEnabled(StringRef OptionKey,95                         const llvm::StringMap<std::string> &StrMap) const;96 97    size_t getAsteriskCount(const std::string &TypeName) const;98    size_t getAsteriskCount(const std::string &TypeName,99                            const NamedDecl *ND) const;100 101    void loadDefaultConfig(102        IdentifierNamingCheck::HungarianNotationOption &HNOption) const;103    void loadFileConfig(104        const ClangTidyCheck::OptionsView &Options,105        IdentifierNamingCheck::HungarianNotationOption &HNOption) const;106 107    bool removeDuplicatedPrefix(108        SmallVector<StringRef, 8> &Words,109        const IdentifierNamingCheck::HungarianNotationOption &HNOption) const;110 111    std::string getPrefix(112        const Decl *D,113        const IdentifierNamingCheck::HungarianNotationOption &HNOption) const;114 115    std::string getDataTypePrefix(116        StringRef TypeName, const NamedDecl *ND,117        const IdentifierNamingCheck::HungarianNotationOption &HNOption) const;118 119    std::string getClassPrefix(120        const CXXRecordDecl *CRD,121        const IdentifierNamingCheck::HungarianNotationOption &HNOption) const;122 123    std::string getEnumPrefix(const EnumConstantDecl *ECD) const;124    std::string getDeclTypeName(const NamedDecl *ND) const;125  };126 127  struct FileStyle {128    FileStyle() : IsActive(false), IgnoreMainLikeFunctions(false) {}129    FileStyle(SmallVectorImpl<std::optional<NamingStyle>> &&Styles,130              HungarianNotationOption HNOption, bool IgnoreMainLike,131              bool CheckAnonFieldInParent)132        : Styles(std::move(Styles)), HNOption(std::move(HNOption)),133          IsActive(true), IgnoreMainLikeFunctions(IgnoreMainLike),134          CheckAnonFieldInParentScope(CheckAnonFieldInParent) {}135 136    ArrayRef<std::optional<NamingStyle>> getStyles() const {137      assert(IsActive);138      return Styles;139    }140 141    const HungarianNotationOption &getHNOption() const {142      assert(IsActive);143      return HNOption;144    }145 146    bool isActive() const { return IsActive; }147    bool isIgnoringMainLikeFunction() const { return IgnoreMainLikeFunctions; }148 149    bool isCheckingAnonFieldInParentScope() const {150      return CheckAnonFieldInParentScope;151    }152 153  private:154    SmallVector<std::optional<NamingStyle>, 0> Styles;155    HungarianNotationOption HNOption;156    bool IsActive;157    bool IgnoreMainLikeFunctions;158    bool CheckAnonFieldInParentScope;159  };160 161  IdentifierNamingCheck::FileStyle162  getFileStyleFromOptions(const ClangTidyCheck::OptionsView &Options) const;163 164  bool165  matchesStyle(StringRef Type, StringRef Name,166               const IdentifierNamingCheck::NamingStyle &Style,167               const IdentifierNamingCheck::HungarianNotationOption &HNOption,168               const NamedDecl *Decl) const;169 170  std::string171  fixupWithCase(StringRef Type, StringRef Name, const Decl *D,172                const IdentifierNamingCheck::NamingStyle &Style,173                const IdentifierNamingCheck::HungarianNotationOption &HNOption,174                IdentifierNamingCheck::CaseType Case) const;175 176  std::string177  fixupWithStyle(StringRef Type, StringRef Name,178                 const IdentifierNamingCheck::NamingStyle &Style,179                 const IdentifierNamingCheck::HungarianNotationOption &HNOption,180                 const Decl *D) const;181 182  StyleKind findStyleKind(183      const NamedDecl *D,184      ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,185      bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope) const;186 187  std::optional<RenamerClangTidyCheck::FailureInfo> getFailureInfo(188      StringRef Type, StringRef Name, const NamedDecl *ND,189      SourceLocation Location,190      ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,191      const IdentifierNamingCheck::HungarianNotationOption &HNOption,192      StyleKind SK, const SourceManager &SM, bool IgnoreFailedSplit) const;193 194  bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl,195                                 bool IncludeMainLike) const;196 197private:198  std::optional<FailureInfo>199  getDeclFailureInfo(const NamedDecl *Decl,200                     const SourceManager &SM) const override;201  std::optional<FailureInfo>202  getMacroFailureInfo(const Token &MacroNameTok,203                      const SourceManager &SM) const override;204  DiagInfo getDiagInfo(const NamingCheckId &ID,205                       const NamingCheckFailure &Failure) const override;206 207  const FileStyle &getStyleForFile(StringRef FileName) const;208  StringRef getRealFileName(StringRef FileName) const;209 210  /// Find the style kind of a field in an anonymous record.211  StyleKind findStyleKindForAnonField(212      const FieldDecl *AnonField,213      ArrayRef<std::optional<NamingStyle>> NamingStyles) const;214 215  StyleKind findStyleKindForField(216      const FieldDecl *Field, QualType Type,217      ArrayRef<std::optional<NamingStyle>> NamingStyles) const;218 219  StyleKind220  findStyleKindForVar(const VarDecl *Var, QualType Type,221                      ArrayRef<std::optional<NamingStyle>> NamingStyles) const;222 223  /// Stores the style options as a vector, indexed by the specified \ref224  /// StyleKind, for a given directory.225  mutable llvm::StringMap<FileStyle> NamingStylesCache;226  mutable llvm::StringMap<SmallString<256U>> RealFileNameCache;227  FileStyle *MainFileStyle;228  ClangTidyContext *Context;229  const bool GetConfigPerFile;230  const bool IgnoreFailedSplit;231  HungarianNotation HungarianNotation;232};233 234} // namespace readability235template <>236struct OptionEnumMapping<readability::IdentifierNamingCheck::CaseType> {237  static llvm::ArrayRef<238      std::pair<readability::IdentifierNamingCheck::CaseType, StringRef>>239  getEnumMapping();240};241} // namespace clang::tidy242 243#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_IDENTIFIERNAMINGCHECK_H244