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); 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, static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
const ObjCMethodDecl *Setter, const ObjCMethodDecl *Setter,
const NSAPI &NS, edit::Commit &commit) { const NSAPI &NS, edit::Commit &commit,
bool GetterHasIsPrefix) {
ASTContext &Context = NS.getASTContext(); ASTContext &Context = NS.getASTContext();
std::string PropertyString = "@property"; std::string PropertyString = "@property";
std::string PropertyNameString = Getter->getNameAsString(); std::string PropertyNameString = Getter->getNameAsString();
StringRef PropertyName(PropertyNameString); StringRef PropertyName(PropertyNameString);
if (GetterHasIsPrefix) {
PropertyString += "(getter=";
PropertyString += PropertyNameString;
}
// Short circuit properties that contain the name "delegate" or "dataSource", // Short circuit properties that contain the name "delegate" or "dataSource",
// or have exact name "target" to have unsafe_unretained attribute. // or have exact name "target" to have unsafe_unretained attribute.
if (PropertyName.equals("target") || if (PropertyName.equals("target") ||
(PropertyName.find("delegate") != StringRef::npos) || (PropertyName.find("delegate") != StringRef::npos) ||
(PropertyName.find("dataSource") != StringRef::npos)) (PropertyName.find("dataSource") != StringRef::npos))
PropertyString += "(unsafe_unretained)"; append_attr(PropertyString, "unsafe_unretained", GetterHasIsPrefix);
else { else {
const ParmVarDecl *argDecl = *Setter->param_begin(); const ParmVarDecl *argDecl = *Setter->param_begin();
QualType ArgType = Context.getCanonicalType(argDecl->getType()); QualType ArgType = Context.getCanonicalType(argDecl->getType());
@ -231,29 +242,46 @@ static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
if (IDecl && if (IDecl &&
IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
PropertyString += "(copy)"; append_attr(PropertyString, "copy", GetterHasIsPrefix);
else else
PropertyString += "(retain)"; append_attr(PropertyString, "retain", GetterHasIsPrefix);
} } else if (GetterHasIsPrefix)
PropertyString += ')';
} else if (propertyLifetime == Qualifiers::OCL_Weak) } else if (propertyLifetime == Qualifiers::OCL_Weak)
// TODO. More precise determination of 'weak' attribute requires // TODO. More precise determination of 'weak' attribute requires
// looking into setter's implementation for backing weak ivar. // looking into setter's implementation for backing weak ivar.
PropertyString += "(weak)"; append_attr(PropertyString, "weak", GetterHasIsPrefix);
else if (RetainableObject) else if (RetainableObject)
PropertyString += "(retain)"; append_attr(PropertyString, "retain", GetterHasIsPrefix);
else if (GetterHasIsPrefix)
PropertyString += ')';
} }
// strip off any ARC lifetime qualifier. QualType RT = Getter->getResultType();
QualType CanResultTy = Context.getCanonicalType(Getter->getResultType()); if (!isa<TypedefType>(RT)) {
if (CanResultTy.getQualifiers().hasObjCLifetime()) { // strip off any ARC lifetime qualifier.
Qualifiers Qs = CanResultTy.getQualifiers(); QualType CanResultTy = Context.getCanonicalType(RT);
Qs.removeObjCLifetime(); if (CanResultTy.getQualifiers().hasObjCLifetime()) {
CanResultTy = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); Qualifiers Qs = CanResultTy.getQualifiers();
Qs.removeObjCLifetime();
RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
}
} }
PropertyString += " "; PropertyString += " ";
PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy()); PropertyString += RT.getAsString(Context.getPrintingPolicy());
PropertyString += " "; 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(), commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
Getter->getDeclaratorEndLoc()), Getter->getDeclaratorEndLoc()),
PropertyString); PropertyString);
@ -285,7 +313,25 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
SelectorTable::constructSetterSelector(PP.getIdentifierTable(), SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
PP.getSelectorTable(), PP.getSelectorTable(),
getterName); 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? // Is this a valid setter, matching the target getter?
QualType SRT = SetterMethod->getResultType(); QualType SRT = SetterMethod->getResultType();
if (!SRT->isVoidType()) if (!SRT->isVoidType())
@ -296,7 +342,8 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
SetterMethod->hasAttrs()) SetterMethod->hasAttrs())
continue; continue;
edit::Commit commit(*Editor); edit::Commit commit(*Editor);
rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit); rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
GetterHasIsPrefix);
Editor->commit(commit); 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: 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 // 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; @class NSString;
@protocol NSCopying @end @protocol NSCopying @end
@ -77,4 +78,13 @@
- (int)value; - (int)value;
- (void)setValue: (int)val; - (void)setValue: (int)val;
-(BOOL) isContinuous;
-(void) setContinuous:(BOOL)value;
- (id) isAnObject;
- (void)setAnObject : (id) object;
- (id)isxdelegateYYY;
- (void)setXdelegateYYY:(id)delegate;
@end @end

View File

@ -3,6 +3,7 @@
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result // 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 // 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; @class NSString;
@protocol NSCopying @end @protocol NSCopying @end
@ -77,4 +78,13 @@
@property int value; @property int value;
@property(getter=isContinuous) BOOL continuous;
@property(getter=isAnObject, retain) id anObject;
@property(getter=isxdelegateYYY, unsafe_unretained) id xdelegateYYY;
@end @end