Merge pull request #9850 from nkcsgexi/perperty-migration-4.0

[4.0][migrator] Handle getter function to property change in function overrides.
diff --git a/include/swift/IDE/APIDigesterData.h b/include/swift/IDE/APIDigesterData.h
index cf8e77f..ead967c 100644
--- a/include/swift/IDE/APIDigesterData.h
+++ b/include/swift/IDE/APIDigesterData.h
@@ -118,6 +118,17 @@
       return false;
     }
   }
+
+  bool isToPropertyChange() const {
+    switch (DiffKind) {
+    case NodeAnnotation::GetterToProperty:
+    case NodeAnnotation::SetterToProperty:
+      return true;
+    default:
+      return false;
+    }
+  }
+
   StringRef getNewName() const { assert(isRename()); return RightComment; }
   APIDiffItemKind getKind() const override {
     return APIDiffItemKind::ADK_CommonDiffItem;
diff --git a/lib/Migrator/APIDiffMigratorPass.cpp b/lib/Migrator/APIDiffMigratorPass.cpp
index 96d0950..75be234 100644
--- a/lib/Migrator/APIDiffMigratorPass.cpp
+++ b/lib/Migrator/APIDiffMigratorPass.cpp
@@ -605,6 +605,84 @@
     return Replacement.contains('&') || Replacement.contains("->");
   }
 
+  void handleOverridingTypeChange(AbstractFunctionDecl *AFD,
+                                  CommonDiffItem *DiffItem) {
+    assert(AFD);
+    assert(DiffItem->isTypeChange());
+    ChildIndexFinder Finder(DiffItem->getChildIndices());
+    auto Result = Finder.findChild(AFD);
+    if (!Result.isValid())
+      return;
+
+    switch (DiffItem->DiffKind) {
+      case ide::api::NodeAnnotation::WrapOptional:
+        if (Result.Suffixable) {
+          Editor.insertAfterToken(Result.TokenRange.End, "?");
+        } else {
+          Editor.insertWrap("(", Result.TokenRange, ")?");
+        }
+        break;
+      case ide::api::NodeAnnotation::WrapImplicitOptional:
+        if (Result.Suffixable) {
+          Editor.insertAfterToken(Result.TokenRange.End, "!");
+        } else {
+          Editor.insertWrap("(", Result.TokenRange, (")!"));
+        }
+        break;
+      case ide::api::NodeAnnotation::UnwrapOptional:
+        if (Result.Optional)
+          Editor.remove(Result.TokenRange.End);
+        break;
+      case ide::api::NodeAnnotation::ImplicitOptionalToOptional:
+        if (Result.Optional)
+          Editor.replace(Result.TokenRange.End, "?");
+        break;
+      case ide::api::NodeAnnotation::TypeRewritten:
+        Editor.replace(Result.TokenRange, DiffItem->RightComment);
+        if (Result.Suffixed && typeReplacementMayNeedParens(DiffItem->RightComment)) {
+          Editor.insertBefore(Result.TokenRange.Start, "(");
+          Editor.insertAfterToken(Result.TokenRange.End, ")");
+        }
+        break;
+      default:
+        break;
+    }
+  }
+
+  void handleOverridingPropertyChange(AbstractFunctionDecl *AFD,
+                                      CommonDiffItem *DiffItem) {
+    assert(AFD);
+    assert(DiffItem->isToPropertyChange());
+    auto FD = dyn_cast<FuncDecl>(AFD);
+    if (!FD)
+      return;
+
+    switch (DiffItem->DiffKind) {
+    case NodeAnnotation::GetterToProperty: {
+      auto FuncLoc = FD->getFuncLoc();
+      auto ReturnTyLoc = FD->getBodyResultTypeLoc().getLoc();
+      auto NameLoc = FD->getNameLoc();
+      if (FuncLoc.isInvalid() || ReturnTyLoc.isInvalid() || NameLoc.isInvalid())
+        break;
+
+      // Replace "func" with "var"
+      Editor.replaceToken(FuncLoc, "var");
+
+      // Replace "() -> " with ": "
+      Editor.replace(CharSourceRange(SM, Lexer::getLocForEndOfToken(SM, NameLoc),
+        ReturnTyLoc), ": ");
+
+      break;
+    }
+    case NodeAnnotation::SetterToProperty: {
+      // FIXME: we should migrate this case too.
+      break;
+    }
+    default:
+      llvm_unreachable("should not be handled here.");
+    }
+  }
+
   bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
     if (D->isImplicit())
       return true;
@@ -612,47 +690,10 @@
       handleFuncDeclRename(AFD, Range);
       for (auto *Item: getRelatedDiffItems(AFD)) {
         if (auto *DiffItem = dyn_cast<CommonDiffItem>(Item)) {
-          if (!DiffItem->isTypeChange())
-            continue;
-
-          ChildIndexFinder Finder(DiffItem->getChildIndices());
-          auto Result = Finder.findChild(AFD);
-          if (!Result.isValid())
-            return false;
-
-          switch (DiffItem->DiffKind) {
-          case ide::api::NodeAnnotation::WrapOptional:
-            if (Result.Suffixable) {
-              Editor.insertAfterToken(Result.TokenRange.End, "?");
-            } else {
-              Editor.insertWrap("(", Result.TokenRange, ")?");
-            }
-            break;
-          case ide::api::NodeAnnotation::WrapImplicitOptional:
-            if (Result.Suffixable) {
-              Editor.insertAfterToken(Result.TokenRange.End, "!");
-            } else {
-              Editor.insertWrap("(", Result.TokenRange, (")!"));
-            }
-            break;
-          case ide::api::NodeAnnotation::UnwrapOptional:
-            if (Result.Optional)
-              Editor.remove(Result.TokenRange.End);
-            break;
-          case ide::api::NodeAnnotation::ImplicitOptionalToOptional:
-            if (Result.Optional)
-              Editor.replace(Result.TokenRange.End, "?");
-            break;
-          case ide::api::NodeAnnotation::TypeRewritten:
-            Editor.replace(Result.TokenRange, DiffItem->RightComment);
-            if (Result.Suffixed && typeReplacementMayNeedParens(DiffItem->RightComment)) {
-              Editor.insertBefore(Result.TokenRange.Start, "(");
-              Editor.insertAfterToken(Result.TokenRange.End, ")");
-            }
-            break;
-          default:
-            break;
-          }
+          if (DiffItem->isTypeChange())
+            handleOverridingTypeChange(AFD, DiffItem);
+          else if (DiffItem->isToPropertyChange())
+            handleOverridingPropertyChange(AFD, DiffItem);
         }
       }
     }
diff --git a/test/Migrator/property.swift b/test/Migrator/property.swift
index 1451aa5..5e35b89 100644
--- a/test/Migrator/property.swift
+++ b/test/Migrator/property.swift
@@ -8,3 +8,7 @@
   a.setField(1)
   _ = a.field()
 }
+
+class C: PropertyUserInterface {
+  public override func field() -> Int32 { return 1 }
+}
diff --git a/test/Migrator/property.swift.expected b/test/Migrator/property.swift.expected
index 68d34ef..09981d1 100644
--- a/test/Migrator/property.swift.expected
+++ b/test/Migrator/property.swift.expected
@@ -8,3 +8,7 @@
   a.Field = 1
   _ = a.field
 }
+
+class C: PropertyUserInterface {
+  public override var field: Int32 { return 1 }
+}