ObjectiveC migration: Handle another special case of

setter/getter methods which can be migrated to
a @property.

llvm-svn: 188005
This commit is contained in:
Fariborz Jahanian 2013-08-08 20:51:58 +00:00
parent b88cdf62f5
commit cf2ff9ba32
3 changed files with 85 additions and 18 deletions

View File

@ -206,20 +206,31 @@ void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
BodyMigrator(*this).TraverseDecl(D);
}
static void append_attr(std::string &PropertyString, const char *attr,
bool GetterHasIsPrefix) {
PropertyString += (GetterHasIsPrefix ? ", " : "(");
PropertyString += attr;
PropertyString += ')';
}
static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
const ObjCMethodDecl *Setter,
const NSAPI &NS, edit::Commit &commit) {
const NSAPI &NS, edit::Commit &commit,
bool GetterHasIsPrefix) {
ASTContext &Context = NS.getASTContext();
std::string PropertyString = "@property";
std::string PropertyNameString = Getter->getNameAsString();
StringRef PropertyName(PropertyNameString);
if (GetterHasIsPrefix) {
PropertyString += "(getter=";
PropertyString += PropertyNameString;
}
// Short circuit properties that contain the name "delegate" or "dataSource",
// or have exact name "target" to have unsafe_unretained attribute.
if (PropertyName.equals("target") ||
(PropertyName.find("delegate") != StringRef::npos) ||
(PropertyName.find("dataSource") != StringRef::npos))
PropertyString += "(unsafe_unretained)";
append_attr(PropertyString, "unsafe_unretained", GetterHasIsPrefix);
else {
const ParmVarDecl *argDecl = *Setter->param_begin();
QualType ArgType = Context.getCanonicalType(argDecl->getType());
@ -231,29 +242,46 @@ static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
if (IDecl &&
IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
PropertyString += "(copy)";
append_attr(PropertyString, "copy", GetterHasIsPrefix);
else
PropertyString += "(retain)";
}
append_attr(PropertyString, "retain", GetterHasIsPrefix);
} else if (GetterHasIsPrefix)
PropertyString += ')';
} else if (propertyLifetime == Qualifiers::OCL_Weak)
// TODO. More precise determination of 'weak' attribute requires
// looking into setter's implementation for backing weak ivar.
PropertyString += "(weak)";
append_attr(PropertyString, "weak", GetterHasIsPrefix);
else if (RetainableObject)
PropertyString += "(retain)";
append_attr(PropertyString, "retain", GetterHasIsPrefix);
else if (GetterHasIsPrefix)
PropertyString += ')';
}
// strip off any ARC lifetime qualifier.
QualType CanResultTy = Context.getCanonicalType(Getter->getResultType());
if (CanResultTy.getQualifiers().hasObjCLifetime()) {
Qualifiers Qs = CanResultTy.getQualifiers();
Qs.removeObjCLifetime();
CanResultTy = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
QualType RT = Getter->getResultType();
if (!isa<TypedefType>(RT)) {
// strip off any ARC lifetime qualifier.
QualType CanResultTy = Context.getCanonicalType(RT);
if (CanResultTy.getQualifiers().hasObjCLifetime()) {
Qualifiers Qs = CanResultTy.getQualifiers();
Qs.removeObjCLifetime();
RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
}
}
PropertyString += " ";
PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy());
PropertyString += RT.getAsString(Context.getPrintingPolicy());
PropertyString += " ";
PropertyString += PropertyNameString;
if (GetterHasIsPrefix) {
// property name must strip off "is" and lower case the first character
// after that; e.g. isContinuous will become continuous.
StringRef PropertyNameStringRef(PropertyNameString);
PropertyNameStringRef = PropertyNameStringRef.drop_front(2);
PropertyNameString = PropertyNameStringRef;
std::string NewPropertyNameString = PropertyNameString;
NewPropertyNameString[0] = std::tolower(NewPropertyNameString[0]);
PropertyString += NewPropertyNameString;
}
else
PropertyString += PropertyNameString;
commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
Getter->getDeclaratorEndLoc()),
PropertyString);
@ -285,7 +313,25 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
PP.getSelectorTable(),
getterName);
if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) {
ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true);
bool GetterHasIsPrefix = false;
if (!SetterMethod) {
// try a different naming convention for getter: isXxxxx
StringRef getterNameString = getterName->getName();
if (getterNameString.startswith("is")) {
GetterHasIsPrefix = true;
const char *CGetterName = getterNameString.data() + 2;
if (CGetterName[0]) {
getterName = &Ctx.Idents.get(CGetterName);
SetterSelector =
SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
PP.getSelectorTable(),
getterName);
SetterMethod = D->lookupMethod(SetterSelector, true);
}
}
}
if (SetterMethod) {
// Is this a valid setter, matching the target getter?
QualType SRT = SetterMethod->getResultType();
if (!SRT->isVoidType())
@ -296,7 +342,8 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
SetterMethod->hasAttrs())
continue;
edit::Commit commit(*Editor);
rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit);
rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
GetterHasIsPrefix);
Editor->commit(commit);
}
}

View File

@ -3,6 +3,7 @@
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result
typedef char BOOL;
@class NSString;
@protocol NSCopying @end
@ -77,4 +78,13 @@
- (int)value;
- (void)setValue: (int)val;
-(BOOL) isContinuous;
-(void) setContinuous:(BOOL)value;
- (id) isAnObject;
- (void)setAnObject : (id) object;
- (id)isxdelegateYYY;
- (void)setXdelegateYYY:(id)delegate;
@end

View File

@ -3,6 +3,7 @@
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result
typedef char BOOL;
@class NSString;
@protocol NSCopying @end
@ -77,4 +78,13 @@
@property int value;
@property(getter=isContinuous) BOOL continuous;
@property(getter=isAnObject, retain) id anObject;
@property(getter=isxdelegateYYY, unsafe_unretained) id xdelegateYYY;
@end