ObjectiveC migrator: Remove semicolon after the typedef

declaration when converting to NS_ENUM. This required
some code refactoring.

llvm-svn: 186619
This commit is contained in:
Fariborz Jahanian 2013-07-18 22:17:33 +00:00
parent 4d56e9c1cb
commit 85e988bbea
4 changed files with 102 additions and 108 deletions

View File

@ -31,19 +31,8 @@ bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit,
const ParentMap *PMap);
bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
const ObjCMethodDecl *Setter,
const NSAPI &NS, Commit &commit);
bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols,
const NSAPI &NS, Commit &commit);
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
const NSAPI &NS, Commit &commit);
bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
const TypedefDecl *TypedefDcl,
const NSAPI &NS, Commit &commit);
}

View File

@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
#include "Transforms.h"
#include "clang/ARCMigrate/ARCMTActions.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@ -199,6 +200,53 @@ void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
BodyMigrator(*this).TraverseDecl(D);
}
static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
const ObjCMethodDecl *Setter,
const NSAPI &NS, edit::Commit &commit) {
ASTContext &Context = NS.getASTContext();
std::string PropertyString = "@property";
const ParmVarDecl *argDecl = *Setter->param_begin();
QualType ArgType = Context.getCanonicalType(argDecl->getType());
Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
if (ArgType->isObjCRetainableType() &&
propertyLifetime == Qualifiers::OCL_Strong) {
if (const ObjCObjectPointerType *ObjPtrTy =
ArgType->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
if (IDecl &&
IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
PropertyString += "(copy)";
}
}
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)";
else
PropertyString += "(unsafe_unretained)";
// 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);
}
PropertyString += " ";
PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy());
PropertyString += " ";
PropertyString += Getter->getNameAsString();
commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
Getter->getDeclaratorEndLoc()),
PropertyString);
SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
// Get location past ';'
EndLoc = EndLoc.getLocWithOffset(1);
commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc));
return true;
}
void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
ObjCInterfaceDecl *D) {
for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end();
@ -231,7 +279,7 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
SetterMethod->hasAttrs())
continue;
edit::Commit commit(*Editor);
edit::rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit);
rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit);
Editor->commit(commit);
}
}
@ -300,6 +348,55 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
return true;
}
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
const NSAPI &NS, edit::Commit &commit) {
const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
std::string ClassString;
SourceLocation EndLoc =
IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
if (Protocols.empty()) {
ClassString = '<';
for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
ClassString += ConformingProtocols[i]->getNameAsString();
if (i != (e-1))
ClassString += ", ";
}
ClassString += "> ";
}
else {
ClassString = ", ";
for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
ClassString += ConformingProtocols[i]->getNameAsString();
if (i != (e-1))
ClassString += ", ";
}
ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
EndLoc = *PL;
}
commit.insertAfterToken(EndLoc, ClassString);
return true;
}
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
const TypedefDecl *TypedefDcl,
const NSAPI &NS, edit::Commit &commit) {
std::string ClassString = "typedef NS_ENUM(NSInteger, ";
ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ')';
SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
commit.replace(R, ClassString);
SourceLocation EndOfTypedefLoc = TypedefDcl->getLocEnd();
EndOfTypedefLoc = trans::findLocationAfterSemi(EndOfTypedefLoc, NS.getASTContext());
if (!EndOfTypedefLoc.isInvalid()) {
commit.remove(SourceRange(TypedefDcl->getLocStart(), EndOfTypedefLoc));
return true;
}
return false;
}
void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
const ObjCImplementationDecl *ImpDecl) {
const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
@ -352,8 +449,8 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
MinimalConformingProtocols.push_back(TargetPDecl);
}
edit::Commit commit(*Editor);
edit::rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
*NSAPIObj, commit);
rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
*NSAPIObj, commit);
Editor->commit(commit);
}
@ -372,7 +469,7 @@ void ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
return;
edit::Commit commit(*Editor);
edit::rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit);
rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit);
Editor->commit(commit);
}

View File

@ -355,98 +355,6 @@ bool edit::rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
return false;
}
bool edit::rewriteToObjCProperty(const ObjCMethodDecl *Getter,
const ObjCMethodDecl *Setter,
const NSAPI &NS, Commit &commit) {
ASTContext &Context = NS.getASTContext();
std::string PropertyString = "@property";
const ParmVarDecl *argDecl = *Setter->param_begin();
QualType ArgType = Context.getCanonicalType(argDecl->getType());
Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
if (ArgType->isObjCRetainableType() &&
propertyLifetime == Qualifiers::OCL_Strong) {
if (const ObjCObjectPointerType *ObjPtrTy =
ArgType->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
if (IDecl &&
IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
PropertyString += "(copy)";
}
}
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)";
else
PropertyString += "(unsafe_unretained)";
// 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);
}
PropertyString += " ";
PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy());
PropertyString += " ";
PropertyString += Getter->getNameAsString();
commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
Getter->getDeclaratorEndLoc()),
PropertyString);
SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
// Get location past ';'
EndLoc = EndLoc.getLocWithOffset(1);
commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc));
return true;
}
bool edit::rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
const NSAPI &NS, Commit &commit) {
const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
std::string ClassString;
SourceLocation EndLoc =
IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
if (Protocols.empty()) {
ClassString = '<';
for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
ClassString += ConformingProtocols[i]->getNameAsString();
if (i != (e-1))
ClassString += ", ";
}
ClassString += "> ";
}
else {
ClassString = ", ";
for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
ClassString += ConformingProtocols[i]->getNameAsString();
if (i != (e-1))
ClassString += ", ";
}
ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
EndLoc = *PL;
}
commit.insertAfterToken(EndLoc, ClassString);
return true;
}
bool edit::rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
const TypedefDecl *TypedefDcl,
const NSAPI &NS, Commit &commit) {
std::string ClassString = "typedef NS_ENUM(NSInteger, ";
ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ')';
SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
commit.replace(R, ClassString);
commit.remove(SourceRange(TypedefDcl->getLocStart(), TypedefDcl->getLocEnd()));
return true;
}
/// \brief Returns true if the immediate message arguments of \c Msg should not
/// be rewritten because it will interfere with the rewrite of the parent
/// message expression. e.g.

View File

@ -10,4 +10,4 @@ typedef NS_ENUM(NSInteger, wibble) {
blah,
blarg
};
;