Skip to content

Commit bf79e46

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Migration: Add support for synthetic constructors in generic class type aliases.
Change-Id: I8eee88e4dd607623fe109143d01438a5271b3230 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107521 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Paul Berry <[email protected]>
1 parent 0f70ef1 commit bf79e46

4 files changed

Lines changed: 117 additions & 0 deletions

File tree

pkg/nnbd_migration/lib/src/decorated_type.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ class DecoratedType {
146146
} else if (type is FunctionType) {
147147
return DecoratedType.forImplicitFunction(
148148
type, NullabilityNode.forInferredType(), graph);
149+
} else if (type is TypeParameterType) {
150+
return DecoratedType(type, NullabilityNode.forInferredType());
149151
}
150152
// TODO(paulberry)
151153
throw UnimplementedError(

pkg/nnbd_migration/lib/src/edge_builder.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:analyzer/dart/ast/token.dart';
77
import 'package:analyzer/dart/ast/visitor.dart';
88
import 'package:analyzer/dart/element/element.dart';
99
import 'package:analyzer/dart/element/type.dart';
10+
import 'package:analyzer/src/dart/element/handle.dart';
1011
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
1112
import 'package:analyzer/src/dart/element/member.dart';
1213
import 'package:analyzer/src/generated/resolver.dart';
@@ -287,6 +288,9 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType> {
287288
var classElement = node.declaredElement;
288289
var supertype = classElement.supertype;
289290
var superElement = supertype.element;
291+
if (superElement is ClassElementHandle) {
292+
superElement = (superElement as ClassElementHandle).actualElement;
293+
}
290294
for (var constructorElement in classElement.constructors) {
291295
assert(constructorElement.isSynthetic);
292296
var superConstructorElement =

pkg/nnbd_migration/test/edge_builder_test.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,21 @@ D f(MyList<int>/*2*/ x) => D(x);
558558
decoratedTypeAnnotation('int>/*1*/').node);
559559
}
560560

561+
test_class_alias_synthetic_constructor_with_parameters_generic() async {
562+
await analyze('''
563+
class C<T> {
564+
C(T t);
565+
}
566+
mixin M {}
567+
class D<U> = C<U> with M;
568+
''');
569+
var syntheticConstructor = findElement.unnamedConstructor('D');
570+
var constructorType = variables.decoratedElementType(syntheticConstructor);
571+
var constructorParameterType = constructorType.positionalParameters[0];
572+
assertUnion(
573+
constructorParameterType.node, decoratedTypeAnnotation('T t').node);
574+
}
575+
561576
test_class_alias_synthetic_constructor_with_parameters_named() async {
562577
await analyze('''
563578
class C {
@@ -707,6 +722,74 @@ class C {
707722
// exception to be thrown.
708723
}
709724

725+
test_constructorDeclaration_returnType_generic() async {
726+
await analyze('''
727+
class C<T, U> {
728+
C();
729+
}
730+
''');
731+
var constructor = findElement.unnamedConstructor('C');
732+
var constructorDecoratedType = variables.decoratedElementType(constructor);
733+
expect(constructorDecoratedType.type.toString(), 'C<T, U> Function()');
734+
expect(constructorDecoratedType.node, same(never));
735+
expect(constructorDecoratedType.typeFormals, isEmpty);
736+
expect(constructorDecoratedType.returnType.node, same(never));
737+
expect(constructorDecoratedType.returnType.type.toString(), 'C<T, U>');
738+
var typeArguments = constructorDecoratedType.returnType.typeArguments;
739+
expect(typeArguments, hasLength(2));
740+
expect(typeArguments[0].type.toString(), 'T');
741+
expect(typeArguments[0].node, same(never));
742+
expect(typeArguments[1].type.toString(), 'U');
743+
expect(typeArguments[1].node, same(never));
744+
}
745+
746+
test_constructorDeclaration_returnType_generic_implicit() async {
747+
await analyze('''
748+
class C<T, U> {}
749+
''');
750+
var constructor = findElement.unnamedConstructor('C');
751+
var constructorDecoratedType = variables.decoratedElementType(constructor);
752+
expect(constructorDecoratedType.type.toString(), 'C<T, U> Function()');
753+
expect(constructorDecoratedType.node, same(never));
754+
expect(constructorDecoratedType.typeFormals, isEmpty);
755+
expect(constructorDecoratedType.returnType.node, same(never));
756+
expect(constructorDecoratedType.returnType.type.toString(), 'C<T, U>');
757+
var typeArguments = constructorDecoratedType.returnType.typeArguments;
758+
expect(typeArguments, hasLength(2));
759+
expect(typeArguments[0].type.toString(), 'T');
760+
expect(typeArguments[0].node, same(never));
761+
expect(typeArguments[1].type.toString(), 'U');
762+
expect(typeArguments[1].node, same(never));
763+
}
764+
765+
test_constructorDeclaration_returnType_simple() async {
766+
await analyze('''
767+
class C {
768+
C();
769+
}
770+
''');
771+
var constructorDecoratedType =
772+
variables.decoratedElementType(findElement.unnamedConstructor('C'));
773+
expect(constructorDecoratedType.type.toString(), 'C Function()');
774+
expect(constructorDecoratedType.node, same(never));
775+
expect(constructorDecoratedType.typeFormals, isEmpty);
776+
expect(constructorDecoratedType.returnType.node, same(never));
777+
expect(constructorDecoratedType.returnType.typeArguments, isEmpty);
778+
}
779+
780+
test_constructorDeclaration_returnType_simple_implicit() async {
781+
await analyze('''
782+
class C {}
783+
''');
784+
var constructorDecoratedType =
785+
variables.decoratedElementType(findElement.unnamedConstructor('C'));
786+
expect(constructorDecoratedType.type.toString(), 'C Function()');
787+
expect(constructorDecoratedType.node, same(never));
788+
expect(constructorDecoratedType.typeFormals, isEmpty);
789+
expect(constructorDecoratedType.returnType.node, same(never));
790+
expect(constructorDecoratedType.returnType.typeArguments, isEmpty);
791+
}
792+
710793
test_doubleLiteral() async {
711794
await analyze('''
712795
double f() {

pkg/nnbd_migration/test/node_builder_test.dart

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,34 @@ class D = C with M;
127127
expect(dType.namedParameters, isEmpty);
128128
}
129129

130+
test_class_alias_synthetic_constructors_with_parameters_generic() async {
131+
await analyze('''
132+
class C<T> {
133+
C(T t);
134+
}
135+
mixin M {}
136+
class D<U> = C<U> with M;
137+
''');
138+
var cConstructor = findElement.unnamedConstructor('C');
139+
var dConstructor = findElement.unnamedConstructor('D');
140+
var cConstructorType = variables.decoratedElementType(cConstructor);
141+
var dConstructorType = variables.decoratedElementType(dConstructor);
142+
expect(dConstructorType.type.toString(), 'D<U> Function(U)');
143+
expect(dConstructorType.node, same(never));
144+
expect(dConstructorType.typeFormals, isEmpty);
145+
expect(dConstructorType.returnType.type.toString(), 'D<U>');
146+
expect(dConstructorType.returnType.node, same(never));
147+
var typeArguments = dConstructorType.returnType.typeArguments;
148+
expect(typeArguments, hasLength(1));
149+
expect(typeArguments[0].type.toString(), 'U');
150+
expect(typeArguments[0].node, same(never));
151+
var cParams = cConstructorType.positionalParameters;
152+
var dParams = dConstructorType.positionalParameters;
153+
expect(dParams, hasLength(1));
154+
expect(dParams[0].type.toString(), 'U');
155+
expect(dParams[0].node, TypeMatcher<NullabilityNodeMutable>());
156+
}
157+
130158
test_class_with_default_constructor() async {
131159
await analyze('''
132160
class C {}

0 commit comments

Comments
 (0)