forked from OSchip/llvm-project
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:
parent
b88cdf62f5
commit
cf2ff9ba32
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue