]> granicus.if.org Git - clang/commitdiff
ObjC migrator: build conforming interface
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 16 Jul 2013 00:20:21 +0000 (00:20 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 16 Jul 2013 00:20:21 +0000 (00:20 +0000)
declaration (not yet used). wip.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186369 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Edit/Rewriters.h
lib/ARCMigrate/ObjCMT.cpp
lib/Edit/RewriteObjCFoundationAPI.cpp

index cfb59dfa32c6c895f19fef4f2d8dea1d8a85d158..d7718c540b4e954a4e3537aa058c7a148a92d0b0 100644 (file)
@@ -9,10 +9,13 @@
 
 #ifndef LLVM_CLANG_EDIT_REWRITERS_H
 #define LLVM_CLANG_EDIT_REWRITERS_H
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
   class ObjCMessageExpr;
   class ObjCMethodDecl;
+  class ObjCInterfaceDecl;
+  class ObjCProtocolDecl;
   class NSAPI;
   class ParentMap;
 
@@ -29,6 +32,9 @@ bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg,
 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);
index 18919faa9a4c7c36c068e8de145f6a8d73b9a378..dd210264582e5d2b9707bbb50bcdf69ffd5a6c3f 100644 (file)
@@ -250,6 +250,8 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
       if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
         continue;
       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) {
         if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
           if (ClassProperty->getPropertyAttributes()
@@ -263,14 +265,20 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
   // At this point, all required properties in this protocol conform to those
   // declared in the class.
   // 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(),
          MEnd = PDecl->meth_end(); M != MEnd; ++M) {
       ObjCMethodDecl *MD = (*M);
+      if (MD->isImplicit())
+        continue;
       if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
         continue;
       bool match = false;
       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)
         if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
           if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
@@ -280,6 +288,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
       if (!match)
         return false;
     }
+  }
 
   return true;
 }
@@ -312,6 +321,12 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
     if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
                                               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 {
index 8d24003d942721dbf87b896d4dbfccaf5a113f0d..fd9c16ee6a09c5878072c7bbc9a8a43d88d004c0 100644 (file)
@@ -402,6 +402,38 @@ bool edit::rewriteToObjCProperty(const ObjCMethodDecl *Getter,
   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
 /// be rewritten because it will interfere with the rewrite of the parent
 /// message expression. e.g.