ObjectiveC migrator: Support for more possibility of

migration to NS_ENUM/NS_OPTIONS macros; when
typedef'ed to NSInteger/NSUInteger preceeds well
before of the enum declaration. // rdar://15201056

llvm-svn: 192645
This commit is contained in:
Fariborz Jahanian 2013-10-15 00:00:28 +00:00
parent fb8b7b9a1c
commit 059e05eeef
3 changed files with 125 additions and 29 deletions

View File

@ -46,6 +46,7 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D);
void migrateProtocolConformance(ASTContext &Ctx,
const ObjCImplementationDecl *ImpDecl);
void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
const TypedefDecl *TypedefDcl);
void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
@ -77,6 +78,8 @@ public:
std::string MigrateDir;
unsigned ASTMigrateActions;
unsigned FileId;
const TypedefDecl *NSIntegerTypedefed;
const TypedefDecl *NSUIntegerTypedefed;
OwningPtr<NSAPI> NSAPIObj;
OwningPtr<edit::EditedSource> Editor;
FileRemapper &Remapper;
@ -96,7 +99,8 @@ public:
bool isOutputFile = false)
: MigrateDir(migrateDir),
ASTMigrateActions(astMigrateActions),
FileId(0), Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
FileId(0), NSIntegerTypedefed(0), NSUIntegerTypedefed(0),
Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
IsOutputFile(isOutputFile) { }
protected:
@ -509,15 +513,34 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
ClassString += ')';
SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
commit.replace(R, ClassString);
SourceLocation EndOfTypedefLoc = TypedefDcl->getLocEnd();
EndOfTypedefLoc = trans::findLocationAfterSemi(EndOfTypedefLoc, NS.getASTContext(),
SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
NS.getASTContext(), /*IsDecl*/true);
if (!EndOfEnumDclLoc.isInvalid()) {
SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
}
else
return false;
SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
NS.getASTContext(), /*IsDecl*/true);
if (!EndTypedefDclLoc.isInvalid()) {
SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
commit.remove(TDRange);
}
else
return false;
EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
/*IsDecl*/true);
SourceLocation BeginOfTypedefLoc = TypedefDcl->getLocStart();
if (!EndOfTypedefLoc.isInvalid()) {
// FIXME. This assumes that typedef decl; is immediately preceeded by eoln.
// It is trying to remove the typedef decl. line entirely.
BeginOfTypedefLoc = BeginOfTypedefLoc.getLocWithOffset(-1);
commit.remove(SourceRange(BeginOfTypedefLoc, EndOfTypedefLoc));
if (!EndOfEnumDclLoc.isInvalid()) {
SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
// FIXME. This assumes that enum decl; is immediately preceeded by eoln.
// It is trying to remove the enum decl. lines entirely.
BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
return true;
}
return false;
@ -638,12 +661,41 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
Editor->commit(commit);
}
void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
const TypedefDecl *TypedefDcl) {
QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
if (NSAPIObj->isObjCNSIntegerType(qt))
NSIntegerTypedefed = TypedefDcl;
else if (NSAPIObj->isObjCNSUIntegerType(qt))
NSUIntegerTypedefed = TypedefDcl;
}
bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
const EnumDecl *EnumDcl,
const TypedefDecl *TypedefDcl) {
if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
!TypedefDcl->getIdentifier() ||
EnumDcl->isDeprecated() || TypedefDcl->isDeprecated())
EnumDcl->isDeprecated())
return false;
if (!TypedefDcl) {
if (NSIntegerTypedefed) {
TypedefDcl = NSIntegerTypedefed;
NSIntegerTypedefed = 0;
}
else if (NSUIntegerTypedefed) {
TypedefDcl = NSUIntegerTypedefed;
NSUIntegerTypedefed = 0;
}
else
return false;
unsigned FileIdOfTypedefDcl =
PP.getSourceManager().getFileID(TypedefDcl->getLocation()).getHashValue();
unsigned FileIdOfEnumDcl =
PP.getSourceManager().getFileID(EnumDcl->getLocation()).getHashValue();
if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
return false;
}
if (TypedefDcl->isDeprecated())
return false;
QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
@ -678,9 +730,10 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
if (IsNSUIntegerType && !Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition())
return false;
edit::Commit commit(*Editor);
rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, IsNSIntegerType, NSOptions);
bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
commit, IsNSIntegerType, NSOptions);
Editor->commit(commit);
return true;
return Res;
}
static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC,
@ -1432,26 +1485,29 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
migrateProtocolConformance(Ctx, ImpDecl);
}
else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
continue;
DeclContext::decl_iterator N = D;
++N;
if (N != DEnd)
if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N)) {
if (ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros) {
if (migrateNSEnumDecl(Ctx, ED, TD))
D++;
}
}
if (++N != DEnd) {
const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
D++;
}
else
migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */0);
}
else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
DeclContext::decl_iterator N = D;
++N;
if (N != DEnd)
if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
if (ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros) {
if (migrateNSEnumDecl(Ctx, ED, TD))
if (ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros) {
DeclContext::decl_iterator N = D;
if (++N != DEnd)
if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
if (migrateNSEnumDecl(Ctx, ED, TD)) {
++D;
continue;
}
}
}
CacheObjCNSIntegerTypedefed(TD);
}
}
else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)

