[ObjectiveC Migration]: Provide knobs for 
migrating setter/getter methods to an eventual
property declaraiton. This is wip.
// rdar://14345082


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@185591 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index 57fac03..8f56648 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -32,6 +32,7 @@
 
 class ObjCMigrateASTConsumer : public ASTConsumer {
   void migrateDecl(Decl *D);
+  void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCInterfaceDecl *D);
 
 public:
   std::string MigrateDir;
@@ -42,6 +43,7 @@
   FileRemapper &Remapper;
   FileManager &FileMgr;
   const PPConditionalDirectiveRecord *PPRec;
+  Preprocessor &PP;
   bool IsOutputFile;
 
   ObjCMigrateASTConsumer(StringRef migrateDir,
@@ -50,11 +52,12 @@
                          FileRemapper &remapper,
                          FileManager &fileMgr,
                          const PPConditionalDirectiveRecord *PPRec,
+                         Preprocessor &PP,
                          bool isOutputFile = false)
   : MigrateDir(migrateDir),
     MigrateLiterals(migrateLiterals),
     MigrateSubscripting(migrateSubscripting),
-    Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec),
+    Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
     IsOutputFile(isOutputFile) { }
 
 protected:
@@ -105,7 +108,8 @@
                                                        MigrateSubscripting,
                                                        Remapper,
                                                     CompInst->getFileManager(),
-                                                       PPRec);
+                                                       PPRec,
+                                                       CompInst->getPreprocessor());
   ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer };
   return new MultiplexConsumer(Consumers);
 }
@@ -184,6 +188,40 @@
   BodyMigrator(*this).TraverseDecl(D);
 }
 
+void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
+                                                      ObjCInterfaceDecl *D) {
+  for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end();
+       M != MEnd; ++M) {
+    ObjCMethodDecl *Method = (*M);
+    if (Method->isPropertyAccessor())
+      continue;
+    // Is this method candidate to be a getter?
+    if (Method->param_size() == 0) {
+      QualType GRT = Method->getResultType();
+      if (GRT->isVoidType())
+        continue;
+      Selector GetterSelector = Method->getSelector();
+      IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
+      Selector SetterSelector =
+        SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
+                                               PP.getSelectorTable(),
+                                               getterName);
+      if (ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true)) {
+        // Is this a valid setter, matching the target getter?
+        QualType SRT = SetterMethod->getResultType();
+        if (!SRT->isVoidType())
+          continue;
+        const ParmVarDecl *argDecl = *SetterMethod->param_begin();
+        // FIXME. Can relax rule for matching getter/setter type further.
+        if (!Ctx.hasSameType(argDecl->getType(), GRT))
+          continue;
+        // we have a matching setter/getter pair.
+        // TODO. synthesize a suitable property declaration here.
+      }
+    }
+  }
+}
+
 namespace {
 
 class RewritesReceiver : public edit::EditsReceiver {
@@ -203,6 +241,14 @@
 }
 
 void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
+  
+  TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
+  for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
+       D != DEnd; ++D) {
+    if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
+      migrateObjCInterfaceDecl(Ctx, CDecl);
+  }
+  
   Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
   RewritesReceiver Rec(rewriter);
   Editor->applyRewrites(Rec);
@@ -247,5 +293,6 @@
                                     Remapper,
                                     CI.getFileManager(),
                                     PPRec,
+                                    CI.getPreprocessor(),
                                     /*isOutputFile=*/true); 
 }