Issue 36890. Improve importing elements when incomplete code.

There might be some false negatives, when there *is* another top-level
declaration with the same name as we are removing. But this is a
pre-existing conflict, so I think we should not be very concerned. At
some point we might collect initial potentially conflicting names using
the same SyntacticScopeNamesCollector instead of element model. With
element model we don't know about parser recovery.

R=brianwilkerson@google.com

Bug: https://github.com/dart-lang/sdk/issues/36890
Change-Id: Ia05db299990f41f16feb493c2812237be84f3d2e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101902
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
index 2f545d1..894e061 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
@@ -142,6 +142,22 @@
   }
 
   @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    var variableList = node.fields;
+
+    // `Foo^ Foo bar() {}` is recovered as `Foo Foo; bar() {}`, i.e. the
+    // return type of `bar()` gets associated with a new variable declaration.
+    if (node.semicolon.isSynthetic) {
+      if (variableList.variables.length == 1) {
+        var name = variableList.variables[0].name.name;
+        names.remove(name);
+      }
+    }
+
+    super.visitFieldDeclaration(node);
+  }
+
+  @override
   void visitForElement(ForElement node) {
     if (!_isCoveredBy(node)) return;
 
@@ -236,6 +252,15 @@
       return;
     }
 
+    // `Foo^ Foo bar() {}` is recovered as `Foo Foo; bar() {}`, i.e. the
+    // return type of `bar()` gets associated with a new variable declaration.
+    if (node.semicolon.isSynthetic) {
+      if (variableList.variables.length == 1) {
+        var name = variableList.variables[0].name.name;
+        names.remove(name);
+      }
+    }
+
     super.visitTopLevelVariableDeclaration(node);
   }
 
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 8873d2e..fade0d2 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -161,6 +161,50 @@
 
 @reflectiveTest
 class ImportLibraryElement_incompleteCode_Test extends _Base {
+  test_fieldDeclaration_atEnd() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class C {
+  A^
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+class C {
+  A
+}
+''',
+    );
+  }
+
+  test_fieldDeclaration_beforeReturnType() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class C {
+  A^
+  
+  A foo() => null;
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+class C {
+  A
+  
+  A foo() => null;
+}
+''',
+    );
+  }
+
   test_formalParameter() async {
     newFile('/home/test/lib/a.dart', content: 'class A {}');
     newFile('/home/test/lib/b.dart', content: r'''
@@ -180,7 +224,7 @@
     );
   }
 
-  test_topLevelVariable() async {
+  test_topLevelVariable_atEnd() async {
     newFile('/home/test/lib/a.dart', content: 'class A {}');
     newFile('/home/test/lib/b.dart', content: r'''
 export 'a.dart';
@@ -198,6 +242,26 @@
 ''',
     );
   }
+
+  test_topLevelVariable_beforeReturnType() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+A^
+
+A foo() => null;
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+A
+
+A foo() => null;
+''',
+    );
+  }
 }
 
 @reflectiveTest