]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
Merge clang trunk r321017 to contrib/llvm/tools/clang.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Tooling / Refactoring / RefactoringActionRulesInternal.h
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"
14 #include "clang/Tooling/Refactoring/RefactoringActionRule.h"
15 #include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
16 #include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
17 #include "clang/Tooling/Refactoring/RefactoringRuleContext.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>
39 llvm::Error findError(Expected<FirstT> &First, Expected<RestT> &... Rest) {
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>
48 void invokeRuleAfterValidatingRequirements(
49     RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context,
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
67 inline void visitRefactoringOptionsImpl(RefactoringOptionVisitor &) {}
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>
72 void visitRefactoringOptionsImpl(RefactoringOptionVisitor &Visitor,
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>
88 void visitRefactoringOptions(
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");
122   static_assert(internal::AreBaseOf<RefactoringActionRuleRequirement,
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 {
139       return internal::HasBaseOf<SourceSelectionRequirement,
140                                  RequirementTypes...>::value;
141     }
142
143     void visitRefactoringOptions(RefactoringOptionVisitor &Visitor) override {
144       internal::visitRefactoringOptions(
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