From 991e55f6ad2f4177f663dc61ab647bdcbb5c7fe5 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Dec 2019 19:53:11 +0000 Subject: [PATCH] NNBD Migrator: Fix generic super initializers Change-Id: Icc78a248791881a97f5221ee2b5edf6314266225 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127542 Reviewed-by: Mike Fairhurst Commit-Queue: Samuel Rawlins --- pkg/nnbd_migration/lib/src/edge_builder.dart | 32 ++++++++++---- .../test/edge_builder_test.dart | 42 ++++++++----------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart index d26eb68ce3dc..4732c4e0e84f 100644 --- a/pkg/nnbd_migration/lib/src/edge_builder.dart +++ b/pkg/nnbd_migration/lib/src/edge_builder.dart @@ -799,11 +799,11 @@ class EdgeBuilder extends GeneralizingAstVisitor InstanceCreationExpression node) { var callee = node.staticElement; var typeParameters = callee.enclosingElement.typeParameters; - List typeArgumentTypes; + Iterable typeArgumentTypes; List decoratedTypeArguments; var typeArguments = node.constructorName.type.typeArguments; if (typeArguments != null) { - typeArgumentTypes = typeArguments.arguments.map((t) => t.type).toList(); + typeArgumentTypes = typeArguments.arguments.map((t) => t.type); decoratedTypeArguments = typeArguments.arguments .map((t) => _variables.decoratedTypeAnnotation(source, t)) .toList(); @@ -1267,15 +1267,28 @@ class EdgeBuilder extends GeneralizingAstVisitor SuperConstructorInvocation node) { var callee = node.staticElement; var nullabilityNode = NullabilityNode.forInferredType(); - var createdType = DecoratedType(callee.returnType, nullabilityNode); + var class_ = node.thisOrAncestorOfType(); + var decoratedSupertype = _decoratedClassHierarchy.getDecoratedSupertype( + class_.declaredElement, callee.enclosingElement); + var typeArguments = decoratedSupertype.typeArguments; + Iterable typeArgumentTypes; + if (typeArguments != null) { + typeArgumentTypes = typeArguments.map((t) => t.type); + } else { + typeArgumentTypes = []; + } + var createdType = DecoratedType(callee.returnType, nullabilityNode, + typeArguments: typeArguments); var calleeType = getOrComputeElementType(callee, targetType: createdType); + var constructorTypeParameters = callee.enclosingElement.typeParameters; + _handleInvocationArguments( node, node.argumentList.arguments, - null /* typeArguments */, - [] /* typeArgumentTypes */, + null /*typeArguments*/, + typeArgumentTypes, calleeType, - [] /* constructorTypeParameters */); + constructorTypeParameters); return null; } @@ -1954,15 +1967,18 @@ class EdgeBuilder extends GeneralizingAstVisitor /// Creates the necessary constraint(s) for an [ArgumentList] when invoking an /// executable element whose type is [calleeType]. /// + /// Only pass [typeArguments] or [typeArgumentTypes] depending on the use + /// case; only one will be used. + /// /// Returns the decorated return type of the invocation, after any necessary /// substitutions. DecoratedType _handleInvocationArguments( AstNode node, Iterable arguments, TypeArgumentList typeArguments, - List typeArgumentTypes, + Iterable typeArgumentTypes, DecoratedType calleeType, - List constructorTypeParameters, + Iterable constructorTypeParameters, {DartType invokeType}) { var typeFormals = constructorTypeParameters ?? calleeType.typeFormals; if (typeFormals.isNotEmpty) { diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart index 1aa5c5bbc2f3..8da44d7c867f 100644 --- a/pkg/nnbd_migration/test/edge_builder_test.dart +++ b/pkg/nnbd_migration/test/edge_builder_test.dart @@ -1665,7 +1665,7 @@ class C { // exception to be thrown. } - test_constructor_withRedirectingSuperInitializer() async { + test_constructor_superInitializer() async { await analyze(''' class C { C.named(int i); @@ -1683,45 +1683,37 @@ class D extends C { hard: true); } - @FailingTest( - reason: 'Need to pass type arguments along in ' - 'EdgeBuilder.visitSuperConstructorInvocation') - test_constructor_withRedirectingSuperInitializer_withTypeArgument() async { + test_constructor_superInitializer_withTypeArgument() async { await analyze(''' class C { - C.named(T i); + C.named(T/*1*/ i); } -class D extends C { - D(int j) : super.named(j); +class D extends C { + D(int/*3*/ j) : super.named(j); } '''); - var namedConstructor = findElement.constructor('named', of: 'C'); - var constructorType = variables.decoratedElementType(namedConstructor); - var constructorParameterType = constructorType.positionalParameters[0]; - assertEdge( - decoratedTypeAnnotation('int j').node, constructorParameterType.node, + var nullable_t1 = decoratedTypeAnnotation('T/*1*/').node; + var nullable_int2 = decoratedTypeAnnotation('int/*2*/').node; + var nullable_int3 = decoratedTypeAnnotation('int/*3*/').node; + assertEdge(nullable_int3, substitutionNode(nullable_int2, nullable_t1), hard: true); } - @FailingTest( - reason: 'Need to pass type arguments along in ' - 'EdgeBuilder.visitSuperConstructorInvocation') - test_constructor_withRedirectingSuperInitializer_withTypeVariable() async { + test_constructor_superInitializer_withTypeVariable() async { await analyze(''' class C { - C.named(T i); + C.named(T/*1*/ i); } -class D extends C { - D(T j) : super.named(j); +class D extends C { + D(U/*3*/ j) : super.named(j); } '''); - var namedConstructor = findElement.constructor('named', of: 'C'); - var constructorType = variables.decoratedElementType(namedConstructor); - var constructorParameterType = constructorType.positionalParameters[0]; - assertEdge( - decoratedTypeAnnotation('int j').node, constructorParameterType.node, + var nullable_t1 = decoratedTypeAnnotation('T/*1*/').node; + var nullable_u2 = decoratedTypeAnnotation('U/*2*/').node; + var nullable_u3 = decoratedTypeAnnotation('U/*3*/').node; + assertEdge(nullable_u3, substitutionNode(nullable_u2, nullable_t1), hard: true); }