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');
}