clang 20.0.0git
RefactoringActionRulesInternal.h
Go to the documentation of this file.
1//===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===//
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_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
10#define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
11
12#include "clang/Basic/LLVM.h"
17#include "llvm/Support/Error.h"
18#include <type_traits>
19
20namespace clang {
21namespace tooling {
22namespace internal {
23
24inline llvm::Error findError() { return llvm::Error::success(); }
25
26inline void ignoreError() {}
27
28template <typename FirstT, typename... RestT>
30 if (!First)
31 llvm::consumeError(First.takeError());
32 ignoreError(Rest...);
33}
34
35/// Scans the tuple and returns a valid \c Error if any of the values are
36/// invalid.
37template <typename FirstT, typename... RestT>
39 if (!First) {
40 ignoreError(Rest...);
41 return First.takeError();
42 }
43 return findError(Rest...);
44}
45
46template <typename RuleType, typename... RequirementTypes, size_t... Is>
49 const std::tuple<RequirementTypes...> &Requirements,
50 std::index_sequence<Is...>) {
51 // Check if the requirements we're interested in can be evaluated.
52 auto Values =
53 std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
54 auto Err = findError(std::get<Is>(Values)...);
55 if (Err)
56 return Consumer.handleError(std::move(Err));
57 // Construct the target action rule by extracting the evaluated
58 // requirements from Expected<> wrappers and then run it.
59 auto Rule =
60 RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...);
61 if (!Rule)
62 return Consumer.handleError(Rule.takeError());
63 Rule->invoke(Consumer, Context);
64}
65
67
68/// Scans the list of requirements in a rule and visits all the refactoring
69/// options that are used by all the requirements.
70template <typename FirstT, typename... RestT>
72 const FirstT &First, const RestT &... Rest) {
73 struct OptionGatherer {
75
76 void operator()(const RefactoringOptionsRequirement &Requirement) {
77 for (const auto &Option : Requirement.getRefactoringOptions())
78 Option->passToVisitor(Visitor);
79 }
80 void operator()(const RefactoringActionRuleRequirement &) {}
81 };
82 (OptionGatherer{Visitor})(First);
83 return visitRefactoringOptionsImpl(Visitor, Rest...);
84}
85
86template <typename... RequirementTypes, size_t... Is>
89 const std::tuple<RequirementTypes...> &Requirements,
90 std::index_sequence<Is...>) {
91 visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...);
92}
93
94/// A type trait that returns true when the given type list has at least one
95/// type whose base is the given base type.
96template <typename Base, typename First, typename... Rest>
97struct HasBaseOf : std::conditional_t<HasBaseOf<Base, First>::value ||
98 HasBaseOf<Base, Rest...>::value,
99 std::true_type, std::false_type> {};
100
101template <typename Base, typename T>
102struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {};
103
104/// A type trait that returns true when the given type list contains types that
105/// derive from Base.
106template <typename Base, typename First, typename... Rest>
107struct AreBaseOf : std::conditional_t<AreBaseOf<Base, First>::value &&
108 AreBaseOf<Base, Rest...>::value,
109 std::true_type, std::false_type> {};
110
111template <typename Base, typename T>
112struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {};
113
114} // end namespace internal
115
116template <typename RuleType, typename... RequirementTypes>
117std::unique_ptr<RefactoringActionRule>
118createRefactoringActionRule(const RequirementTypes &... Requirements) {
119 static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value,
120 "Expected a refactoring action rule type");
122 RequirementTypes...>::value,
123 "Expected a list of refactoring action rules");
124
125 class Rule final : public RefactoringActionRule {
126 public:
127 Rule(std::tuple<RequirementTypes...> Requirements)
128 : Requirements(Requirements) {}
129
130 void invoke(RefactoringResultConsumer &Consumer,
131 RefactoringRuleContext &Context) override {
132 internal::invokeRuleAfterValidatingRequirements<RuleType>(
133 Consumer, Context, Requirements,
134 std::index_sequence_for<RequirementTypes...>());
135 }
136
137 bool hasSelectionRequirement() override {
139 RequirementTypes...>::value;
140 }
141
142 void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
143 internal::visitRefactoringOptions(
144 Visitor, Requirements,
145 std::index_sequence_for<RequirementTypes...>());
146 }
147 private:
148 std::tuple<RequirementTypes...> Requirements;
149 };
150
151 return std::make_unique<Rule>(std::make_tuple(Requirements...));
152}
153
154} // end namespace tooling
155} // end namespace clang
156
157#endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
A refactoring action rule requirement determines when a refactoring action rule can be invoked.
A refactoring action rule is a wrapper class around a specific refactoring action rule (SourceChangeR...
An interface that declares functions that handle different refactoring option types.
A base class for any requirement that requires some refactoring options.
virtual ArrayRef< std::shared_ptr< RefactoringOption > > getRefactoringOptions() const =0
Returns the set of refactoring options that are used when evaluating this requirement.
An abstract interface that consumes the various refactoring results that can be produced by refactori...
virtual void handleError(llvm::Error Err)=0
Handles an initiation or an invication error.
The refactoring rule context stores all of the inputs that might be needed by a refactoring action ru...
A base class for any requirement that expects some part of the source to be selected in an editor (or...
void invokeRuleAfterValidatingRequirements(RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, const std::tuple< RequirementTypes... > &Requirements, std::index_sequence< Is... >)
void visitRefactoringOptions(RefactoringOptionVisitor &Visitor, const std::tuple< RequirementTypes... > &Requirements, std::index_sequence< Is... >)
void visitRefactoringOptionsImpl(RefactoringOptionVisitor &)
std::unique_ptr< RefactoringActionRule > createRefactoringActionRule(const RequirementTypes &... Requirements)
Creates a new refactoring action rule that constructs and invokes the RuleType rule when all of the r...
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
A type trait that returns true when the given type list contains types that derive from Base.
A type trait that returns true when the given type list has at least one type whose base is the given...