Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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"
  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. /// Scans the tuple and returns a valid \c Error if any of the values are
  36. /// invalid.
  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.     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.  
  66. inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {}
  67.  
  68. /// Scans the list of requirements in a rule and visits all the refactoring
  69. /// options that are used by all the requirements.
  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.     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.
  96. template <typename Base, typename First, typename... Rest>
  97. struct HasBaseOf : std::conditional_t<HasBaseOf<Base, First>::value ||
  98.                                           HasBaseOf<Base, Rest...>::value,
  99.                                       std::true_type, std::false_type> {};
  100.  
  101. template <typename Base, typename T>
  102. struct 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.
  106. template <typename Base, typename First, typename... Rest>
  107. struct AreBaseOf : std::conditional_t<AreBaseOf<Base, First>::value &&
  108.                                           AreBaseOf<Base, Rest...>::value,
  109.                                       std::true_type, std::false_type> {};
  110.  
  111. template <typename Base, typename T>
  112. struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {};
  113.  
  114. } // end namespace internal
  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.           std::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.           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
  158.