From 1e416fe23df4750fe79c717357c427b2ecb09cf0 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Wed, 1 Nov 2017 00:20:55 +0000 Subject: [PATCH] [refactor][extract] prohibit extraction of ObjC property setters llvm-svn: 317056 --- .../clang/Basic/DiagnosticRefactoringKinds.td | 2 ++ clang/lib/Tooling/Refactoring/Extract.cpp | 19 +++++++--- clang/test/Refactor/Extract/ObjCProperty.m | 41 ++++++++++++++++++++++ 3 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 clang/test/Refactor/Extract/ObjCProperty.m diff --git a/clang/include/clang/Basic/DiagnosticRefactoringKinds.td b/clang/include/clang/Basic/DiagnosticRefactoringKinds.td index b54b930..ee396b9 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 b1000b6..e81bb3f 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(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(Code[0]))) + return Context.createDiagnosticError( + diag::err_refactor_extract_simple_expression); + + // Property setters can't be extracted. + if (const auto *PRE = dyn_cast(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 0000000..152ccb3 --- /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 -- 2.7.4