clang  19.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_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
10 #define LLVM_CLANG_TOOLING_REFACTORING_REFACTORINGACTIONRULESINTERNAL_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_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");
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_REFACTORING_REFACTORINGACTIONRULESINTERNAL_H
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
A refactoring action rule requirement determines when a refactoring action rule can be invoked.
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.
A base class for any requirement that requires some refactoring options.
virtual ArrayRef< std::shared_ptr< RefactoringOption > > getRefactoringOptions() const =0
Returns the set of refactoring options that are used when evaluating this requirement.
An abstract interface that consumes the various refactoring results that can be produced by refactori...
virtual void handleError(llvm::Error Err)=0
Handles an initiation or an invication error.
The refactoring rule context stores all of the inputs that might be needed by a refactoring action ru...
A base class for any requirement that expects some part of the source to be selected in an editor (or...
void invokeRuleAfterValidatingRequirements(RefactoringResultConsumer &Consumer, RefactoringRuleContext &Context, const std::tuple< RequirementTypes... > &Requirements, std::index_sequence< Is... >)
void visitRefactoringOptions(RefactoringOptionVisitor &Visitor, const std::tuple< RequirementTypes... > &Requirements, std::index_sequence< Is... >)
void visitRefactoringOptionsImpl(RefactoringOptionVisitor &)
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...
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
A type trait that returns true when the given type list contains types that derive from Base.
A type trait that returns true when the given type list has at least one type whose base is the given...