150
|
1 //===--- RenamderClangTidyCheck.h - clang-tidy ------------------*- C++ -*-===//
|
|
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-exception
|
|
6 //
|
|
7 //===----------------------------------------------------------------------===//
|
|
8
|
|
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
|
|
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
|
|
11
|
|
12 #include "../ClangTidyCheck.h"
|
|
13 #include "llvm/ADT/DenseMap.h"
|
|
14 #include "llvm/ADT/DenseSet.h"
|
|
15 #include "llvm/ADT/Optional.h"
|
|
16 #include <string>
|
|
17 #include <utility>
|
|
18
|
|
19 namespace clang {
|
|
20
|
|
21 class MacroInfo;
|
|
22
|
|
23 namespace tidy {
|
|
24
|
|
25 /// Base class for clang-tidy checks that want to flag declarations and/or
|
|
26 /// macros for renaming based on customizable criteria.
|
|
27 class RenamerClangTidyCheck : public ClangTidyCheck {
|
|
28 public:
|
|
29 RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);
|
|
30 ~RenamerClangTidyCheck();
|
|
31
|
|
32 /// Derived classes should not implement any matching logic themselves; this
|
|
33 /// class will do the matching and call the derived class'
|
|
34 /// GetDeclFailureInfo() and GetMacroFailureInfo() for determining whether a
|
|
35 /// given identifier passes or fails the check.
|
|
36 void registerMatchers(ast_matchers::MatchFinder *Finder) override final;
|
|
37 void
|
|
38 check(const ast_matchers::MatchFinder::MatchResult &Result) override final;
|
|
39 void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
|
|
40 Preprocessor *ModuleExpanderPP) override final;
|
|
41 void onEndOfTranslationUnit() override final;
|
|
42
|
|
43 /// This enum will be used in %select of the diagnostic message.
|
|
44 /// Each value below IgnoreFailureThreshold should have an error message.
|
|
45 enum class ShouldFixStatus {
|
|
46 ShouldFix,
|
|
47
|
|
48 /// The fixup will conflict with a language keyword,
|
|
49 /// so we can't fix it automatically.
|
|
50 ConflictsWithKeyword,
|
|
51
|
|
52 /// The fixup will conflict with a macro
|
|
53 /// definition, so we can't fix it
|
|
54 /// automatically.
|
|
55 ConflictsWithMacroDefinition,
|
|
56
|
|
57 /// Values pass this threshold will be ignored completely
|
|
58 /// i.e no message, no fixup.
|
|
59 IgnoreFailureThreshold,
|
|
60
|
|
61 /// If the identifier was used or declared within a macro we
|
|
62 /// won't offer a fixup for safety reasons.
|
|
63 InsideMacro,
|
|
64 };
|
|
65
|
|
66 /// Information describing a failed check
|
|
67 struct FailureInfo {
|
|
68 std::string KindName; // Tag or misc info to be used as derived classes need
|
|
69 std::string Fixup; // The name that will be proposed as a fix-it hint
|
|
70 };
|
|
71
|
|
72 /// Holds an identifier name check failure, tracking the kind of the
|
|
73 /// identifier, its possible fixup and the starting locations of all the
|
|
74 /// identifier usages.
|
|
75 struct NamingCheckFailure {
|
|
76 FailureInfo Info;
|
|
77
|
|
78 /// Whether the failure should be fixed or not.
|
|
79 ///
|
|
80 /// e.g.: if the identifier was used or declared within a macro we won't
|
|
81 /// offer a fixup for safety reasons.
|
|
82 bool ShouldFix() const {
|
|
83 return FixStatus == ShouldFixStatus::ShouldFix && !Info.Fixup.empty();
|
|
84 }
|
|
85
|
|
86 bool ShouldNotify() const {
|
|
87 return FixStatus < ShouldFixStatus::IgnoreFailureThreshold;
|
|
88 }
|
|
89
|
|
90 ShouldFixStatus FixStatus = ShouldFixStatus::ShouldFix;
|
|
91
|
|
92 /// A set of all the identifier usages starting SourceLocation, in
|
|
93 /// their encoded form.
|
|
94 llvm::DenseSet<unsigned> RawUsageLocs;
|
|
95
|
|
96 NamingCheckFailure() = default;
|
|
97 };
|
|
98
|
|
99 using NamingCheckId = std::pair<SourceLocation, std::string>;
|
|
100
|
|
101 using NamingCheckFailureMap =
|
|
102 llvm::DenseMap<NamingCheckId, NamingCheckFailure>;
|
|
103
|
|
104 /// Check Macros for style violations.
|
|
105 void checkMacro(SourceManager &sourceMgr, const Token &MacroNameTok,
|
|
106 const MacroInfo *MI);
|
|
107
|
|
108 /// Add a usage of a macro if it already has a violation.
|
|
109 void expandMacro(const Token &MacroNameTok, const MacroInfo *MI);
|
|
110
|
|
111 protected:
|
|
112 /// Overridden by derived classes, returns information about if and how a Decl
|
|
113 /// failed the check. A 'None' result means the Decl did not fail the check.
|
|
114 virtual llvm::Optional<FailureInfo>
|
|
115 GetDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const = 0;
|
|
116
|
|
117 /// Overridden by derived classes, returns information about if and how a
|
|
118 /// macro failed the check. A 'None' result means the macro did not fail the
|
|
119 /// check.
|
|
120 virtual llvm::Optional<FailureInfo>
|
|
121 GetMacroFailureInfo(const Token &MacroNameTok,
|
|
122 const SourceManager &SM) const = 0;
|
|
123
|
|
124 /// Represents customized diagnostic text and how arguments should be applied.
|
|
125 /// Example usage:
|
|
126 ///
|
|
127 /// return DiagInfo{"my %1 very %2 special %3 text",
|
|
128 /// [=](DiagnosticBuilder &diag) {
|
|
129 /// diag << arg1 << arg2 << arg3;
|
|
130 /// }};
|
|
131 struct DiagInfo {
|
|
132 std::string Text;
|
|
133 llvm::unique_function<void(DiagnosticBuilder &)> ApplyArgs;
|
|
134 };
|
|
135
|
|
136 /// Overridden by derived classes, returns a description of the diagnostic
|
|
137 /// that should be emitted for the given failure. The base class will then
|
|
138 /// further customize the diagnostic by adding info about whether the fix-it
|
|
139 /// can be automatically applied or not.
|
|
140 virtual DiagInfo GetDiagInfo(const NamingCheckId &ID,
|
|
141 const NamingCheckFailure &Failure) const = 0;
|
|
142
|
|
143 private:
|
|
144 NamingCheckFailureMap NamingCheckFailures;
|
|
145 };
|
|
146
|
|
147 } // namespace tidy
|
|
148 } // namespace clang
|
|
149
|
|
150 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
|