diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2013-08-01 22:29:32 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2013-08-01 22:29:32 +0000 |
commit | 8234d40843d545e80d98147e30e2917169d30840 (patch) | |
tree | 15826d8ea9e20ad8876f993382d599311ab2e758 /clang/lib | |
parent | 7699e4a50b14faf8a0dd821d0bda87eaa67b45eb (diff) | |
download | bcm5719-llvm-8234d40843d545e80d98147e30e2917169d30840.tar.gz bcm5719-llvm-8234d40843d545e80d98147e30e2917169d30840.zip |
ObjectiveC migrator. Migrate to instancetype return type
for mehods with certain prefix selector matching their class names'
suffix.
llvm-svn: 187626
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/ARCMigrate/ObjCMT.cpp | 80 | ||||
-rw-r--r-- | clang/lib/Basic/IdentifierTable.cpp | 8 |
2 files changed, 63 insertions, 25 deletions
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index 2b2f9224e99..62f3c6b7e79 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -41,6 +41,8 @@ class ObjCMigrateASTConsumer : public ASTConsumer { void migrateInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl); void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl, ObjCMethodDecl *OM); + void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl, + ObjCMethodDecl *OM); public: std::string MigrateDir; @@ -549,13 +551,34 @@ void ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, Editor->commit(commit); } +static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC, + ObjCMethodDecl *OM) { + SourceRange R; + std::string ClassString; + if (TypeSourceInfo *TSInfo = OM->getResultTypeSourceInfo()) { + TypeLoc TL = TSInfo->getTypeLoc(); + R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); + ClassString = "instancetype"; + } + else { + R = SourceRange(OM->getLocStart(), OM->getLocStart()); + ClassString = OM->isInstanceMethod() ? '-' : '+'; + ClassString += " (instancetype)"; + } + edit::Commit commit(*ASTC.Editor); + commit.replace(R, ClassString); + ASTC.Editor->commit(commit); +} + void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl, ObjCMethodDecl *OM) { ObjCInstanceTypeFamily OIT_Family = Selector::getInstTypeMethodFamily(OM->getSelector()); - if (OIT_Family == OIT_None) + if (OIT_Family == OIT_None) { + migrateFactoryMethod(Ctx, CDecl, OM); return; + } std::string ClassName; switch (OIT_Family) { case OIT_Array: @@ -581,24 +604,11 @@ void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, IDecl = ImpDecl->getClassInterface(); } if (!IDecl || - !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) + !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) { + migrateFactoryMethod(Ctx, CDecl, OM); return; - - SourceRange R; - std::string ClassString; - if (TypeSourceInfo *TSInfo = OM->getResultTypeSourceInfo()) { - TypeLoc TL = TSInfo->getTypeLoc(); - R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); - ClassString = "instancetype"; - } - else { - R = SourceRange(OM->getLocStart(), OM->getLocStart()); - ClassString = OM->isInstanceMethod() ? '-' : '+'; - ClassString += " (instancetype)"; } - edit::Commit commit(*Editor); - commit.replace(R, ClassString); - Editor->commit(commit); + ReplaceWithInstancetype(*this, OM); } void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx, @@ -612,6 +622,42 @@ void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx, } } +void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx, + ObjCContainerDecl *CDecl, + ObjCMethodDecl *OM) { + if (OM->isInstanceMethod() || !OM->getResultType()->isObjCIdType()) + return; + + // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class + // NSYYYNamE with matching names be at least 3 characters long. + ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); + if (!IDecl) { + if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) + IDecl = CatDecl->getClassInterface(); + else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) + IDecl = ImpDecl->getClassInterface(); + } + if (!IDecl) + return; + + StringRef ClassName = IDecl->getName(); + if (!ClassName.startswith("NS")) + return; + + ClassName = ClassName.lower(); + IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0); + StringRef MethodName = MethodIdName->getName(); + StringRef MethodNamePrefix = MethodName.substr(0, 3).lower(); + size_t Ix = ClassName.rfind(MethodNamePrefix); + if (Ix == StringRef::npos) + return; + StringRef ClassNamePostfix = ClassName.substr(Ix); + MethodName = MethodName.lower(); + if (!MethodName.startswith(ClassNamePostfix)) + return; + ReplaceWithInstancetype(*this, OM); +} + namespace { class RewritesReceiver : public edit::EditsReceiver { diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 96d9e56b6c3..3572930903f 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -474,14 +474,6 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) { case 'r': if (startsWithWord(name, "retain")) return OIT_MemManage; break; - case 's': - if (startsWithWord(name, "string")) return OIT_NSString; - else - if (startsWithWord(name, "set")) return OIT_NSSet; - break; - case 'U': - if (startsWithWord(name, "URL")) return OIT_NSURL; - break; default: break; } |