blob: 9ef82fc68f6f1f955a5d640479afbc8abf9487a5 [file] [log] [blame]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
import 'dart:developer';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'common/test_helper.dart';
// AUTOGENERATED START
//
// Update these constants by running:
//
// dart pkg/vm_service/test/update_line_numbers.dart <test.dart>
//
const LINE_A = 39;
const LINE_B = 44;
const LINE_C = 50;
// AUTOGENERATED END
class A {}
class B extends A {}
class C extends Object with ListMixin<C> implements List<C> {
@override
int length = 0;
@override
C operator [](int index) => throw UnimplementedError();
@override
void operator []=(int index, C value) {}
}
void testFunction4<T4 extends List<T4>>() {
debugger(); // LINE_A
print('T4 = $T4');
}
void testFunction3<T3, S3 extends T3>() {
debugger(); // LINE_B
print('T3 = $T3');
print('S3 = $S3');
}
void testFunction2<E extends String>(List<E> x) {
debugger(); // LINE_C
print('x = $x');
}
void testFunction() {
testFunction2<String>(<String>['a', 'b', 'c']);
testFunction3<A, B>();
testFunction4<C>();
}
final tests = <IsolateTest>[
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_C),
(VmService service, IsolateRef isolateRef) async {
final isolateId = isolateRef.id!;
{
// Can add List<E extends String> to List<String> directly.
final expression = '''
() {
List<E> y = List<E>.from(["hello"]);
x.addAll(y);
return x.last;
}()
''';
await evaluateInFrameAndExpect(
service,
isolateId,
expression,
'hello',
kind: InstanceKind.kString,
);
}
{
final expression = '''
() {
List<E> y = [];
y.addAll(x);
return y.last;
}()
''';
// Can't add List<String> to List<E extends String> directly.
try {
await service.evaluateInFrame(isolateId, 0, expression);
fail("Can't add List<String> to List<E extends String> directly.");
} on RPCError catch (e) {
expect(e.code, RPCErrorKind.kExpressionCompilationError.code);
expect(
e.details,
contains(
"The argument type '_GrowableList<String>' can't be assigned "
"to the parameter type 'Iterable<E>'",
),
);
}
}
{
// Can add List<String> to List<E extends String> via cast.
final expression = '''
() {
List<E> y = [];
y.addAll(x.cast());
return y.toString();
}()
''';
await evaluateInFrameAndExpect(
service,
isolateId,
expression,
// Notice how "hello" was added a few evaluations back.
'[a, b, c, hello]',
kind: InstanceKind.kString,
);
}
{
// Can create List<String> from List<E extends String>.
final expression = '''
() {
List<E> y = List<E>.from(x);
return y.toString();
}()
''';
await evaluateInFrameAndExpect(
service,
isolateId,
expression,
// Notice how "hello" was added a few evaluations back.
'[a, b, c, hello]',
kind: InstanceKind.kString,
);
}
},
resumeIsolate,
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_B),
(VmService service, IsolateRef isolateRef) async {
// This is just to make sure the VM doesn't crash.
final isolateId = isolateRef.id!;
await evaluateInFrameAndExpect(
service,
isolateId,
'S3.toString()',
'B',
kind: InstanceKind.kString,
);
},
resumeIsolate,
hasStoppedAtBreakpoint,
stoppedAtLine(LINE_A),
(VmService service, IsolateRef isolateRef) async {
// This is just to make sure the VM doesn't crash.
final isolateId = isolateRef.id!;
await evaluateInFrameAndExpect(
service,
isolateId,
'T4.toString()',
'C',
kind: InstanceKind.kString,
);
},
];
void main([args = const <String>[]]) => runIsolateTests(
args,
tests,
'evaluate_type_arguments_test.dart',
testeeConcurrent: testFunction,
);