| 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 | |