File indexing completed on 2026-05-10 08:37:11
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
0010 #define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
0011
0012 #include "clang/Basic/LLVM.h"
0013 #include "clang/Tooling/Refactoring/RefactoringActionRule.h"
0014 #include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
0015 #include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
0016 #include "clang/Tooling/Refactoring/RefactoringRuleContext.h"
0017 #include "llvm/Support/Error.h"
0018 #include <type_traits>
0019
0020 namespace clang {
0021 namespace tooling {
0022 namespace internal {
0023
0024 inline llvm::Error findError() { return llvm::Error::success(); }
0025
0026 inline void ignoreError() {}
0027
0028 template <typename FirstT, typename... RestT>
0029 void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
0030 if (!First)
0031 llvm::consumeError(First.takeError());
0032 ignoreError(Rest...);
0033 }
0034
0035
0036
0037 template <typename FirstT, typename... RestT>
0038 llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
0039 if (!First) {
0040 ignoreError(Rest...);
0041 return First.takeError();
0042 }
0043 return findError(Rest...);
0044 }
0045
0046 template <typename RuleType, typename... RequirementTypes, size_t... Is>
0047 void invokeRuleAfterValidatingRequirements(
0048 RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context,
0049 const std::tuple<RequirementTypes...> &Requirements,
0050 std::index_sequence<Is...>) {
0051
0052 auto Values =
0053 std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
0054 auto Err = findError(std::get<Is>(Values)...);
0055 if (Err)
0056 return Consumer.handleError(std::move(Err));
0057
0058
0059 auto Rule =
0060 RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...);
0061 if (!Rule)
0062 return Consumer.handleError(Rule.takeError());
0063 Rule->invoke(Consumer, Context);
0064 }
0065
0066 inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {}
0067
0068
0069
0070 template <typename FirstT, typename... RestT>
0071 void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor,
0072 const FirstT &First, const RestT &... Rest) {
0073 struct OptionGatherer {
0074 RefactoringOptionVisitor &Visitor;
0075
0076 void operator()(const RefactoringOptionsRequirement &Requirement) {
0077 for (const auto &Option : Requirement.getRefactoringOptions())
0078 Option->passToVisitor(Visitor);
0079 }
0080 void operator()(const RefactoringActionRuleRequirement &) {}
0081 };
0082 (OptionGatherer{Visitor})(First);
0083 return visitRefactoringOptionsImpl(Visitor, Rest...);
0084 }
0085
0086 template <typename... RequirementTypes, size_t... Is>
0087 void visitRefactoringOptions(
0088 RefactoringOptionVisitor &Visitor,
0089 const std::tuple<RequirementTypes...> &Requirements,
0090 std::index_sequence<Is...>) {
0091 visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...);
0092 }
0093
0094
0095
0096 template <typename Base, typename First, typename... Rest>
0097 struct HasBaseOf : std::conditional_t<HasBaseOf<Base, First>::value ||
0098 HasBaseOf<Base, Rest...>::value,
0099 std::true_type, std::false_type> {};
0100
0101 template <typename Base, typename T>
0102 struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {};
0103
0104
0105
0106 template <typename Base, typename First, typename... Rest>
0107 struct AreBaseOf : std::conditional_t<AreBaseOf<Base, First>::value &&
0108 AreBaseOf<Base, Rest...>::value,
0109 std::true_type, std::false_type> {};
0110
0111 template <typename Base, typename T>
0112 struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {};
0113
0114 }
0115
0116 template <typename RuleType, typename... RequirementTypes>
0117 std::unique_ptr<RefactoringActionRule>
0118 createRefactoringActionRule(const RequirementTypes &... Requirements) {
0119 static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value,
0120 "Expected a refactoring action rule type");
0121 static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement,
0122 RequirementTypes...>::value,
0123 "Expected a list of refactoring action rules");
0124
0125 class Rule final : public RefactoringActionRule {
0126 public:
0127 Rule(std::tuple<RequirementTypes...> Requirements)
0128 : Requirements(Requirements) {}
0129
0130 void invoke(RefactoringResultConsumer &Consumer,
0131 RefactoringRuleContext &Context) override {
0132 internal::invokeRuleAfterValidatingRequirements<RuleType>(
0133 Consumer, Context, Requirements,
0134 std::index_sequence_for<RequirementTypes...>());
0135 }
0136
0137 bool hasSelectionRequirement() override {
0138 return internal::HasBaseOf<SourceSelectionRequirement,
0139 RequirementTypes...>::value;
0140 }
0141
0142 void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
0143 internal::visitRefactoringOptions(
0144 Visitor, Requirements,
0145 std::index_sequence_for<RequirementTypes...>());
0146 }
0147 private:
0148 std::tuple<RequirementTypes...> Requirements;
0149 };
0150
0151 return std::make_unique<Rule>(std::make_tuple(Requirements...));
0152 }
0153
0154 }
0155 }
0156
0157 #endif