arphaman updated this revision to Diff 113222.
arphaman added a comment.
Fixed a comment
Repository:
rL LLVM
https://reviews.llvm.org/D37291
Files:
include/clang/Tooling/Refactoring/RefactoringActionRule.h
include/clang/Tooling/Refactoring/RefactoringActionRules.h
include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
unittests/Tooling/RefactoringActionRulesTest.cpp
Index: unittests/Tooling/RefactoringActionRulesTest.cpp
===================================================================
--- unittests/Tooling/RefactoringActionRulesTest.cpp
+++ unittests/Tooling/RefactoringActionRulesTest.cpp
@@ -35,8 +35,27 @@
Expected<Optional<AtomicChanges>>
createReplacements(const std::unique_ptr<RefactoringActionRule> &Rule,
RefactoringRuleContext &Context) {
- return cast<SourceChangeRefactoringRule>(*Rule).createSourceReplacements(
- Context);
+ class Consumer final : public RefactoringResultConsumer {
+ void handleInitiationFailure() {
+ Result = Expected<Optional<AtomicChanges>>(None);
+ }
+ void handleInitiationError(llvm::Error Err) { Result = std::move(Err); }
+
+ void handleInvocationError(llvm::Error Err) {
+ handleInitiationError(std::move(Err));
+ }
+
+ void handle(AtomicChanges SourceReplacements) {
+ Result = std::move(SourceReplacements);
+ }
+
+ public:
+ Optional<Expected<Optional<AtomicChanges>>> Result;
+ };
+
+ Consumer C;
+ Rule->invoke(C, Context);
+ return std::move(*C.Result);
}
TEST_F(RefactoringActionRulesTest, MyFirstRefactoringRule) {
Index: include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
===================================================================
--- /dev/null
+++ include/clang/Tooling/Refactoring/RefactoringResultConsumer.h
@@ -0,0 +1,68 @@
+//===--- RefactoringResultConsumer.h - Clang refactoring library ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
+#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
+
+#include "clang/Basic/LLVM.h"
+#include "clang/Tooling/Refactoring/AtomicChange.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace tooling {
+
+/// An abstract interface that consumes the various refactoring results that can
+/// be produced by refactoring actions.
+///
+/// A valid refactoring result must be handled by a \c handle method.
+class RefactoringResultConsumer {
+public:
+ virtual ~RefactoringResultConsumer() {}
+
+ /// Handles an initiation failure. An action typically fails to initiate when
+ /// the source selection has no overlap at all with any relevant AST nodes.
+ virtual void handleInitiationFailure() = 0;
+
+ /// Handles an initation error. The error typically has a \c DiagnosticError
+ /// payload that describes why initation failed.
+ virtual void handleInitiationError(llvm::Error Err) = 0;
+
+ virtual void handleInvocationError(llvm::Error Err) = 0;
+
+ /// Handles the source replacements that are produced by a refactoring action.
+ virtual void handle(AtomicChanges SourceReplacements) = 0;
+};
+
+namespace traits {
+namespace internal {
+
+template <typename T> struct HasHandle {
+private:
+ template <typename ClassT>
+ static auto check(ClassT *) -> typename std::is_same<
+ decltype(std::declval<ClassT>().handle(std::declval<T>())), void>::type;
+
+ template <typename> static std::false_type check(...);
+
+public:
+ using Type = decltype(check<RefactoringResultConsumer>(nullptr));
+};
+
+} // end namespace internal
+
+/// A type trait that returns true iff the given type is a valid refactoring
+/// result.
+template <typename T>
+struct IsValidRefactoringResult : internal::HasHandle<T>::Type {};
+
+} // end namespace traits
+} // end namespace tooling
+} // end namespace clang
+
+#endif // LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_RESULT_CONSUMER_H
Index: include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
===================================================================
--- include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
+++ include/clang/Tooling/Refactoring/RefactoringActionRulesInternal.h
@@ -13,6 +13,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Tooling/Refactoring/RefactoringActionRule.h"
#include "clang/Tooling/Refactoring/RefactoringActionRuleRequirements.h"
+#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h"
#include "clang/Tooling/Refactoring/RefactoringRuleContext.h"
#include "llvm/Support/Error.h"
#include <type_traits>
@@ -22,39 +23,20 @@
namespace refactoring_action_rules {
namespace internal {
-/// A wrapper around a specific refactoring action rule that calls a generic
-/// 'perform' method from the specific refactoring method.
-template <typename T> struct SpecificRefactoringRuleAdapter {};
-
-template <>
-class SpecificRefactoringRuleAdapter<AtomicChanges>
- : public SourceChangeRefactoringRule {
-public:
- virtual Expected<Optional<AtomicChanges>>
- perform(RefactoringRuleContext &Context) = 0;
-
- Expected<Optional<AtomicChanges>>
- createSourceReplacements(RefactoringRuleContext &Context) final override {
- return perform(Context);
- }
-};
-
/// A specialized refactoring action rule that calls the stored function once
/// all the of the requirements are fullfilled. The values produced during the
/// evaluation of requirements are passed to the stored function.
-template <typename ResultType, typename FunctionType,
- typename... RequirementTypes>
-class PlainFunctionRule final
- : public SpecificRefactoringRuleAdapter<ResultType> {
+template <typename FunctionType, typename... RequirementTypes>
+class PlainFunctionRule final : public RefactoringActionRule {
public:
PlainFunctionRule(FunctionType Function,
std::tuple<RequirementTypes...> &&Requirements)
: Function(Function), Requirements(std::move(Requirements)) {}
- Expected<Optional<ResultType>>
- perform(RefactoringRuleContext &Context) override {
- return performImpl(Context,
- llvm::index_sequence_for<RequirementTypes...>());
+ void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) override {
+ return invokeImpl(Consumer, Context,
+ llvm::index_sequence_for<RequirementTypes...>());
}
private:
@@ -95,22 +77,26 @@
}
template <size_t... Is>
- Expected<Optional<ResultType>> performImpl(RefactoringRuleContext &Context,
- llvm::index_sequence<Is...>) {
+ void invokeImpl(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context,
+ llvm::index_sequence<Is...>) {
// Initiate the operation.
auto Values =
std::make_tuple(std::get<Is>(Requirements).evaluate(Context)...);
Optional<llvm::Error> InitiationFailure =
findErrorNone(std::get<Is>(Values)...);
if (InitiationFailure) {
llvm::Error Error = std::move(*InitiationFailure);
if (!Error)
- return None;
- return std::move(Error);
+ return Consumer.handleInitiationFailure();
+ return Consumer.handleInitiationError(std::move(Error));
}
// Perform the operation.
- return Function(
- unwrapRequirementResult(std::move(std::get<Is>(Values)))...);
+ auto Result =
+ Function(unwrapRequirementResult(std::move(std::get<Is>(Values)))...);
+ if (!Result)
+ return Consumer.handleInvocationError(Result.takeError());
+ Consumer.handle(*Result);
}
FunctionType Function;
Index: include/clang/Tooling/Refactoring/RefactoringActionRules.h
===================================================================
--- include/clang/Tooling/Refactoring/RefactoringActionRules.h
+++ include/clang/Tooling/Refactoring/RefactoringActionRules.h
@@ -42,15 +42,12 @@
createRefactoringRule(Expected<ResultType> (*RefactoringFunction)(
typename RequirementTypes::OutputType...),
const RequirementTypes &... Requirements) {
- static_assert(
- std::is_base_of<
- RefactoringActionRule,
- internal::SpecificRefactoringRuleAdapter<ResultType>>::value,
- "invalid refactoring result type");
+ static_assert(tooling::traits::IsValidRefactoringResult<ResultType>::value,
+ "invalid refactoring result type");
static_assert(traits::IsRequirement<RequirementTypes...>::value,
"invalid refactoring action rule requirement");
return llvm::make_unique<internal::PlainFunctionRule<
- ResultType, decltype(RefactoringFunction), RequirementTypes...>>(
+ decltype(RefactoringFunction), RequirementTypes...>>(
RefactoringFunction, std::make_tuple(Requirements...));
}
Index: include/clang/Tooling/Refactoring/RefactoringActionRule.h
===================================================================
--- include/clang/Tooling/Refactoring/RefactoringActionRule.h
+++ include/clang/Tooling/Refactoring/RefactoringActionRule.h
@@ -11,52 +11,25 @@
#define LLVM_CLANG_TOOLING_REFACTOR_REFACTORING_ACTION_RULE_H
#include "clang/Basic/LLVM.h"
-#include "clang/Tooling/Refactoring/AtomicChange.h"
-#include "llvm/Support/Error.h"
#include <vector>
namespace clang {
namespace tooling {
+class RefactoringResultConsumer;
class RefactoringRuleContext;
/// A common refactoring action rule interface.
class RefactoringActionRule {
public:
- enum RuleKind { SourceChangeRefactoringRuleKind };
-
- RuleKind getRuleKind() const { return Kind; }
-
virtual ~RefactoringActionRule() {}
-protected:
- RefactoringActionRule(RuleKind Kind) : Kind(Kind) {}
-
-private:
- RuleKind Kind;
-};
-
-/// A type of refactoring action rule that produces source replacements in the
-/// form of atomic changes.
-///
-/// This action rule is typically used for local refactorings that replace
-/// source in a single AST unit.
-class SourceChangeRefactoringRule : public RefactoringActionRule {
-public:
- SourceChangeRefactoringRule()
- : RefactoringActionRule(SourceChangeRefactoringRuleKind) {}
-
- /// Initiates and performs a refactoring action that modifies the sources.
+ /// Initiates and performs a specific refactoring action.
///
- /// The specific rule must return an llvm::Error with a DiagnosticError
- /// payload or None when the refactoring action couldn't be initiated/
- /// performed, or \c AtomicChanges when the action was performed successfully.
- virtual Expected<Optional<AtomicChanges>>
- createSourceReplacements(RefactoringRuleContext &Context) = 0;
-
- static bool classof(const RefactoringActionRule *Rule) {
- return Rule->getRuleKind() == SourceChangeRefactoringRuleKind;
- }
+ /// The specific rule will invoke an appropriate \c handle method on a
+ /// consumer to propagate the result of the refactoring action.
+ virtual void invoke(RefactoringResultConsumer &Consumer,
+ RefactoringRuleContext &Context) = 0;
};
/// A set of refactoring action rules that should have unique initiation
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits