brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · fe1059d Raw
171 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_UTILS_RENAMERCLANGTIDYCHECK_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_RENAMERCLANGTIDYCHECK_H11 12#include "../ClangTidyCheck.h"13#include "llvm/ADT/DenseMap.h"14#include "llvm/ADT/DenseSet.h"15#include "llvm/ADT/FunctionExtras.h"16#include <optional>17#include <string>18#include <utility>19 20namespace clang {21 22class MacroInfo;23 24namespace tidy {25 26/// Base class for clang-tidy checks that want to flag declarations and/or27/// macros for renaming based on customizable criteria.28class RenamerClangTidyCheck : public ClangTidyCheck {29public:30  RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);31  ~RenamerClangTidyCheck() override;32 33  /// Derived classes should not implement any matching logic themselves; this34  /// class will do the matching and call the derived class'35  /// getDeclFailureInfo() and getMacroFailureInfo() for determining whether a36  /// given identifier passes or fails the check.37  void registerMatchers(ast_matchers::MatchFinder *Finder) final;38  void check(const ast_matchers::MatchFinder::MatchResult &Result) final;39  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,40                           Preprocessor *ModuleExpanderPP) final;41  void onEndOfTranslationUnit() final;42 43  /// Derived classes that override this function should call this method from44  /// the overridden method.45  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;46 47  /// This enum will be used in %select of the diagnostic message.48  /// Each value below IgnoreFailureThreshold should have an error message.49  enum class ShouldFixStatus {50    ShouldFix,51 52    /// The fixup will conflict with a language keyword,53    /// so we can't fix it automatically.54    ConflictsWithKeyword,55 56    /// The fixup will conflict with a macro57    /// definition, so we can't fix it58    /// automatically.59    ConflictsWithMacroDefinition,60 61    /// The fixup results in an identifier that is not a valid c/c++ identifier.62    FixInvalidIdentifier,63 64    /// Values pass this threshold will be ignored completely65    /// i.e no message, no fixup.66    IgnoreFailureThreshold,67 68    /// If the identifier was used or declared within a macro we69    /// won't offer a fixup for safety reasons.70    InsideMacro,71  };72 73  /// Information describing a failed check74  struct FailureInfo {75    std::string KindName; // Tag or misc info to be used as derived classes need76    std::string Fixup;    // The name that will be proposed as a fix-it hint77  };78 79  /// Holds an identifier name check failure, tracking the kind of the80  /// identifier, its possible fixup and the starting locations of all the81  /// identifier usages.82  struct NamingCheckFailure {83    FailureInfo Info;84 85    /// Whether the failure should be fixed or not.86    ///87    /// e.g.: if the identifier was used or declared within a macro we won't88    /// offer a fixup for safety reasons.89    bool shouldFix() const {90      return FixStatus == ShouldFixStatus::ShouldFix && !Info.Fixup.empty();91    }92 93    bool shouldNotify() const {94      return FixStatus < ShouldFixStatus::IgnoreFailureThreshold;95    }96 97    ShouldFixStatus FixStatus = ShouldFixStatus::ShouldFix;98 99    /// A set of all the identifier usages starting SourceLocation.100    llvm::DenseSet<SourceLocation> RawUsageLocs;101 102    NamingCheckFailure() = default;103  };104 105  using NamingCheckId = std::pair<SourceLocation, StringRef>;106 107  using NamingCheckFailureMap =108      llvm::DenseMap<NamingCheckId, NamingCheckFailure>;109 110  /// Check Macros for style violations.111  void checkMacro(const Token &MacroNameTok, const MacroInfo *MI,112                  const SourceManager &SourceMgr);113 114  /// Add a usage of a macro if it already has a violation.115  void expandMacro(const Token &MacroNameTok, const MacroInfo *MI,116                   const SourceManager &SourceMgr);117 118  void addUsage(const NamedDecl *Decl, SourceRange Range,119                const SourceManager &SourceMgr);120 121protected:122  /// Overridden by derived classes, returns information about if and how a Decl123  /// failed the check. A 'std::nullopt' result means the Decl did not fail the124  /// check.125  virtual std::optional<FailureInfo>126  getDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const = 0;127 128  /// Overridden by derived classes, returns information about if and how a129  /// macro failed the check. A 'std::nullopt' result means the macro did not130  /// fail the check.131  virtual std::optional<FailureInfo>132  getMacroFailureInfo(const Token &MacroNameTok,133                      const SourceManager &SM) const = 0;134 135  /// Represents customized diagnostic text and how arguments should be applied.136  /// Example usage:137  ///138  /// return DiagInfo{"my %1 very %2 special %3 text",139  ///                  [=](DiagnosticBuilder &diag) {140  ///                    diag << arg1 << arg2 << arg3;141  ///                  }};142  struct DiagInfo {143    std::string Text;144    llvm::unique_function<void(DiagnosticBuilder &)> ApplyArgs;145  };146 147  /// Overridden by derived classes, returns a description of the diagnostic148  /// that should be emitted for the given failure. The base class will then149  /// further customize the diagnostic by adding info about whether the fix-it150  /// can be automatically applied or not.151  virtual DiagInfo getDiagInfo(const NamingCheckId &ID,152                               const NamingCheckFailure &Failure) const = 0;153 154private:155  // Manage additions to the Failure/usage map156  //157  // return the result of NamingCheckFailures::try_emplace() if the usage was158  // accepted.159  std::pair<NamingCheckFailureMap::iterator, bool>160  addUsage(const RenamerClangTidyCheck::NamingCheckId &FailureId,161           SourceRange UsageRange, const SourceManager &SourceMgr);162 163  NamingCheckFailureMap NamingCheckFailures;164  const bool AggressiveDependentMemberLookup;165};166 167} // namespace tidy168} // namespace clang169 170#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_RENAMERCLANGTIDYCHECK_H171