View File

@ -216,6 +216,9 @@ enum {
} NS_ENUM_AVAILABLE_MAC(10.9);
typedef NSInteger NSModalResponse NS_AVAILABLE_MAC(10.9);
// rdar://15201056
typedef NSUInteger FarAwayNSUInteger;
// rdar://15200915
typedef NSUInteger NSWorkspaceLaunchOptions;
enum {
@ -246,8 +249,26 @@ enum {
NSExclude10_4ElementsCreationOption = 1 << 2
};
enum {
FarAway1 = 1 << 1,
FarAway2 = 1 << 2
};
enum {
NSExcludeQuickDrawElementsIconOption = 1 << 1,
NSExclude10_4ElementsIconOption = 1 << 2
};
typedef NSUInteger NSWorkspaceIconOptions;
typedef NSInteger NSCollectionViewDropOperation;
@interface INTF {
NSCollectionViewDropOperation I1;
NSCollectionViewDropOperation I2;
}
@end
enum {
NotFarAway1 = 1 << 1,
NotFarAway2 = 1 << 2
};

View File

@ -121,6 +121,7 @@ typedef enum {
#define NS_ENUM_AVAILABLE(X,Y)
typedef NS_OPTIONS(NSUInteger, NSFOptions) {
NSFStrongMemory NS_ENUM_AVAILABLE(10_5, 6_0) = (0UL << 0),
NSFOpaqueMemory NS_ENUM_AVAILABLE(10_5, 6_0) = (2UL << 0),
@ -137,7 +138,6 @@ typedef NS_OPTIONS(NSUInteger, NSFOptions) {
NSFCopyIn NS_ENUM_AVAILABLE(10_5, 6_0) = (1UL << 16),
};
typedef NS_ENUM(NSInteger, UIP) {
UIP0One = 0,
UIP0Two = 1,
@ -206,6 +206,12 @@ typedef NS_ENUM(NSInteger, NSModalResponse) {
NSModalResponseContinue = (-1002),
} NS_ENUM_AVAILABLE_MAC(10.9);
// rdar://15201056
typedef NS_OPTIONS(NSUInteger, FarAwayNSUInteger) {
FarAway1 = 1 << 1,
FarAway2 = 1 << 2
};
// rdar://15200915
typedef NS_OPTIONS(NSUInteger, NSWorkspaceLaunchOptions) {
NSWorkspaceLaunchAndPrint = 0x00000002,
@ -233,7 +239,20 @@ typedef NS_OPTIONS(NSUInteger, NSWorkspaceCreationOptions) {
NSExclude10_4ElementsCreationOption = 1 << 2
};
typedef NS_OPTIONS(NSUInteger, NSWorkspaceIconOptions) {
NSExcludeQuickDrawElementsIconOption = 1 << 1,
NSExclude10_4ElementsIconOption = 1 << 2
};
typedef NS_OPTIONS(NSUInteger, NSCollectionViewDropOperation) {
NotFarAway1 = 1 << 1,
NotFarAway2 = 1 << 2
};
@interface INTF {
NSCollectionViewDropOperation I1;
NSCollectionViewDropOperation I2;
}
@end