forked from OSchip/llvm-project
ObjC migrator: build conforming interface
declaration (not yet used). wip. llvm-svn: 186369
This commit is contained in:
parent
aa0307021d
commit
5bd5affe2d
|
@ -9,10 +9,13 @@
|
||||||
|
|
||||||
#ifndef LLVM_CLANG_EDIT_REWRITERS_H
|
#ifndef LLVM_CLANG_EDIT_REWRITERS_H
|
||||||
#define LLVM_CLANG_EDIT_REWRITERS_H
|
#define LLVM_CLANG_EDIT_REWRITERS_H
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class ObjCMessageExpr;
|
class ObjCMessageExpr;
|
||||||
class ObjCMethodDecl;
|
class ObjCMethodDecl;
|
||||||
|
class ObjCInterfaceDecl;
|
||||||
|
class ObjCProtocolDecl;
|
||||||
class NSAPI;
|
class NSAPI;
|
||||||
class ParentMap;
|
class ParentMap;
|
||||||
|
|
||||||
|
@ -29,6 +32,9 @@ bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
|
||||||
bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
|
bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
|
||||||
const ObjCMethodDecl *Setter,
|
const ObjCMethodDecl *Setter,
|
||||||
const NSAPI &NS, Commit &commit);
|
const NSAPI &NS, Commit &commit);
|
||||||
|
bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
|
||||||
|
llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols,
|
||||||
|
const NSAPI &NS, Commit &commit);
|
||||||
|
|
||||||
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
|
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg,
|
||||||
const NSAPI &NS, Commit &commit);
|
const NSAPI &NS, Commit &commit);
|
||||||
|
|
|
@ -250,6 +250,8 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
|
||||||
if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
||||||
continue;
|
continue;
|
||||||
DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
|
DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
|
||||||
|
if (R.size() == 0)
|
||||||
|
return false;
|
||||||
for (unsigned I = 0, N = R.size(); I != N; ++I) {
|
for (unsigned I = 0, N = R.size(); I != N; ++I) {
|
||||||
if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
|
if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
|
||||||
if (ClassProperty->getPropertyAttributes()
|
if (ClassProperty->getPropertyAttributes()
|
||||||
|
@ -263,14 +265,20 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
|
||||||
// At this point, all required properties in this protocol conform to those
|
// At this point, all required properties in this protocol conform to those
|
||||||
// declared in the class.
|
// declared in the class.
|
||||||
// Check that class implements the required methods of the protocol too.
|
// Check that class implements the required methods of the protocol too.
|
||||||
if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
|
if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
|
||||||
|
if (PDecl->meth_begin() == PDecl->meth_end())
|
||||||
|
return false;
|
||||||
for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(),
|
for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(),
|
||||||
MEnd = PDecl->meth_end(); M != MEnd; ++M) {
|
MEnd = PDecl->meth_end(); M != MEnd; ++M) {
|
||||||
ObjCMethodDecl *MD = (*M);
|
ObjCMethodDecl *MD = (*M);
|
||||||
|
if (MD->isImplicit())
|
||||||
|
continue;
|
||||||
if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
|
if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
|
||||||
continue;
|
continue;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
|
DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
|
||||||
|
if (R.size() == 0)
|
||||||
|
return false;
|
||||||
for (unsigned I = 0, N = R.size(); I != N; ++I)
|
for (unsigned I = 0, N = R.size(); I != N; ++I)
|
||||||
if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
|
if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
|
||||||
if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
|
if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
|
||||||
|
@ -280,6 +288,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
|
||||||
if (!match)
|
if (!match)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -312,6 +321,12 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
|
||||||
if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
|
if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
|
||||||
PotentialImplicitProtocols[i]))
|
PotentialImplicitProtocols[i]))
|
||||||
ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
|
ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
|
||||||
|
|
||||||
|
if (ConformingProtocols.empty())
|
||||||
|
return;
|
||||||
|
edit::Commit commit(*Editor);
|
||||||
|
edit::rewriteToObjCInterfaceDecl(IDecl, ConformingProtocols, *NSAPIObj, commit);
|
||||||
|
Editor->commit(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -402,6 +402,38 @@ bool edit::rewriteToObjCProperty(const ObjCMethodDecl *Getter,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool edit::rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
|
||||||
|
llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
|
||||||
|
const NSAPI &NS, Commit &commit) {
|
||||||
|
const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
|
||||||
|
|
||||||
|
// ASTContext &Context = NS.getASTContext();
|
||||||
|
std::string ClassString = "@interface ";
|
||||||
|
ClassString += IDecl->getNameAsString();
|
||||||
|
|
||||||
|
if (IDecl->getSuperClass()) {
|
||||||
|
ClassString += " : ";
|
||||||
|
ClassString += IDecl->getSuperClass()->getNameAsString();
|
||||||
|
}
|
||||||
|
if (Protocols.empty())
|
||||||
|
ClassString += '<';
|
||||||
|
|
||||||
|
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
|
||||||
|
E = Protocols.end(); I != E; ++I) {
|
||||||
|
ClassString += (I == Protocols.begin() ? '<' : ',');
|
||||||
|
ClassString += (*I)->getNameAsString();
|
||||||
|
}
|
||||||
|
if (!Protocols.empty())
|
||||||
|
ClassString += ',';
|
||||||
|
for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
|
||||||
|
ClassString += ConformingProtocols[i]->getNameAsString();
|
||||||
|
if (i != (e-1))
|
||||||
|
ClassString += ',';
|
||||||
|
}
|
||||||
|
ClassString += "> ";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Returns true if the immediate message arguments of \c Msg should not
|
/// \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
|
/// be rewritten because it will interfere with the rewrite of the parent
|
||||||
/// message expression. e.g.
|
/// message expression. e.g.
|
||||||
|
|
Loading…
Reference in New Issue