diff clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h @ 150:1d019706d866

LLVM10
author anatofuz
date Thu, 13 Feb 2020 15:10:13 +0900
parents
children 0572611fdcc8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h	Thu Feb 13 15:10:13 2020 +0900
@@ -0,0 +1,150 @@
+//===--- RenamderClangTidyCheck.h - clang-tidy ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+#include <string>
+#include <utility>
+
+namespace clang {
+
+class MacroInfo;
+
+namespace tidy {
+
+/// Base class for clang-tidy checks that want to flag declarations and/or
+/// macros for renaming based on customizable criteria.
+class RenamerClangTidyCheck : public ClangTidyCheck {
+public:
+  RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);
+  ~RenamerClangTidyCheck();
+
+  /// Derived classes should not implement any matching logic themselves; this
+  /// class will do the matching and call the derived class'
+  /// GetDeclFailureInfo() and GetMacroFailureInfo() for determining whether a
+  /// given identifier passes or fails the check.
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override final;
+  void
+  check(const ast_matchers::MatchFinder::MatchResult &Result) override final;
+  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+                           Preprocessor *ModuleExpanderPP) override final;
+  void onEndOfTranslationUnit() override final;
+
+  /// This enum will be used in %select of the diagnostic message.
+  /// Each value below IgnoreFailureThreshold should have an error message.
+  enum class ShouldFixStatus {
+    ShouldFix,
+
+    /// The fixup will conflict with a language keyword,
+    /// so we can't fix it automatically.
+    ConflictsWithKeyword,
+
+    /// The fixup will conflict with a macro
+    /// definition, so we can't fix it
+    /// automatically.
+    ConflictsWithMacroDefinition,
+
+    /// Values pass this threshold will be ignored completely
+    /// i.e no message, no fixup.
+    IgnoreFailureThreshold,
+
+    /// If the identifier was used or declared within a macro we
+    /// won't offer a fixup for safety reasons.
+    InsideMacro,
+  };
+
+  /// Information describing a failed check
+  struct FailureInfo {
+    std::string KindName; // Tag or misc info to be used as derived classes need
+    std::string Fixup;    // The name that will be proposed as a fix-it hint
+  };
+
+  /// Holds an identifier name check failure, tracking the kind of the
+  /// identifier, its possible fixup and the starting locations of all the
+  /// identifier usages.
+  struct NamingCheckFailure {
+    FailureInfo Info;
+
+    /// Whether the failure should be fixed or not.
+    ///
+    /// e.g.: if the identifier was used or declared within a macro we won't
+    /// offer a fixup for safety reasons.
+    bool ShouldFix() const {
+      return FixStatus == ShouldFixStatus::ShouldFix && !Info.Fixup.empty();
+    }
+
+    bool ShouldNotify() const {
+      return FixStatus < ShouldFixStatus::IgnoreFailureThreshold;
+    }
+
+    ShouldFixStatus FixStatus = ShouldFixStatus::ShouldFix;
+
+    /// A set of all the identifier usages starting SourceLocation, in
+    /// their encoded form.
+    llvm::DenseSet<unsigned> RawUsageLocs;
+
+    NamingCheckFailure() = default;
+  };
+
+  using NamingCheckId = std::pair<SourceLocation, std::string>;
+
+  using NamingCheckFailureMap =
+      llvm::DenseMap<NamingCheckId, NamingCheckFailure>;
+
+  /// Check Macros for style violations.
+  void checkMacro(SourceManager &sourceMgr, const Token &MacroNameTok,
+                  const MacroInfo *MI);
+
+  /// Add a usage of a macro if it already has a violation.
+  void expandMacro(const Token &MacroNameTok, const MacroInfo *MI);
+
+protected:
+  /// Overridden by derived classes, returns information about if and how a Decl
+  /// failed the check. A 'None' result means the Decl did not fail the check.
+  virtual llvm::Optional<FailureInfo>
+  GetDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const = 0;
+
+  /// Overridden by derived classes, returns information about if and how a
+  /// macro failed the check. A 'None' result means the macro did not fail the
+  /// check.
+  virtual llvm::Optional<FailureInfo>
+  GetMacroFailureInfo(const Token &MacroNameTok,
+                      const SourceManager &SM) const = 0;
+
+  /// Represents customized diagnostic text and how arguments should be applied.
+  /// Example usage:
+  ///
+  /// return DiagInfo{"my %1 very %2 special %3 text",
+  ///                  [=](DiagnosticBuilder &diag) {
+  ///                    diag << arg1 << arg2 << arg3;
+  ///                  }};
+  struct DiagInfo {
+    std::string Text;
+    llvm::unique_function<void(DiagnosticBuilder &)> ApplyArgs;
+  };
+
+  /// Overridden by derived classes, returns a description of the diagnostic
+  /// that should be emitted for the given failure. The base class will then
+  /// further customize the diagnostic by adding info about whether the fix-it
+  /// can be automatically applied or not.
+  virtual DiagInfo GetDiagInfo(const NamingCheckId &ID,
+                               const NamingCheckFailure &Failure) const = 0;
+
+private:
+  NamingCheckFailureMap NamingCheckFailures;
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H