Migration: preliminary support for interface types without type parameters.
I'll build on this in future CLs to address more complex cases, where
the type is instantiated to a bound.
Fixes #37213.
Change-Id: I1e23c5599557ef17177483222f15b1a7985b9ca8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105726
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 88991e5..51548fd 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -153,9 +153,13 @@
var namedParameters = const <String, DecoratedType>{};
if (type is InterfaceType && type.typeParameters.isNotEmpty) {
if (node is TypeName) {
- assert(node.typeArguments != null);
- typeArguments =
- node.typeArguments.arguments.map((t) => t.accept(this)).toList();
+ if (node.typeArguments == null) {
+ typeArguments =
+ type.typeArguments.map(_decorateImplicitTypeArgument).toList();
+ } else {
+ typeArguments =
+ node.typeArguments.arguments.map((t) => t.accept(this)).toList();
+ }
} else {
assert(false); // TODO(paulberry): is this possible?
}
@@ -227,6 +231,16 @@
return _NullabilityComment.none;
}
+ /// Creates a DecoratedType corresponding to [type], with fresh nullability
+ /// nodes everywhere that don't correspond to any source location. These
+ /// nodes can later be unioned with other nodes.
+ DecoratedType _decorateImplicitTypeArgument(DartType type) {
+ if (type.isDynamic) {
+ return DecoratedType(type, _graph.always);
+ }
+ throw UnimplementedError('TODO(paulberry): ${type.runtimeType}');
+ }
+
/// Common handling of function and method declarations.
void _handleExecutableDeclaration(
ExecutableElement declaredElement,
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 8f3e7d7..07bb061 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -645,6 +645,18 @@
await _checkSingleFileChanges(content, expected);
}
+ test_genericType_noTypeArguments() async {
+ var content = '''
+void f(C c) {}
+class C<E> {}
+''';
+ var expected = '''
+void f(C c) {}
+class C<E> {}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
test_getter_topLevel() async {
var content = '''
int get g => 0;
diff --git a/pkg/nnbd_migration/test/migration_visitor_test.dart b/pkg/nnbd_migration/test/migration_visitor_test.dart
index 2edc2a0..0b96814 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test.dart
@@ -1339,6 +1339,19 @@
expect(decoratedIntType.node, isNot(never));
}
+ test_interfaceType_generic_instantiate_to_dynamic() async {
+ await analyze('''
+void f(List x) {}
+''');
+ var decoratedListType = decoratedTypeAnnotation('List');
+ expect(decoratedFunctionType('f').positionalParameters[0],
+ same(decoratedListType));
+ expect(decoratedListType.node, isNotNull);
+ expect(decoratedListType.node, isNot(never));
+ var decoratedArgType = decoratedListType.typeArguments[0];
+ expect(decoratedArgType.node, same(always));
+ }
+
test_interfaceType_typeParameter() async {
await analyze('''
void f(List<int> x) {}