1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H |
10 | #define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H |
11 | |
12 | #include "clang/Basic/LLVM.h" |
13 | #include "clang/Tooling/Refactoring/RefactoringActionRule.h" |
14 | #include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h" |
15 | #include "clang/Tooling/Refactoring/RefactoringResultConsumer.h" |
16 | #include "clang/Tooling/Refactoring/RefactoringRuleContext.h" |
17 | #include "llvm/Support/Error.h" |
18 | #include <type_traits> |
19 | |
20 | namespace clang { |
21 | namespace tooling { |
22 | namespace internal { |
23 | |
24 | inline llvm::Error findError() { return llvm::Error::success(); } |
25 | |
26 | inline void ignoreError() {} |
27 | |
28 | template <typename FirstT, typename... RestT> |
29 | void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) { |
30 | if (!First) |
31 | llvm::consumeError(First.takeError()); |
32 | ignoreError(Rest...); |
33 | } |
34 | |
35 | |
36 | |
37 | template <typename FirstT, typename... RestT> |
38 | llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) { |
39 | if (!First) { |
40 | ignoreError(Rest...); |
41 | return First.takeError(); |
42 | } |
43 | return findError(Rest...); |
44 | } |
45 | |
46 | template <typename RuleType, typename... RequirementTypes, size_t... Is> |
47 | void invokeRuleAfterValidatingRequirements( |
48 | RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, |
49 | const std::tuple<RequirementTypes...> &Requirements, |
50 | llvm::index_sequence<Is...>) { |
51 | |
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 | |
58 | |
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 | |
66 | inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {} |
67 | |
68 | |
69 | |
70 | template <typename FirstT, typename... RestT> |
71 | void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor, |
72 | const FirstT &First, const RestT &... Rest) { |
73 | struct OptionGatherer { |
74 | RefactoringOptionVisitor &Visitor; |
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 | |
86 | template <typename... RequirementTypes, size_t... Is> |
87 | void visitRefactoringOptions( |
88 | RefactoringOptionVisitor &Visitor, |
89 | const std::tuple<RequirementTypes...> &Requirements, |
90 | llvm::index_sequence<Is...>) { |
91 | visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...); |
92 | } |
93 | |
94 | |
95 | |
96 | template <typename Base, typename First, typename... Rest> |
97 | struct HasBaseOf : std::conditional<HasBaseOf<Base, First>::value || |
98 | HasBaseOf<Base, Rest...>::value, |
99 | std::true_type, std::false_type>::type {}; |
100 | |
101 | template <typename Base, typename T> |
102 | struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {}; |
103 | |
104 | |
105 | |
106 | template <typename Base, typename First, typename... Rest> |
107 | struct AreBaseOf : std::conditional<AreBaseOf<Base, First>::value && |
108 | AreBaseOf<Base, Rest...>::value, |
109 | std::true_type, std::false_type>::type {}; |
110 | |
111 | template <typename Base, typename T> |
112 | struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {}; |
113 | |
114 | } |
115 | |
116 | template <typename RuleType, typename... RequirementTypes> |
117 | std::unique_ptr<RefactoringActionRule> |
118 | createRefactoringActionRule(const RequirementTypes &... Requirements) { |
119 | static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value, |
120 | "Expected a refactoring action rule type"); |
121 | static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement, |
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 | llvm::index_sequence_for<RequirementTypes...>()); |
135 | } |
136 | |
137 | bool hasSelectionRequirement() override { |
138 | return internal::HasBaseOf<SourceSelectionRequirement, |
139 | RequirementTypes...>::value; |
140 | } |
141 | |
142 | void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override { |
143 | internal::visitRefactoringOptions( |
144 | Visitor, Requirements, |
145 | llvm::index_sequence_for<RequirementTypes...>()); |
146 | } |
147 | private: |
148 | std::tuple<RequirementTypes...> Requirements; |
149 | }; |
150 | |
151 | return llvm::make_unique<Rule>(std::make_tuple(Requirements...)); |
152 | } |
153 | |
154 | } |
155 | } |
156 | |
157 | #endif |
158 | |