1//===--- RenamerClangTidyCheck.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/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/or
27/// macros for renaming based on customizable criteria.
28class RenamerClangTidyCheck : public ClangTidyCheck {
29public:
30 RenamerClangTidyCheck(StringRef CheckName, ClangTidyContext *Context);
31 ~RenamerClangTidyCheck();
32
33 /// Derived classes should not implement any matching logic themselves; this
34 /// class will do the matching and call the derived class'
35 /// getDeclFailureInfo() and getMacroFailureInfo() for determining whether a
36 /// 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 from
44 /// 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 macro
57 /// definition, so we can't fix it
58 /// 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 completely
65 /// i.e no message, no fixup.
66 IgnoreFailureThreshold,
67
68 /// If the identifier was used or declared within a macro we
69 /// won't offer a fixup for safety reasons.
70 InsideMacro,
71 };
72
73 /// Information describing a failed check
74 struct FailureInfo {
75 std::string KindName; // Tag or misc info to be used as derived classes need
76 std::string Fixup; // The name that will be proposed as a fix-it hint
77 };
78
79 /// Holds an identifier name check failure, tracking the kind of the
80 /// identifier, its possible fixup and the starting locations of all the
81 /// 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't
88 /// 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 RenamerClangTidyCheck::NamingCheckId &Decl,
119 SourceRange Range, const SourceManager &SourceMgr);
120
121 /// Convenience method when the usage to be added is a NamedDecl.
122 void addUsage(const NamedDecl *Decl, SourceRange Range,
123 const SourceManager &SourceMgr);
124
125 void checkNamedDecl(const NamedDecl *Decl, const SourceManager &SourceMgr);
126
127protected:
128 /// Overridden by derived classes, returns information about if and how a Decl
129 /// failed the check. A 'std::nullopt' result means the Decl did not fail the
130 /// check.
131 virtual std::optional<FailureInfo>
132 getDeclFailureInfo(const NamedDecl *Decl, const SourceManager &SM) const = 0;
133
134 /// Overridden by derived classes, returns information about if and how a
135 /// macro failed the check. A 'std::nullopt' result means the macro did not
136 /// fail the check.
137 virtual std::optional<FailureInfo>
138 getMacroFailureInfo(const Token &MacroNameTok,
139 const SourceManager &SM) const = 0;
140
141 /// Represents customized diagnostic text and how arguments should be applied.
142 /// Example usage:
143 ///
144 /// return DiagInfo{"my %1 very %2 special %3 text",
145 /// [=](DiagnosticBuilder &diag) {
146 /// diag << arg1 << arg2 << arg3;
147 /// }};
148 struct DiagInfo {
149 std::string Text;
150 llvm::unique_function<void(DiagnosticBuilder &)> ApplyArgs;
151 };
152
153 /// Overridden by derived classes, returns a description of the diagnostic
154 /// that should be emitted for the given failure. The base class will then
155 /// further customize the diagnostic by adding info about whether the fix-it
156 /// can be automatically applied or not.
157 virtual DiagInfo getDiagInfo(const NamingCheckId &ID,
158 const NamingCheckFailure &Failure) const = 0;
159
160private:
161 NamingCheckFailureMap NamingCheckFailures;
162 const bool AggressiveDependentMemberLookup;
163};
164
165} // namespace tidy
166} // namespace clang
167
168#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
169

source code of clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h