| //===--- RenamerClangTidyCheck.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/FunctionExtras.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; |
| |
| /// Derived classes that override this function should call this method from |
| /// the overridden method. |
| void storeOptions(ClangTidyOptions::OptionMap &Opts) override; |
| |
| /// 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, |
| |
| /// The fixup results in an identifier that is not a valid c/c++ identifier. |
| FixInvalidIdentifier, |
| |
| /// 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. |
| llvm::DenseSet<SourceLocation> 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); |
| |
| void addUsage(const RenamerClangTidyCheck::NamingCheckId &Decl, |
| SourceRange Range, SourceManager *SourceMgr = nullptr); |
| |
| /// Convenience method when the usage to be added is a NamedDecl. |
| void addUsage(const NamedDecl *Decl, SourceRange Range, |
| SourceManager *SourceMgr = nullptr); |
| |
| 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; |
| const bool AggressiveDependentMemberLookup; |
| }; |
| |
| } // namespace tidy |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H |