Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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