diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart index acd3a687781..7d8a6a01c1f 100644 --- a/pkg/nnbd_migration/lib/src/variables.dart +++ b/pkg/nnbd_migration/lib/src/variables.dart @@ -4,6 +4,7 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/dart/element/handle.dart'; import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/generated/source.dart'; @@ -245,14 +246,18 @@ class Variables implements VariableRecorder, VariableRepository { /// class. Map _decorateDirectSupertypes( ClassElement class_) { - if (class_.type.isObject) { - // TODO(paulberry): this special case is just to get the basic - // infrastructure working (necessary since all classes derive from - // Object). Once we have the full implementation this case shouldn't be - // needed. - return const {}; + var result = {}; + for (var supertype in class_.allSupertypes) { + var decoratedSupertype = + _alreadyMigratedCodeDecorator.decorate(supertype); + assert(identical(decoratedSupertype.node, _graph.never)); + var class_ = (decoratedSupertype.type as InterfaceType).element; + if (class_ is ClassElementHandle) { + class_ = (class_ as ClassElementHandle).actualElement; + } + result[class_] = decoratedSupertype; } - throw UnimplementedError('TODO(paulberry)'); + return result; } int _uniqueOffsetForTypeAnnotation(TypeAnnotation typeAnnotation) => diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart index 81465ac042e..fa146414ab8 100644 --- a/pkg/nnbd_migration/test/edge_builder_test.dart +++ b/pkg/nnbd_migration/test/edge_builder_test.dart @@ -410,6 +410,25 @@ class C> { hard: false); } + test_assign_upcast_generic() async { + await analyze(''' +void f(Iterable x) {} +void g(List x) { + f(x); +} +'''); + + var iterableInt = decoratedTypeAnnotation('Iterable'); + var listInt = decoratedTypeAnnotation('List'); + assertEdge(listInt.node, iterableInt.node, hard: true); + var substitution = graph + .getUpstreamEdges(iterableInt.typeArguments[0].node) + .single + .primarySource as NullabilityNodeForSubstitution; + expect(substitution.innerNode, same(listInt.typeArguments[0].node)); + expect(substitution.outerNode, same(never)); + } + test_assignmentExpression_field() async { await analyze(''' class C {