clang  6.0.0svn
RefactoringActionRulesInternal.h
Go to the documentation of this file.
1 //===--- RefactoringActionRulesInternal.h - Clang refactoring library -----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
11 #define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
12 
13 #include "clang/Basic/LLVM.h"
18 #include "llvm/Support/Error.h"
19 #include <type_traits>
20 
21 namespace clang {
22 namespace tooling {
23 namespace internal {
24 
25 inline llvm::Error findError() { return llvm::Error::success(); }
26 
27 inline void ignoreError() {}
28 
29 template <typename FirstT, typename... RestT>
30 void ignoreError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
31  if (!First)
32  llvm::consumeError(First.takeError());
33  ignoreError(Rest...);
34 }
35 
36 /// Scans the tuple and returns a valid \c Error if any of the values are
37 /// invalid.
38 template <typename FirstT, typename... RestT>
40  if (!First) {
41  ignoreError(Rest...);
42  return First.takeError();
43  }
44  return findError(Rest...);
45 }
46 
47 template <typename RuleType, typename... RequirementTypes, size_t... Is>
50  const std::tuple<RequirementTypes...> &Requirements,
51  llvm::index_sequence<Is...>) {
52  // Check if the requirements we're interested in can be evaluated.
53  auto Values =
54  std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
55  auto Err = findError(std::get<Is>(Values)...);
56  if (Err)
57  return Consumer.handleError(std::move(Err));
58  // Construct the target action rule by extracting the evaluated
59  // requirements from Expected<> wrappers and then run it.
60  auto Rule =
61  RuleType::initiate(Context, std::move((*std::get<Is>(Values)))...);
62  if (!Rule)
63  return Consumer.handleError(Rule.takeError());
64  Rule->invoke(Consumer, Context);
65 }
66 
68 
69 /// Scans the list of requirements in a rule and visits all the refactoring
70 /// options that are used by all the requirements.
71 template <typename FirstT, typename... RestT>
73  const FirstT &First, const RestT &... Rest) {
74  struct OptionGatherer {
75  RefactoringOptionVisitor &Visitor;
76 
77  void operator()(const RefactoringOptionsRequirement &Requirement) {
78  for (const auto &Option : Requirement.getRefactoringOptions())
79  Option->passToVisitor(Visitor);
80  }
81  void operator()(const RefactoringActionRuleRequirement &) {}
82  };
83  (OptionGatherer{Visitor})(First);
84  return visitRefactoringOptionsImpl(Visitor, Rest...);
85 }
86 
87 template <typename... RequirementTypes, size_t... Is>
89  RefactoringOptionVisitor &Visitor,
90  const std::tuple<RequirementTypes...> &Requirements,
91  llvm::index_sequence<Is...>) {
92  visitRefactoringOptionsImpl(Visitor, std::get<Is>(Requirements)...);
93 }
94 
95 /// A type trait that returns true when the given type list has at least one
96 /// type whose base is the given base type.
97 template <typename Base, typename First, typename... Rest>
98 struct HasBaseOf : std::conditional<HasBaseOf<Base, First>::value ||
99  HasBaseOf<Base, Rest...>::value,
100  std::true_type, std::false_type>::type {};
101 
102 template <typename Base, typename T>
103 struct HasBaseOf<Base, T> : std::is_base_of<Base, T> {};
104 
105 /// A type trait that returns true when the given type list contains types that
106 /// derive from Base.
107 template <typename Base, typename First, typename... Rest>
108 struct AreBaseOf : std::conditional<AreBaseOf<Base, First>::value &&
109  AreBaseOf<Base, Rest...>::value,
110  std::true_type, std::false_type>::type {};
111 
112 template <typename Base, typename T>
113 struct AreBaseOf<Base, T> : std::is_base_of<Base, T> {};
114 
115 } // end namespace internal
116 
117 template <typename RuleType, typename... RequirementTypes>
118 std::unique_ptr<RefactoringActionRule>
119 createRefactoringActionRule(const RequirementTypes &... Requirements) {
120  static_assert(std::is_base_of<RefactoringActionRuleBase, RuleType>::value,
121  "Expected a refactoring action rule type");
123  RequirementTypes...>::value,
124  "Expected a list of refactoring action rules");
125 
126  class Rule final : public RefactoringActionRule {
127  public:
128  Rule(std::tuple<RequirementTypes...> Requirements)
129  : Requirements(Requirements) {}
130 
131  void invoke(RefactoringResultConsumer &Consumer,
132  RefactoringRuleContext &Context) override {
133  internal::invokeRuleAfterValidatingRequirements<RuleType>(
134  Consumer, Context, Requirements,
135  llvm::index_sequence_for<RequirementTypes...>());
136  }
137 
138  bool hasSelectionRequirement() override {
140  RequirementTypes...>::value;
141  }
142 
143  void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
145  Visitor, Requirements,
146  llvm::index_sequence_for<RequirementTypes...>());
147  }
148  private:
149  std::tuple<RequirementTypes...> Requirements;
150  };
151 
152  return llvm::make_unique<Rule>(std::make_tuple(Requirements...));
153 }
154 
155 } // end namespace tooling
156 } // end namespace clang
157 
158 #endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULES_INTERNAL_H
A refactoring action rule is a wrapper class around a specific refactoring action rule (SourceChangeR...
An interface that declares functions that handle different refactoring option types.
virtual void handleError(llvm::Error Err)=0
Handles an initation or an invication error.
void invokeRuleAfterValidatingRequirements(RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, const std::tuple< RequirementTypes... > &Requirements, llvm::index_sequence< Is... >)
A refactoring action rule requirement determines when a refactoring action rule can be invoked...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
The refactoring rule context stores all of the inputs that might be needed by a refactoring action ru...
const FunctionProtoType * T
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...
A base class for any requirement that requires some refactoring options.
An abstract interface that consumes the various refactoring results that can be produced by refactori...
A type trait that returns true when the given type list contains types that derive from Base...
Dataflow Directional Tag Classes.
virtual ArrayRef< std::shared_ptr< RefactoringOption > > getRefactoringOptions() const =0
Returns the set of refactoring options that are used when evaluating this requirement.
A base class for any requirement that expects some part of the source to be selected in an editor (or...
void visitRefactoringOptions(RefactoringOptionVisitor &Visitor, const std::tuple< RequirementTypes... > &Requirements, llvm::index_sequence< Is... >)
void visitRefactoringOptionsImpl(RefactoringOptionVisitor &)
A type trait that returns true when the given type list has at least one type whose base is the given...