clang  14.0.0git
RefactoringActionRulesInternal.h
Go to the documentation of this file.
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_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
10 #define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
11 
12 #include "clang/Basic/LLVM.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>
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 
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>
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>
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<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 /// 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<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 } // 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");
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 {
139  RequirementTypes...>::value;
140  }
141 
142  void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
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_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
clang::tooling::RefactoringResultConsumer::handleError
virtual void handleError(llvm::Error Err)=0
Handles an initiation or an invication error.
type
RefactoringResultConsumer.h
RefactoringActionRule.h
clang::tooling::RefactoringActionRule
A refactoring action rule is a wrapper class around a specific refactoring action rule (SourceChangeR...
Definition: RefactoringActionRule.h:54
clang::tooling::RefactoringActionRuleRequirement
A refactoring action rule requirement determines when a refactoring action rule can be invoked.
Definition: RefactoringActionRuleRequirements.h:36
clang::ComparisonCategoryType::First
@ First
llvm::Expected
Definition: LLVM.h:41
clang::tooling::SourceSelectionRequirement
A base class for any requirement that expects some part of the source to be selected in an editor (or...
Definition: RefactoringActionRuleRequirements.h:42
clang::tooling::RefactoringOptionsRequirement
A base class for any requirement that requires some refactoring options.
Definition: RefactoringActionRuleRequirements.h:81
clang::tooling::internal::AreBaseOf
A type trait that returns true when the given type list contains types that derive from Base.
Definition: RefactoringActionRulesInternal.h:107
clang::tooling::internal::visitRefactoringOptions
void visitRefactoringOptions(RefactoringOptionVisitor &Visitor, const std::tuple< RequirementTypes... > &Requirements, std::index_sequence< Is... >)
Definition: RefactoringActionRulesInternal.h:87
clang::tooling::internal::visitRefactoringOptionsImpl
void visitRefactoringOptionsImpl(RefactoringOptionVisitor &)
Definition: RefactoringActionRulesInternal.h:66
clang::tooling::internal::invokeRuleAfterValidatingRequirements
void invokeRuleAfterValidatingRequirements(RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, const std::tuple< RequirementTypes... > &Requirements, std::index_sequence< Is... >)
Definition: RefactoringActionRulesInternal.h:47
clang::tooling::RefactoringRuleContext
The refactoring rule context stores all of the inputs that might be needed by a refactoring action ru...
Definition: RefactoringRuleContext.h:33
clang::tooling::createRefactoringActionRule
std::unique_ptr< RefactoringActionRule > createRefactoringActionRule(const RequirementTypes &... Requirements)
Creates a new refactoring action rule that constructs and invokes the RuleType rule when all of the r...
Definition: RefactoringActionRulesInternal.h:118
Base
clang::tooling::internal::ignoreError
void ignoreError()
Definition: RefactoringActionRulesInternal.h:26
RefactoringActionRuleRequirements.h
clang::tooling::internal::HasBaseOf
A type trait that returns true when the given type list has at least one type whose base is the given...
Definition: RefactoringActionRulesInternal.h:97
clang::tooling::internal::findError
llvm::Error findError()
Definition: RefactoringActionRulesInternal.h:24
LLVM.h
clang::tooling::RefactoringResultConsumer
An abstract interface that consumes the various refactoring results that can be produced by refactori...
Definition: RefactoringResultConsumer.h:24
RefactoringRuleContext.h
clang
Definition: CalledOnceCheck.h:17
clang::tooling::RefactoringOptionVisitor
An interface that declares functions that handle different refactoring option types.
Definition: RefactoringOptionVisitor.h:25
clang::tooling::RefactoringOptionsRequirement::getRefactoringOptions
virtual ArrayRef< std::shared_ptr< RefactoringOption > > getRefactoringOptions() const =0
Returns the set of refactoring options that are used when evaluating this requirement.