Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:11

0001 //===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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 /// Scans the tuple and returns a valid \c Error if any of the values are
0036 /// invalid.
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   // Check if the requirements we're interested in can be evaluated.
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   // Construct the target action rule by extracting the evaluated
0058   // requirements from Expected<> wrappers and then run it.
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 /// Scans the list of requirements in a rule and visits all the refactoring
0069 /// options that are used by all the requirements.
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 /// A type trait that returns true when the given type list has at least one
0095 /// type whose base is the given base type.
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 /// A type trait that returns true when the given type list contains types that
0105 /// derive from Base.
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 } // end namespace internal
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 } // end namespace tooling
0155 } // end namespace clang
0156 
0157 #endif // LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H