blob: e63cff394ae4d97daa0cfeb458a11427ec933284 [file] [log] [blame]
// Copyright (c) 2021, 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 'package:dev_compiler/src/compiler/module_builder.dart'
show ModuleFormat;
import 'package:test/test.dart';
import 'expression_compiler_e2e_suite.dart';
void main() async {
var driver = await TestDriver.init();
group('Dart 2.17 language features', () {
tearDownAll(() async {
await driver.finish();
});
group('(Unsound null safety)', () {
group('(AMD module system)', () {
var setup = SetupCompilerOptions(
soundNullSafety: false,
legacyCode: false,
moduleFormat: ModuleFormat.amd);
runSharedTests(setup, driver);
});
group('(DDC module system)', () {
var setup = SetupCompilerOptions(
soundNullSafety: false,
legacyCode: false,
moduleFormat: ModuleFormat.ddc);
runSharedTests(setup, driver);
});
});
group('(Sound null safety)', () {
group('(AMD module system)', () {
var setup = SetupCompilerOptions(
soundNullSafety: true,
legacyCode: false,
moduleFormat: ModuleFormat.amd);
runSharedTests(setup, driver);
});
group('(DDC module system)', () {
var setup = SetupCompilerOptions(
soundNullSafety: true,
legacyCode: false,
moduleFormat: ModuleFormat.ddc);
runSharedTests(setup, driver);
});
});
});
}
/// Shared tests for language features introduced in version 2.17.0.
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
group('Named arguments anywhere', () {
var source = r'''
String topLevelMethod(int param1, String param2,
{int param3 = -1, String param4 = 'default'}) =>
'$param1, $param2, $param3, $param4';
class C {
int param1;
String param2;
int param3;
String param4;
C(this.param1, this.param2,
{this.param3 = -1, this.param4 = 'default'});
static String staticMethod(int param1, String param2,
{int param3 = -1, String param4 = 'default'}) =>
'$param1, $param2, $param3, $param4';
String instanceMethod(int param1, String param2,
{int param3 = -1, String param4 = 'default'}) =>
'$param1, $param2, $param3, $param4';
String toString() => '$param1, $param2, $param3, $param4';
}
main() {
String localMethod(int param1, String param2,
{int param3 = -1, String param4 = 'default'}) =>
'$param1, $param2, $param3, $param4';
var c = C(1, 'two');
// Breakpoint: bp
print('hello world');
}
''';
setUpAll(() async {
await driver.initSource(setup, source, experiments: const {});
});
tearDownAll(() async {
await driver.cleanupTest();
});
test('in top level method', () async {
await driver.check(
breakpointId: 'bp',
expression: 'topLevelMethod(param3: 3, 1, param4: "four", "two")',
expectedResult: '1, two, 3, four');
});
test('in local method', () async {
await driver.check(
breakpointId: 'bp',
expression: 'topLevelMethod(param3: 3, 1, param4: "four", "two")',
expectedResult: '1, two, 3, four');
});
test('in class constructor', () async {
await driver.check(
breakpointId: 'bp',
expression: 'C(param3: 3, 1, param4: "four", "two").toString()',
expectedResult: '1, two, 3, four');
});
test('in class static method', () async {
await driver.check(
breakpointId: 'bp',
expression: 'C.staticMethod(param3: 3, 1, param4: "four", "two")',
expectedResult: '1, two, 3, four');
});
test('in class instance method', () async {
await driver.check(
breakpointId: 'bp',
expression: 'c.instanceMethod(param3: 3, 1, param4: "four", "two")',
expectedResult: '1, two, 3, four');
});
});
group('Super parameters', () {
var source = r'''
class S {
final int i;
final String? s;
final double d;
S(this.i, [this.s]): d = 3.14;
S.named(this.i, {this.d = 3.14}): s = 'default';
}
class C extends S {
final int i1;
final int i2;
C(this.i1, super.i, this.i2, [super.s]);
C.named({super.d}): i1 = 10, i2 = 30, super.named(20);
}
main() {
var c = C(1, 2, 3, 'bar');
var c2 = C.named(d: 2.71);
// Breakpoint: bp
print('hello world');
}
''';
setUpAll(() async {
await driver.initSource(setup, source, experiments: const {});
});
tearDownAll(() async {
await driver.cleanupTest();
});
test('in constructor mixed with regular parameters', () async {
await driver.check(
breakpointId: 'bp', expression: 'c.i1', expectedResult: '1');
await driver.check(
breakpointId: 'bp', expression: 'c.i', expectedResult: '2');
await driver.check(
breakpointId: 'bp', expression: 'c.i2', expectedResult: '3');
await driver.check(
breakpointId: 'bp', expression: 'c.s', expectedResult: 'bar');
await driver.check(
breakpointId: 'bp', expression: 'c.d', expectedResult: '3.14');
});
test('in named constructor mixed with regular parameters', () async {
await driver.check(
breakpointId: 'bp', expression: 'c2.i1', expectedResult: '10');
await driver.check(
breakpointId: 'bp', expression: 'c2.i', expectedResult: '20');
await driver.check(
breakpointId: 'bp', expression: 'c2.i2', expectedResult: '30');
await driver.check(
breakpointId: 'bp', expression: 'c2.s', expectedResult: 'default');
await driver.check(
breakpointId: 'bp', expression: 'c2.d', expectedResult: '2.71');
});
});
group('Enhanced enums', () {
var source = r'''
enum E<T> with M {
id_int<int>(0),
id_bool<bool>(true),
id_string<String>('hello world', n: 13);
final T field;
final num n;
static const constStaticField = id_string;
const E(T arg0, {num? n}) : this.field = arg0, this.n = n ?? 42;
T get fieldGetter => field;
num instanceMethod() => n;
}
enum E2 with M {
v1, v2, id_string;
}
mixin M on Enum {
int mixinMethod() => index * 100;
}
main() {
var e = E.id_string;
// Breakpoint: bp
print('hello world');
}
''';
setUpAll(() async {
await driver.initSource(setup, source, experiments: const {});
});
tearDownAll(() async {
await driver.cleanupTest();
});
test('evaluate to the correct string', () async {
await driver.check(
breakpointId: 'bp',
expression: 'E.id_string.toString()',
expectedResult: 'E.id_string');
});
test('evaluate to the correct index', () async {
await driver.check(
breakpointId: 'bp',
expression: 'E.id_string.index',
expectedResult: '2');
});
test('compare properly against themselves', () async {
await driver.check(
breakpointId: 'bp',
expression: 'e == E.id_string && E.id_string == E.id_string',
expectedResult: 'true');
});
test('compare properly against other enums', () async {
await driver.check(
breakpointId: 'bp',
expression: 'e != E2.id_string && E.id_string != E2.id_string',
expectedResult: 'true');
});
test('with instance methods', () async {
await driver.check(
breakpointId: 'bp',
expression: 'E.id_bool.instanceMethod()',
expectedResult: '42');
});
test('with instance methods from local instance', () async {
await driver.check(
breakpointId: 'bp',
expression: 'e.instanceMethod()',
expectedResult: '13');
});
test('with getters', () async {
await driver.check(
breakpointId: 'bp',
expression: 'E.id_int.fieldGetter',
expectedResult: '0');
});
test('with getters from local instance', () async {
await driver.check(
breakpointId: 'bp',
expression: 'e.fieldGetter',
expectedResult: 'hello world');
});
test('with mixin calls', () async {
await driver.check(
breakpointId: 'bp',
expression: 'E.id_string.mixinMethod()',
expectedResult: '200');
});
test('with mixin calls through overridden indices', () async {
await driver.check(
breakpointId: 'bp',
expression: 'E2.v2.mixinMethod()',
expectedResult: '100');
});
});
}