Bug fix with file move and renames, http://dartbug.com/37121

Bug: dartbug.com/37121
Change-Id: I9ffc7e39a33ca36d78a123b8567261d8709b9e6a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107200
Reviewed-by: Jaime Wren <jwren@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Jaime Wren <jwren@google.com>
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index 164d553..2a0f5fb 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -69,21 +69,49 @@
 
   @override
   Future<SourceChange> createChange() async {
-    var changeBuilder = new DartChangeBuilder(driver.currentSession);
-    final element = resolvedUnit.unit.declaredElement;
+    final DartChangeBuilder changeBuilder =
+        new DartChangeBuilder(driver.currentSession);
+    final CompilationUnitElement element = resolvedUnit.unit.declaredElement;
     if (element == null) {
       return changeBuilder.sourceChange;
     }
-    final library = element.library;
+    final LibraryElement libraryElement = element.library;
 
     // If this element is a library, update outgoing references inside the file.
-    if (element == library.definingCompilationUnit) {
-      await changeBuilder.addFileEdit(library.source.fullName, (builder) {
-        final oldDir = pathContext.dirname(oldFile);
-        final newDir = pathContext.dirname(newFile);
-        _updateUriReferences(builder, library.imports, oldDir, newDir);
-        _updateUriReferences(builder, library.exports, oldDir, newDir);
-        _updateUriReferences(builder, library.parts, oldDir, newDir);
+    if (element == libraryElement.definingCompilationUnit) {
+      // Handle part-of directives in this library
+      final ResolvedLibraryResult libraryResult = await driver.currentSession
+          .getResolvedLibraryByElement(libraryElement);
+      for (ResolvedUnitResult result in libraryResult.units) {
+        if (result.isPart) {
+          Iterable<PartOfDirective> partOfs = result.unit.directives
+              .whereType<PartOfDirective>()
+              .where(
+                  (po) => po.uri != null && _isRelativeUri(po.uri.stringValue));
+          if (partOfs.isNotEmpty) {
+            await changeBuilder.addFileEdit(result.unit.element.source.fullName,
+                (builder) {
+              partOfs.forEach((po) {
+                final oldDir = pathContext.dirname(oldFile);
+                final newDir = pathContext.dirname(newFile);
+                String newLocation =
+                    pathContext.join(newDir, pathos.basename(newFile));
+                String newUri = _getRelativeUri(newLocation, oldDir);
+                builder.addSimpleReplacement(
+                    new SourceRange(po.uri.offset, po.uri.length), "'$newUri'");
+              });
+            });
+          }
+        }
+      }
+
+      await changeBuilder.addFileEdit(libraryElement.source.fullName,
+          (builder) {
+        final String oldDir = pathContext.dirname(oldFile);
+        final String newDir = pathContext.dirname(newFile);
+        _updateUriReferences(builder, libraryElement.imports, oldDir, newDir);
+        _updateUriReferences(builder, libraryElement.exports, oldDir, newDir);
+        _updateUriReferences(builder, libraryElement.parts, oldDir, newDir);
       });
     } else {
       // Otherwise, we need to update any relative part-of references.
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index f49c238..69260ef 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -345,8 +345,6 @@
 ''');
   }
 
-  // Failing test for http://dartbug.com/37121
-  @failingTest
   test_renaming_part_that_uses_uri_in_part_of_2() async {
     // If the file is a part in a library, and the part-of directive uses a URI
     // rather than a library name, that will need updating too (if the relative
@@ -377,6 +375,29 @@
     String pathA = convertPath('/home/test/000/1111/a.dart');
     testFile = convertPath('/home/test/000/1111/test.dart');
     addSource(pathA, '''
+part of 'test.dart';
+''');
+    await resolveTestUnit('''
+part 'a.dart';
+''');
+    // perform refactoring
+    _createRefactoring('/home/test/000/1111/test2.dart');
+    await _assertSuccessfulRefactoring();
+    assertFileChangeResult(pathA, '''
+part of 'test2.dart';
+''');
+    assertFileChangeResult(testFile, '''
+part 'a.dart';
+''');
+  }
+
+  test_renaming_part_that_uses_uri_in_part_of_4() async {
+    // If the file is a part in a library, and the part-of directive uses a URI
+    // rather than a library name, that will need updating too (if the relative
+    // path to the parent changes).
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/test.dart');
+    addSource(pathA, '''
 part 'test.dart';
 ''');
     await resolveTestUnit('''
@@ -393,6 +414,29 @@
 ''');
   }
 
+  test_renaming_part_that_uses_uri_in_part_of_5() async {
+    // If the file is a part in a library, and the part-of directive uses a URI
+    // rather than a library name, that will need updating too (if the relative
+    // path to the parent changes).
+    String pathA = convertPath('/home/test/000/1111/a.dart');
+    testFile = convertPath('/home/test/000/1111/test.dart');
+    addSource(pathA, '''
+part 'test.dart';
+''');
+    await resolveTestUnit('''
+part of 'a.dart';
+''');
+    // perform refactoring
+    _createRefactoring('/home/test/000/1111/test2.dart');
+    await _assertSuccessfulRefactoring();
+    assertFileChangeResult(pathA, '''
+part 'test2.dart';
+''');
+    assertFileChangeResult(testFile, '''
+part of 'a.dart';
+''');
+  }
+
   Future _assertFailedRefactoring(RefactoringProblemSeverity expectedSeverity,
       {String expectedMessage}) async {
     RefactoringStatus status = await refactoring.checkAllConditions();