1 //===--- RenamerClangTidyCheck.h - clang-tidy -------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H
12 #include "../ClangTidyCheck.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/DenseSet.h"
15 #include "llvm/ADT/FunctionExtras.h"
26 /// Base class for clang-tidy checks that want to flag declarations and/or
27 /// macros for renaming based on customizable criteria.
28 class RenamerClangTidyCheck
: public ClangTidyCheck
{
30 RenamerClangTidyCheck(StringRef CheckName
, ClangTidyContext
*Context
);
31 ~RenamerClangTidyCheck();
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
;
43 /// Derived classes that override this function should call this method from
44 /// the overridden method.
45 void storeOptions(ClangTidyOptions::OptionMap
&Opts
) override
;
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
{
52 /// The fixup will conflict with a language keyword,
53 /// so we can't fix it automatically.
56 /// The fixup will conflict with a macro
57 /// definition, so we can't fix it
59 ConflictsWithMacroDefinition
,
61 /// The fixup results in an identifier that is not a valid c/c++ identifier.
64 /// Values pass this threshold will be ignored completely
65 /// i.e no message, no fixup.
66 IgnoreFailureThreshold
,
68 /// If the identifier was used or declared within a macro we
69 /// won't offer a fixup for safety reasons.
73 /// Information describing a failed check
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
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
{
85 /// Whether the failure should be fixed or not.
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();
93 bool shouldNotify() const {
94 return FixStatus
< ShouldFixStatus::IgnoreFailureThreshold
;
97 ShouldFixStatus FixStatus
= ShouldFixStatus::ShouldFix
;
99 /// A set of all the identifier usages starting SourceLocation.
100 llvm::DenseSet
<SourceLocation
> RawUsageLocs
;
102 NamingCheckFailure() = default;
105 using NamingCheckId
= std::pair
<SourceLocation
, StringRef
>;
107 using NamingCheckFailureMap
=
108 llvm::DenseMap
<NamingCheckId
, NamingCheckFailure
>;
110 /// Check Macros for style violations.
111 void checkMacro(const SourceManager
&SourceMgr
, const Token
&MacroNameTok
,
112 const MacroInfo
*MI
);
114 /// Add a usage of a macro if it already has a violation.
115 void expandMacro(const Token
&MacroNameTok
, const MacroInfo
*MI
);
117 void addUsage(const RenamerClangTidyCheck::NamingCheckId
&Decl
,
118 SourceRange Range
, const SourceManager
*SourceMgr
= nullptr);
120 /// Convenience method when the usage to be added is a NamedDecl.
121 void addUsage(const NamedDecl
*Decl
, SourceRange Range
,
122 const SourceManager
*SourceMgr
= nullptr);
124 void checkNamedDecl(const NamedDecl
*Decl
, const SourceManager
&SourceMgr
);
127 /// Overridden by derived classes, returns information about if and how a Decl
128 /// failed the check. A 'std::nullopt' result means the Decl did not fail the
130 virtual std::optional
<FailureInfo
>
131 getDeclFailureInfo(const NamedDecl
*Decl
, const SourceManager
&SM
) const = 0;
133 /// Overridden by derived classes, returns information about if and how a
134 /// macro failed the check. A 'std::nullopt' result means the macro did not
136 virtual std::optional
<FailureInfo
>
137 getMacroFailureInfo(const Token
&MacroNameTok
,
138 const SourceManager
&SM
) const = 0;
140 /// Represents customized diagnostic text and how arguments should be applied.
143 /// return DiagInfo{"my %1 very %2 special %3 text",
144 /// [=](DiagnosticBuilder &diag) {
145 /// diag << arg1 << arg2 << arg3;
149 llvm::unique_function
<void(DiagnosticBuilder
&)> ApplyArgs
;
152 /// Overridden by derived classes, returns a description of the diagnostic
153 /// that should be emitted for the given failure. The base class will then
154 /// further customize the diagnostic by adding info about whether the fix-it
155 /// can be automatically applied or not.
156 virtual DiagInfo
getDiagInfo(const NamingCheckId
&ID
,
157 const NamingCheckFailure
&Failure
) const = 0;
160 NamingCheckFailureMap NamingCheckFailures
;
161 const bool AggressiveDependentMemberLookup
;
167 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_RENAMERCLANGTIDYCHECK_H