summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticRefactoringKinds.td2
-rw-r--r--clang/lib/Tooling/Refactoring/Extract.cpp19
-rw-r--r--clang/test/Refactor/Extract/ObjCProperty.m41
3 files changed, 57 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/DiagnosticRefactoringKinds.td b/clang/include/clang/Basic/DiagnosticRefactoringKinds.td
index b54b9301a7c..ee396b93072 100644
--- a/clang/include/clang/Basic/DiagnosticRefactoringKinds.td
+++ b/clang/include/clang/Basic/DiagnosticRefactoringKinds.td
@@ -26,6 +26,8 @@ def err_refactor_code_outside_of_function : Error<"the selected code is not a "
"part of a function's / method's body">;
def err_refactor_extract_simple_expression : Error<"the selected expression "
"is too simple to extract">;
+def err_refactor_extract_prohibited_expression : Error<"the selected "
+ "expression can't be extracted">;
}
diff --git a/clang/lib/Tooling/Refactoring/Extract.cpp b/clang/lib/Tooling/Refactoring/Extract.cpp
index b1000b60ee0..e81bb3ffe9b 100644
--- a/clang/lib/Tooling/Refactoring/Extract.cpp
+++ b/clang/lib/Tooling/Refactoring/Extract.cpp
@@ -16,6 +16,7 @@
#include "clang/Tooling/Refactoring/Extract/Extract.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
#include "clang/Rewrite/Core/Rewriter.h"
namespace clang {
@@ -70,12 +71,20 @@ ExtractFunction::initiate(RefactoringRuleContext &Context,
return Context.createDiagnosticError(
diag::err_refactor_code_outside_of_function);
- // Avoid extraction of simple literals and references.
- if (Code.size() == 1 && isSimpleExpression(dyn_cast<Expr>(Code[0])))
- return Context.createDiagnosticError(
- diag::err_refactor_extract_simple_expression);
+ if (Code.size() == 1) {
+ // Avoid extraction of simple literals and references.
+ if (isSimpleExpression(dyn_cast<Expr>(Code[0])))
+ return Context.createDiagnosticError(
+ diag::err_refactor_extract_simple_expression);
+
+ // Property setters can't be extracted.
+ if (const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(Code[0])) {
+ if (!PRE->isMessagingGetter())
+ return Context.createDiagnosticError(
+ diag::err_refactor_extract_prohibited_expression);
+ }
+ }
- // FIXME (Alex L): Prohibit extraction of Objective-C property setters.
return ExtractFunction(std::move(Code), DeclName);
}
diff --git a/clang/test/Refactor/Extract/ObjCProperty.m b/clang/test/Refactor/Extract/ObjCProperty.m
new file mode 100644
index 00000000000..152ccb34842
--- /dev/null
+++ b/clang/test/Refactor/Extract/ObjCProperty.m
@@ -0,0 +1,41 @@
+// RUN: clang-refactor extract -selection=test:%s %s -- 2>&1 | grep -v CHECK | FileCheck %s
+
+@interface HasProperty
+
+@property (strong) HasProperty *item;
+
+- (HasProperty *)implicitProp;
+
+- (void)setImplicitSetter:(HasProperty *)value;
+
+@end
+
+@implementation HasProperty
+
+- (void)allowGetterExtraction {
+ /*range allow_getter=->+0:42*/self.item;
+ /*range allow_imp_getter=->+0:54*/self.implicitProp;
+}
+// CHECK: 1 'allow_getter' results:
+// CHECK: extracted() {
+// CHECK-NEXT: return self.item;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: - (void)allowGetterExtraction {
+// CHECK-NEXT: extracted();
+
+// CHECK: 1 'allow_imp_getter' results:
+// CHECK: extracted() {
+// CHECK-NEXT: return self.implicitProp;{{$}}
+// CHECK-NEXT: }{{[[:space:]].*}}
+// CHECK-NEXT: - (void)allowGetterExtraction {
+// CHECK-NEXT: self.item;
+// CHECK-NEXT: extracted();
+
+- (void)prohibitSetterExtraction {
+ /*range prohibit_setter=->+0:45*/self.item = 0;
+ /*range prohibit_setter=->+0:55*/self.implicitSetter = 0;
+}
+// CHECK: 2 'prohibit_setter' results:
+// CHECK: the selected expression can't be extracted
+
+@end
OpenPOWER on IntegriCloud