Give import prefix type 'dynamic' when it is used as an expression.

R=brianwilkerson@google.com

Bug: https://github.com/dart-lang/sdk/issues/34209
Change-Id: I6c393af70342037c496adebefaaf66c7a685852a
Reviewed-on: https://dart-review.googlesource.com/73240
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 3eff7fd..12ebc38 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -547,6 +547,10 @@
   }
 
   Expression _findOuterExpression(AstNode start, InterfaceType builtInType) {
+    if (start is SimpleIdentifier && start.staticElement is PrefixElement) {
+      return null;
+    }
+
     AstNode parent;
     if (start is Expression) {
       parent = start;
@@ -556,11 +560,13 @@
     if (parent == null) {
       return null;
     }
+
     var list = <Expression>[];
     while (parent is Expression) {
       list.add(parent);
       parent = parent.parent;
     }
+
     Expression expr = list.firstWhere((expr) {
       DartType type = expr.staticType;
       if (type == null) return false;
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 8e8dcb0..5e69a5b 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -994,7 +994,12 @@
       VariableElement variable = element;
       staticType = _promoteManager.getStaticType(variable);
     } else if (element is PrefixElement) {
-      return null;
+      var parent = node.parent;
+      if (parent is PrefixedIdentifier && parent.prefix == node ||
+          parent is MethodInvocation && parent.target == node) {
+        return null;
+      }
+      staticType = _typeProvider.dynamicType;
     } else if (element is DynamicElementImpl) {
       staticType = _typeProvider.typeType;
     } else {
@@ -1207,10 +1212,6 @@
   }
 
   DartType _findIteratedType(DartType type, DartType targetType) {
-    if (type == null) {
-      return null;
-    }
-
     // TODO(vsm): Use leafp's matchType here?
     // Set by _find if match is found
     DartType result;
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index 31b18ca..6316ceb 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -770,7 +770,7 @@
 
     var pRef = findNode.simple('p +=');
     assertElement(pRef, findElement.prefix('p'));
-    assertTypeNull(pRef);
+    assertTypeDynamic(pRef);
   }
 
   test_to_prefix_increment() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
index 88b9125..3062f41 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_in_test.dart
@@ -18,6 +18,8 @@
 
 abstract class ForInResolutionMixin implements ResolutionTest {
   test_importPrefix_asIterable() async {
+    // TODO(scheglov) Remove this test (already tested as import prefix).
+    // TODO(scheglov) Move other for-in tests here.
     addTestFile(r'''
 import 'dart:async' as p;
 
@@ -32,8 +34,8 @@
     expect(xRef.staticElement, isNotNull);
 
     var pRef = findNode.simple('p) {}');
-    assertElement(pRef, findElement.import('dart:async').prefix);
-    assertTypeNull(pRef);
+    assertElement(pRef, findElement.prefix('p'));
+    assertTypeDynamic(pRef);
   }
 }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
new file mode 100644
index 0000000..ea22bc8
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/import_prefix_test.dart
@@ -0,0 +1,115 @@
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+import 'resolution.dart';
+import 'task_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImportPrefixDriverResolutionTest);
+    defineReflectiveTests(ImportPrefixTaskResolutionTest);
+  });
+}
+
+@reflectiveTest
+class ImportPrefixDriverResolutionTest extends DriverResolutionTest
+    with ImportPrefixResolutionMixin {}
+
+abstract class ImportPrefixResolutionMixin implements ResolutionTest {
+  test_asExpression_expressionStatement() async {
+    addTestFile(r'''
+import 'dart:async' as p;
+
+main() {
+  p; // use
+}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+    ]);
+
+    var pRef = findNode.simple('p; // use');
+    assertElement(pRef, findElement.prefix('p'));
+    assertTypeDynamic(pRef);
+  }
+
+  test_asExpression_forIn_iterable() async {
+    addTestFile(r'''
+import 'dart:async' as p;
+
+main() {
+  for (var x in p) {}
+}
+''');
+    await resolveTestFile();
+    assertHasTestErrors();
+
+    var xRef = findNode.simple('x in');
+    expect(xRef.staticElement, isNotNull);
+
+    var pRef = findNode.simple('p) {}');
+    assertElement(pRef, findElement.prefix('p'));
+    assertTypeDynamic(pRef);
+  }
+
+  test_asExpression_instanceCreation_argument() async {
+    addTestFile(r'''
+import 'dart:async' as p;
+
+class C<T> {
+  C(a);
+}
+
+main() {
+  var x = new C(p);
+}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+    ]);
+
+    var pRef = findNode.simple('p);');
+    assertElement(pRef, findElement.prefix('p'));
+    assertTypeDynamic(pRef);
+  }
+
+  test_asPrefix_methodInvocation() async {
+    addTestFile(r'''
+import 'dart:math' as p;
+
+main() {
+  p.max(0, 0);
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var pRef = findNode.simple('p.max');
+    assertElement(pRef, findElement.prefix('p'));
+    assertTypeNull(pRef);
+  }
+
+  test_asPrefix_prefixedIdentifier() async {
+    addTestFile(r'''
+import 'dart:async' as p;
+
+main() {
+  p.Future;
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var pRef = findNode.simple('p.Future');
+    assertElement(pRef, findElement.prefix('p'));
+    assertTypeNull(pRef);
+  }
+}
+
+@reflectiveTest
+class ImportPrefixTaskResolutionTest extends TaskResolutionTest
+    with ImportPrefixResolutionMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 4417ef9..6863f71 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -7,6 +7,7 @@
 import 'assignment_test.dart' as assignment_test;
 import 'class_test.dart' as class_test;
 import 'for_in_test.dart' as for_in_test;
+import 'import_prefix_test.dart' as import_prefix_test;
 import 'mixin_test.dart' as mixin_test;
 
 main() {
@@ -14,6 +15,7 @@
     assignment_test.main();
     class_test.main();
     for_in_test.main();
+    import_prefix_test.main();
     mixin_test.main();
   }, name: 'resolution');
 }