mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[ddc] Clean up expression compiler tests
- Allow running the tests with asserts enabled - Allow running the tests in canary mode - Unify common test code and remove duplication - merge expression_compiler/setup_compiler_options.dart into share_compiler_options.dart - Merge TestCompiler code from expression evaluation and expression compilation tests and move into expression_compiler/test_compiler.dart - Rename various TestDrivers so they have more descriptive names - Remove 'golden' JS comparison tests from expression_compiler_test.dart - replace by evaluation tests where needed Closes: https://github.com/dart-lang/sdk/issues/53145 Change-Id: Ic797fa4ee9bfa6b858b924be9f9a53fd10ae1448 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/318080 Commit-Queue: Anna Gringauze <annagrin@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
286e5761e3
commit
67d752aa12
|
@ -35,5 +35,4 @@ dev_dependencies:
|
|||
stack_trace: any
|
||||
test: any
|
||||
testing: any
|
||||
vm: any
|
||||
webkit_inspection_protocol: any
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
var setup = SetupCompilerOptions(args: args);
|
||||
|
||||
group('Assertions |', () {
|
||||
group('Asserts', () {
|
||||
const source = r'''
|
||||
void main() {
|
||||
var b = const bool.fromEnvironment('dart.web.assertions_enabled');
|
||||
|
@ -24,60 +25,66 @@ void main(List<String> args) async {
|
|||
}
|
||||
''';
|
||||
|
||||
tearDown(() async {
|
||||
await driver.cleanupTest();
|
||||
});
|
||||
|
||||
setUpAll(() => driver.initSource(setup, source));
|
||||
tearDownAll(() async {
|
||||
await driver.cleanupTest();
|
||||
await driver.finish();
|
||||
});
|
||||
|
||||
test('dart.web.assertions_enabled is set when asserts are enabled',
|
||||
() async {
|
||||
var setup = SetupCompilerOptions(args: args);
|
||||
await driver.initSource(setup, source);
|
||||
if (setup.enableAsserts) {
|
||||
group('enabled |', () {
|
||||
test('dart.web.assertions_enabled is set', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'bp', expression: 'b', expectedResult: 'true');
|
||||
});
|
||||
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: 'b',
|
||||
expectedResult: '${setup.enableAsserts}');
|
||||
});
|
||||
|
||||
test('assert errors in the source code when asserts are enabled', () async {
|
||||
var setup = SetupCompilerOptions(args: args);
|
||||
await driver.initSource(setup, source);
|
||||
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: 'myAssert()',
|
||||
expectedResult: setup.enableAsserts
|
||||
? allOf(
|
||||
test('assert errors in the source code', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: 'myAssert()',
|
||||
expectedResult: allOf(
|
||||
contains('Error: Assertion failed:'),
|
||||
contains('test.dart:8:16'),
|
||||
contains('false'),
|
||||
contains('is not true'),
|
||||
)
|
||||
: '0',
|
||||
);
|
||||
});
|
||||
));
|
||||
});
|
||||
|
||||
test('assert errors in evaluated expression when asserts are enabled',
|
||||
() async {
|
||||
var setup = SetupCompilerOptions(args: args);
|
||||
await driver.initSource(setup, source);
|
||||
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: '() { assert(false); return 0; } ()',
|
||||
expectedResult: setup.enableAsserts
|
||||
? allOf(
|
||||
test('assert errors in evaluated expression', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: '() { assert(false); return 0; } ()',
|
||||
expectedResult: allOf(
|
||||
contains('Error: Assertion failed:'),
|
||||
contains('<unknown source>:-1:-1'),
|
||||
contains('BoolLiteral(false)'),
|
||||
contains('is not true'),
|
||||
)
|
||||
: '0',
|
||||
);
|
||||
});
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!setup.enableAsserts) {
|
||||
group('disabled |', () {
|
||||
test('dart.web.assertions_enabled is not set', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'bp', expression: 'b', expectedResult: 'false');
|
||||
});
|
||||
|
||||
test('no assert errors in the source code', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: 'myAssert()',
|
||||
expectedResult: '0');
|
||||
});
|
||||
|
||||
test('no assert errors in evaluated expression', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'bp',
|
||||
expression: '() { assert(false); return 0; } ()',
|
||||
expectedResult: '0');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,13 +6,15 @@ import 'dart:io';
|
|||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
var setup = SetupCompilerOptions(args: args);
|
||||
var mode = setup.canaryFeatures ? 'canary' : 'stable';
|
||||
|
||||
group('canary', () {
|
||||
group('$mode mode', () {
|
||||
const source = r'''
|
||||
void main() {
|
||||
print('hello world');
|
||||
|
@ -28,7 +30,6 @@ void main(List<String> args) async {
|
|||
});
|
||||
|
||||
test('is automatically set to the configuration value', () async {
|
||||
var setup = SetupCompilerOptions(args: args);
|
||||
await driver.initSource(setup, source);
|
||||
|
||||
expect(
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Sound null safety) (Agnostic code shard 1)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Sound null safety) (Agnostic code shard 2)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Unsound null safety) (Agnostic code shard 1)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Unsound null safety) (Agnostic code shard 2)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Legacy code shard 1)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Legacy code shard 2)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,14 +6,14 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
// Set to `true` for debug output.
|
||||
final debug = false;
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Sound null safety)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Unsound null safety)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,11 +6,11 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('Dart 2.17 language features', () {
|
||||
tearDownAll(() async {
|
||||
|
@ -64,7 +64,8 @@ void main(List<String> args) async {
|
|||
}
|
||||
|
||||
/// Shared tests for language features introduced in version 2.17.0.
|
||||
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
||||
void runSharedTests(
|
||||
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||
group('Named arguments anywhere', () {
|
||||
var source = r'''
|
||||
String topLevelMethod(int param1, String param2,
|
||||
|
|
|
@ -6,11 +6,11 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('Dart 3.0 language features', () {
|
||||
tearDownAll(() async {
|
||||
|
@ -64,7 +64,8 @@ void main(List<String> args) async {
|
|||
}
|
||||
|
||||
/// Shared tests for language features introduced in version 3.0.0.
|
||||
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
||||
void runSharedTests(
|
||||
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||
group('Records', () {
|
||||
const recordsSource = '''
|
||||
void main() {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Sound null safety) (Agnostic code shard 1)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Sound null safety) (Agnostic code shard 2)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Unsound null safety) (Agnostic code shard 1)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Unsound null safety) (Agnostic code shard 2)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Legacy code shard 1)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Legacy code shard 2)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Sound null safety)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -6,12 +6,12 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_shared.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
group('(Unsound null safety)', () {
|
||||
tearDownAll(() async {
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
const simpleClassSource = '''
|
||||
extension NumberParsing on String {
|
||||
|
@ -64,7 +64,8 @@ main() {
|
|||
/// Shared tests that require a language version >=2.12.0 <2.17.0.
|
||||
// TODO(nshahan) Merge with [runAgnosticSharedTests] after we no longer need to
|
||||
// test support for evaluation in legacy (pre-null safety) code.
|
||||
void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
||||
void runNullSafeSharedTests(
|
||||
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||
group('Exceptions', () {
|
||||
const exceptionSource = r'''
|
||||
void main() {
|
||||
|
@ -207,6 +208,17 @@ void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
|||
expectedResult: 'test.C.new { Symbol(_unusedField): 4, '
|
||||
'Symbol(C.field): 42, Symbol(_field): 0}');
|
||||
});
|
||||
|
||||
test('map access', () async {
|
||||
await driver.check(
|
||||
breakpointId: 'methodBP',
|
||||
expression: '''
|
||||
(Map<String, String> params) {
|
||||
return params["a"];
|
||||
}({"a":"b"})
|
||||
''',
|
||||
expectedResult: 'b');
|
||||
});
|
||||
});
|
||||
|
||||
group('Expression compiler tests in global function:', () {
|
||||
|
@ -470,7 +482,7 @@ void runNullSafeSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
|||
/// This group of tests has been sharded manually. The others are in
|
||||
/// [runAgnosticSharedTestsShard2].
|
||||
void runAgnosticSharedTestsShard1(
|
||||
SetupCompilerOptions setup, TestDriver driver) {
|
||||
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||
group('Correct null safety mode used', () {
|
||||
var source = '''
|
||||
const soundNullSafety = !(<Null>[] is List<int>);
|
||||
|
@ -956,7 +968,7 @@ void runAgnosticSharedTestsShard1(
|
|||
/// This group of tests has been sharded manually. The others are in
|
||||
/// [runAgnosticSharedTestsShard1].
|
||||
void runAgnosticSharedTestsShard2(
|
||||
SetupCompilerOptions setup, TestDriver driver) {
|
||||
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||
group('Expression compiler tests in constructor:', () {
|
||||
var source = simpleClassSource;
|
||||
|
||||
|
|
|
@ -10,182 +10,20 @@ import 'dart:math';
|
|||
import 'package:async/async.dart';
|
||||
import 'package:browser_launcher/browser_launcher.dart' as browser;
|
||||
import 'package:dev_compiler/src/compiler/module_builder.dart';
|
||||
import 'package:dev_compiler/src/compiler/shared_command.dart'
|
||||
show SharedCompilerOptions;
|
||||
import 'package:dev_compiler/src/kernel/command.dart';
|
||||
import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler;
|
||||
import 'package:dev_compiler/src/kernel/expression_compiler.dart'
|
||||
show ExpressionCompiler;
|
||||
import 'package:dev_compiler/src/kernel/module_metadata.dart';
|
||||
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
||||
import 'package:front_end/src/fasta/incremental_serializer.dart' as fe;
|
||||
import 'package:kernel/ast.dart' show Component, Library;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_maps/source_maps.dart' as source_maps;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'
|
||||
as wip;
|
||||
|
||||
import 'setup_compiler_options.dart';
|
||||
import '../shared_test_options.dart';
|
||||
import 'test_compiler.dart';
|
||||
|
||||
class DevelopmentIncrementalCompiler extends fe.IncrementalCompiler {
|
||||
Uri entryPoint;
|
||||
|
||||
DevelopmentIncrementalCompiler(fe.CompilerOptions options, this.entryPoint,
|
||||
[Uri? initializeFrom,
|
||||
bool? outlineOnly,
|
||||
fe.IncrementalSerializer? incrementalSerializer])
|
||||
: super(
|
||||
fe.CompilerContext(
|
||||
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||
initializeFrom,
|
||||
outlineOnly,
|
||||
incrementalSerializer);
|
||||
|
||||
DevelopmentIncrementalCompiler.fromComponent(fe.CompilerOptions options,
|
||||
this.entryPoint, Component componentToInitializeFrom,
|
||||
[bool? outlineOnly, fe.IncrementalSerializer? incrementalSerializer])
|
||||
: super.fromComponent(
|
||||
fe.CompilerContext(
|
||||
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||
componentToInitializeFrom,
|
||||
outlineOnly,
|
||||
incrementalSerializer);
|
||||
}
|
||||
|
||||
class TestCompilationResult {
|
||||
final String? result;
|
||||
final bool isSuccess;
|
||||
|
||||
TestCompilationResult(this.result, this.isSuccess);
|
||||
}
|
||||
|
||||
class TestCompiler {
|
||||
final SetupCompilerOptions setup;
|
||||
final Component component;
|
||||
final ExpressionCompiler evaluator;
|
||||
final ModuleMetadata? metadata;
|
||||
final source_maps.SingleMapping sourceMap;
|
||||
|
||||
TestCompiler._(this.setup, this.component, this.evaluator, this.metadata,
|
||||
this.sourceMap);
|
||||
|
||||
static Future<TestCompiler> init(SetupCompilerOptions setup,
|
||||
{required Uri input,
|
||||
required Uri output,
|
||||
Uri? packages,
|
||||
Map<String, bool> experiments = const {}}) async {
|
||||
// Initialize the incremental compiler and module component.
|
||||
// TODO: extend this for multi-module compilations by storing separate
|
||||
// compilers/components/names per module.
|
||||
setup.options.packagesFileUri = packages;
|
||||
setup.options.explicitExperimentalFlags.addAll(fe.parseExperimentalFlags(
|
||||
experiments,
|
||||
onError: (message) => throw Exception(message)));
|
||||
var compiler = DevelopmentIncrementalCompiler(setup.options, input);
|
||||
var compilerResult = await compiler.computeDelta();
|
||||
var component = compilerResult.component;
|
||||
component.computeCanonicalNames();
|
||||
// Initialize DDC.
|
||||
var moduleName = p.basenameWithoutExtension(output.toFilePath());
|
||||
|
||||
var classHierarchy = compilerResult.classHierarchy!;
|
||||
var compilerOptions = SharedCompilerOptions(
|
||||
replCompile: true,
|
||||
moduleName: moduleName,
|
||||
experiments: experiments,
|
||||
soundNullSafety: setup.soundNullSafety,
|
||||
emitDebugMetadata: true,
|
||||
canaryFeatures: setup.canaryFeatures,
|
||||
enableAsserts: setup.enableAsserts,
|
||||
);
|
||||
var coreTypes = compilerResult.coreTypes;
|
||||
|
||||
final importToSummary = Map<Library, Component>.identity();
|
||||
final summaryToModule = Map<Component, String>.identity();
|
||||
for (var lib in component.libraries) {
|
||||
importToSummary[lib] = component;
|
||||
}
|
||||
summaryToModule[component] = moduleName;
|
||||
|
||||
var kernel2jsCompiler = ProgramCompiler(component, classHierarchy,
|
||||
compilerOptions, importToSummary, summaryToModule,
|
||||
coreTypes: coreTypes);
|
||||
var module = kernel2jsCompiler.emitModule(component);
|
||||
|
||||
// Perform a full compile, writing the compiled JS + sourcemap.
|
||||
var code = jsProgramToCode(
|
||||
module,
|
||||
setup.moduleFormat,
|
||||
inlineSourceMap: compilerOptions.inlineSourceMap,
|
||||
buildSourceMap: compilerOptions.sourceMap,
|
||||
emitDebugMetadata: compilerOptions.emitDebugMetadata,
|
||||
emitDebugSymbols: compilerOptions.emitDebugSymbols,
|
||||
jsUrl: '$output',
|
||||
mapUrl: '$output.map',
|
||||
compiler: kernel2jsCompiler,
|
||||
component: component,
|
||||
);
|
||||
var codeBytes = utf8.encode(code.code);
|
||||
var sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
|
||||
|
||||
File(output.toFilePath()).writeAsBytesSync(codeBytes);
|
||||
File('${output.toFilePath()}.map').writeAsBytesSync(sourceMapBytes);
|
||||
|
||||
// Save the expression evaluator for future evaluations.
|
||||
var evaluator = ExpressionCompiler(
|
||||
setup.options,
|
||||
setup.moduleFormat,
|
||||
setup.errors,
|
||||
compiler,
|
||||
kernel2jsCompiler,
|
||||
component,
|
||||
);
|
||||
|
||||
if (setup.errors.isNotEmpty) {
|
||||
throw Exception('Compilation failed with: ${setup.errors}');
|
||||
}
|
||||
setup.diagnosticMessages.clear();
|
||||
|
||||
var sourceMap = source_maps.SingleMapping.fromJson(
|
||||
code.sourceMap!.cast<String, dynamic>());
|
||||
return TestCompiler._(
|
||||
setup, component, evaluator, code.metadata, sourceMap);
|
||||
}
|
||||
|
||||
Future<TestCompilationResult> compileExpression(
|
||||
{required Uri input,
|
||||
required int line,
|
||||
required int column,
|
||||
required Map<String, String> scope,
|
||||
required String expression}) async {
|
||||
var libraryUri = metadataForLibraryUri(input);
|
||||
var jsExpression = await evaluator.compileExpressionToJs(
|
||||
libraryUri.importUri, line, column, scope, expression);
|
||||
if (setup.errors.isNotEmpty) {
|
||||
jsExpression = setup.errors.toString().replaceAll(
|
||||
RegExp(
|
||||
r'org-dartlang-debug:synthetic_debug_expression:[0-9]*:[0-9]*:'),
|
||||
'');
|
||||
|
||||
return TestCompilationResult(jsExpression, false);
|
||||
}
|
||||
|
||||
return TestCompilationResult(jsExpression, true);
|
||||
}
|
||||
|
||||
LibraryMetadata metadataForLibraryUri(Uri libraryUri) =>
|
||||
metadata!.libraries.entries
|
||||
.firstWhere((entry) => entry.value.fileUri == '$libraryUri')
|
||||
.value;
|
||||
}
|
||||
|
||||
class TestDriver {
|
||||
class ExpressionEvaluationTestDriver {
|
||||
final browser.Chrome chrome;
|
||||
final Directory chromeDir;
|
||||
final wip.WipConnection connection;
|
||||
final wip.WipDebugger debugger;
|
||||
late TestCompiler compiler;
|
||||
late TestExpressionCompiler compiler;
|
||||
late Uri htmlBootstrapper;
|
||||
late Uri input;
|
||||
late Uri output;
|
||||
|
@ -196,10 +34,11 @@ class TestDriver {
|
|||
late Directory testDir;
|
||||
late String dartSdkPath;
|
||||
|
||||
TestDriver._(this.chrome, this.chromeDir, this.connection, this.debugger);
|
||||
ExpressionEvaluationTestDriver._(
|
||||
this.chrome, this.chromeDir, this.connection, this.debugger);
|
||||
|
||||
/// Initializes a Chrome browser instance, tab connection, and debugger.
|
||||
static Future<TestDriver> init() async {
|
||||
static Future<ExpressionEvaluationTestDriver> init() async {
|
||||
// Create a temporary directory for holding Chrome tests.
|
||||
var chromeDir = Directory.systemTemp.createTempSync('ddc_eval_test_anchor');
|
||||
|
||||
|
@ -243,7 +82,8 @@ class TestDriver {
|
|||
var debugger = connection.debugger;
|
||||
await debugger.enable().timeout(Duration(seconds: 5),
|
||||
onTimeout: (() => throw Exception('Unable to enable WIP debugger')));
|
||||
return TestDriver._(chrome, chromeDir, connection, debugger);
|
||||
return ExpressionEvaluationTestDriver._(
|
||||
chrome, chromeDir, connection, debugger);
|
||||
}
|
||||
|
||||
/// Must be called when testing a new Dart program.
|
||||
|
@ -288,7 +128,7 @@ class TestDriver {
|
|||
''');
|
||||
|
||||
// Initialize DDC and the incremental compiler, then perform a full compile.
|
||||
compiler = await TestCompiler.init(setup,
|
||||
compiler = await TestExpressionCompiler.init(setup,
|
||||
input: input,
|
||||
output: output,
|
||||
packages: packagesFile,
|
||||
|
@ -660,14 +500,10 @@ class TestDriver {
|
|||
}) async {
|
||||
var frame = event.getCallFrames().first;
|
||||
|
||||
var loadModule = setup.moduleFormat == ModuleFormat.amd
|
||||
? 'require'
|
||||
: 'dart_library.import';
|
||||
|
||||
var jsExpression = '''
|
||||
(function () {
|
||||
try {
|
||||
var sdk = $loadModule('dart_sdk');
|
||||
var sdk = ${setup.loadModule}('dart_sdk');
|
||||
var dart = sdk.dart;
|
||||
var interceptors = sdk._interceptors;
|
||||
return $expression;
|
||||
|
@ -685,23 +521,28 @@ class TestDriver {
|
|||
);
|
||||
}
|
||||
|
||||
Future<TestCompilationResult> _compileDartExpression(
|
||||
wip.WipCallFrame frame, String expression, int dartLine) async {
|
||||
// Retrieve the call frame and its scope variables.
|
||||
var scope = await _collectScopeVariables(frame);
|
||||
|
||||
// Perform an incremental compile.
|
||||
return await compiler.compileExpression(
|
||||
input: input,
|
||||
line: dartLine,
|
||||
column: 1,
|
||||
scope: scope,
|
||||
expression: expression);
|
||||
}
|
||||
|
||||
Future<wip.RemoteObject> _evaluateDartExpression(
|
||||
wip.DebuggerPausedEvent event,
|
||||
String expression,
|
||||
int dartLine, {
|
||||
bool returnByValue = false,
|
||||
}) async {
|
||||
// Retrieve the call frame and its scope variables.
|
||||
var frame = event.getCallFrames().first;
|
||||
var scope = await _collectScopeVariables(frame);
|
||||
|
||||
// Perform an incremental compile.
|
||||
var result = await compiler.compileExpression(
|
||||
input: input,
|
||||
line: dartLine,
|
||||
column: 1,
|
||||
scope: scope,
|
||||
expression: expression);
|
||||
var result = await _compileDartExpression(frame, expression, dartLine);
|
||||
|
||||
if (!result.isSuccess) {
|
||||
setup.diagnosticMessages.clear();
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
// 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:io' show Directory, File;
|
||||
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'test_compiler.dart';
|
||||
|
||||
class ExpressionCompilerTestDriver {
|
||||
final SetupCompilerOptions setup;
|
||||
late Directory testDir;
|
||||
String source;
|
||||
late Uri input;
|
||||
late Uri output;
|
||||
late Uri packages;
|
||||
late int line;
|
||||
|
||||
ExpressionCompilerTestDriver(this.setup, this.source) {
|
||||
source = '${setup.dartLangComment}\n\n$source';
|
||||
line = _getEvaluationLine(source);
|
||||
var systemTempDir = Directory.systemTemp;
|
||||
testDir = systemTempDir.createTempSync('foo bar');
|
||||
|
||||
output = testDir.uri.resolve('test.js');
|
||||
input = testDir.uri.resolve('test.dart');
|
||||
File.fromUri(input)
|
||||
..createSync()
|
||||
..writeAsStringSync(source);
|
||||
|
||||
packages = testDir.uri.resolve('package_config.json');
|
||||
File.fromUri(packages)
|
||||
..createSync()
|
||||
..writeAsStringSync('''
|
||||
{
|
||||
"configVersion": 2,
|
||||
"packages": [
|
||||
{
|
||||
"name": "foo",
|
||||
"rootUri": "./",
|
||||
"packageUri": "./"
|
||||
}
|
||||
]
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
void delete() {
|
||||
testDir.deleteSync(recursive: true);
|
||||
}
|
||||
|
||||
Future<TestExpressionCompiler> createCompiler() =>
|
||||
TestExpressionCompiler.init(setup,
|
||||
input: input, output: output, packages: packages);
|
||||
|
||||
Future<TestCompilationResult> compile({
|
||||
required TestExpressionCompiler compiler,
|
||||
required Map<String, String> scope,
|
||||
required String expression,
|
||||
}) async {
|
||||
return compiler.compileExpression(
|
||||
input: input,
|
||||
line: line,
|
||||
column: 1,
|
||||
scope: scope,
|
||||
expression: expression);
|
||||
}
|
||||
|
||||
void checkResult(
|
||||
TestCompilationResult result, {
|
||||
String? expectedError,
|
||||
dynamic expectedResult,
|
||||
}) {
|
||||
var success = expectedError == null;
|
||||
var message = success ? expectedResult! : expectedError;
|
||||
|
||||
expect(
|
||||
result,
|
||||
const TypeMatcher<TestCompilationResult>()
|
||||
.having((r) => r.result!, 'result', _matches(message))
|
||||
.having((r) => r.isSuccess, 'isSuccess', success));
|
||||
}
|
||||
|
||||
Future<void> check({
|
||||
TestExpressionCompiler? compiler,
|
||||
required Map<String, String> scope,
|
||||
required String expression,
|
||||
String? expectedError,
|
||||
dynamic expectedResult,
|
||||
}) async {
|
||||
compiler ??= await createCompiler();
|
||||
var result =
|
||||
await compile(compiler: compiler, scope: scope, expression: expression);
|
||||
|
||||
checkResult(result,
|
||||
expectedError: expectedError, expectedResult: expectedResult);
|
||||
}
|
||||
|
||||
Matcher _matches(dynamic matcher) {
|
||||
if (matcher is Matcher) return matcher;
|
||||
if (matcher is! String) throw StateError('Unsupported matcher $matcher');
|
||||
|
||||
var unIndented = RegExp.escape(matcher).replaceAll(RegExp('[ ]+'), '[ ]*');
|
||||
return matches(RegExp(unIndented, multiLine: true));
|
||||
}
|
||||
|
||||
static int _getEvaluationLine(String source) {
|
||||
var placeholderRegExp = RegExp(r'// Breakpoint');
|
||||
|
||||
var lines = source.split('\n');
|
||||
for (var line = 0; line < lines.length; line++) {
|
||||
var content = lines[line];
|
||||
if (placeholderRegExp.firstMatch(content) != null) {
|
||||
return line + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -2,284 +2,21 @@
|
|||
// 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:io' show Directory, File;
|
||||
|
||||
import 'package:dev_compiler/src/compiler/js_names.dart';
|
||||
import 'package:dev_compiler/src/compiler/module_builder.dart';
|
||||
import 'package:dev_compiler/src/compiler/shared_command.dart'
|
||||
show SharedCompilerOptions;
|
||||
import 'package:dev_compiler/src/js_ast/js_ast.dart';
|
||||
import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler;
|
||||
import 'package:dev_compiler/src/kernel/expression_compiler.dart'
|
||||
show ExpressionCompiler;
|
||||
import 'package:kernel/ast.dart' show Component, Library;
|
||||
import 'package:test/test.dart';
|
||||
import 'package:vm/transformations/type_flow/utils.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_suite.dart';
|
||||
|
||||
// TODO(annagrin): Replace javascript matching in tests below with evaluating
|
||||
// the javascript and checking the result.
|
||||
// See https://github.com/dart-lang/sdk/issues/41959
|
||||
|
||||
/// Convenience class describing JavaScript module
|
||||
/// to ensure we have normalized module names
|
||||
class Module {
|
||||
/// variable name used in JavaScript output to load the module
|
||||
/// example: file
|
||||
final String name;
|
||||
|
||||
/// JavaScript module name used in trackLibraries
|
||||
/// example: packages/package/file.dart
|
||||
final String path;
|
||||
|
||||
/// URI where the contents of the library that produces this module
|
||||
/// can be found
|
||||
/// example: /Users/../package/file.dart
|
||||
final Uri fileUri;
|
||||
|
||||
/// Import URI for the library that generates this module.
|
||||
/// example: packages:package/file.dart
|
||||
final Uri importUri;
|
||||
|
||||
Module(this.importUri, this.fileUri)
|
||||
: name = libraryUriToJsIdentifier(importUri),
|
||||
path = importUri.isScheme('package')
|
||||
? 'packages/${importUri.path}'
|
||||
: importUri.path;
|
||||
|
||||
String get package => importUri.toString();
|
||||
String get file => fileUri.path;
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'Name: \$name, File: \$file, Package: \$package, path: \$path';
|
||||
}
|
||||
|
||||
class TestCompilationResult {
|
||||
final String result;
|
||||
final bool isSuccess;
|
||||
|
||||
TestCompilationResult(this.result, this.isSuccess);
|
||||
}
|
||||
|
||||
class TestCompiler {
|
||||
final SetupCompilerOptions setup;
|
||||
final Map<Uri, Module> _modules = {};
|
||||
late final ExpressionCompiler compiler;
|
||||
|
||||
TestCompiler._(this.setup);
|
||||
|
||||
static Future<TestCompiler> create(
|
||||
SetupCompilerOptions setup, Uri input, Uri packages) async {
|
||||
final testCompiler = TestCompiler._(setup);
|
||||
await testCompiler._createCompiler(input, packages);
|
||||
return testCompiler;
|
||||
}
|
||||
|
||||
Future<TestCompilationResult> compile(
|
||||
{required Uri input,
|
||||
required int line,
|
||||
required int column,
|
||||
required Map<String, String> scope,
|
||||
required String expression}) async {
|
||||
// clear previous errors
|
||||
setup.errors.clear();
|
||||
|
||||
// compile
|
||||
var jsExpression = await compiler.compileExpressionToJs(
|
||||
_libraryUriFor(input), line, column, scope, expression);
|
||||
|
||||
if (setup.errors.isNotEmpty) {
|
||||
jsExpression = setup.errors.toString().replaceAll(
|
||||
RegExp(
|
||||
r'org-dartlang-debug:synthetic_debug_expression:[0-9]*:[0-9]*:'),
|
||||
'');
|
||||
|
||||
return TestCompilationResult(jsExpression, false);
|
||||
}
|
||||
|
||||
return TestCompilationResult(jsExpression!, true);
|
||||
}
|
||||
|
||||
Future<void> _createCompiler(Uri input, Uri packages) async {
|
||||
// initialize incremental compiler and create component
|
||||
setup.options.packagesFileUri = packages;
|
||||
var frontend = DevelopmentIncrementalCompiler(setup.options, input);
|
||||
var compilerResult = await frontend.computeDelta();
|
||||
var component = compilerResult.component;
|
||||
component.computeCanonicalNames();
|
||||
|
||||
// initialize ddc
|
||||
var moduleName = 'foo.dart';
|
||||
var classHierarchy = compilerResult.classHierarchy;
|
||||
var compilerOptions = SharedCompilerOptions(
|
||||
replCompile: true,
|
||||
moduleName: moduleName,
|
||||
soundNullSafety: setup.soundNullSafety,
|
||||
moduleFormats: [setup.moduleFormat],
|
||||
canaryFeatures: false,
|
||||
);
|
||||
var coreTypes = compilerResult.coreTypes;
|
||||
|
||||
final importToSummary = Map<Library, Component>.identity();
|
||||
final summaryToModule = Map<Component, String>.identity();
|
||||
for (var lib in component.libraries) {
|
||||
importToSummary[lib] = component;
|
||||
}
|
||||
summaryToModule[component] = moduleName;
|
||||
|
||||
var kernel2jsCompiler = ProgramCompiler(component, classHierarchy!,
|
||||
compilerOptions, importToSummary, summaryToModule,
|
||||
coreTypes: coreTypes);
|
||||
var moduleTree = kernel2jsCompiler.emitModule(component);
|
||||
|
||||
{
|
||||
var opts = JavaScriptPrintingOptions(
|
||||
allowKeywordsInProperties: true, allowSingleLineIfStatements: true);
|
||||
var printer = SimpleJavaScriptPrintingContext();
|
||||
|
||||
var tree = transformModuleFormat(setup.moduleFormat, moduleTree);
|
||||
tree.accept(Printer(opts, printer, localNamer: TemporaryNamer(tree)));
|
||||
var printed = printer.getText();
|
||||
debugPrint(printed);
|
||||
}
|
||||
|
||||
_collectModules(component);
|
||||
|
||||
// create expression compiler
|
||||
compiler = ExpressionCompiler(
|
||||
setup.options,
|
||||
setup.moduleFormat,
|
||||
setup.errors,
|
||||
frontend,
|
||||
kernel2jsCompiler,
|
||||
component,
|
||||
);
|
||||
}
|
||||
|
||||
void _collectModules(Component component) {
|
||||
for (var library in component.libraries) {
|
||||
_modules[library.fileUri] = Module(library.importUri, library.fileUri);
|
||||
}
|
||||
}
|
||||
|
||||
String _libraryUriFor(Uri input) => _modules[input]!.package;
|
||||
}
|
||||
|
||||
class TestDriver {
|
||||
final SetupCompilerOptions options;
|
||||
late Directory tempDir;
|
||||
final String source;
|
||||
late Uri input;
|
||||
late Uri packages;
|
||||
late File file;
|
||||
int line;
|
||||
|
||||
TestDriver(this.options, this.source) : line = _getEvaluationLine(source) {
|
||||
var systemTempDir = Directory.systemTemp;
|
||||
tempDir = systemTempDir.createTempSync('foo bar');
|
||||
|
||||
input = tempDir.uri.resolve('foo.dart');
|
||||
file = File.fromUri(input)..createSync();
|
||||
file.writeAsStringSync(source);
|
||||
|
||||
packages = tempDir.uri.resolve('package_config.json');
|
||||
file = File.fromUri(packages)..createSync();
|
||||
file.writeAsStringSync('''
|
||||
{
|
||||
"configVersion": 2,
|
||||
"packages": [
|
||||
{
|
||||
"name": "foo",
|
||||
"rootUri": "./",
|
||||
"packageUri": "./"
|
||||
}
|
||||
]
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
void delete() {
|
||||
tempDir.delete(recursive: true);
|
||||
}
|
||||
|
||||
Future<TestCompiler> createCompiler() =>
|
||||
TestCompiler.create(options, input, packages);
|
||||
|
||||
Future<TestCompilationResult> compile({
|
||||
required TestCompiler compiler,
|
||||
required Map<String, String> scope,
|
||||
required String expression,
|
||||
}) async {
|
||||
return compiler.compile(
|
||||
input: input,
|
||||
line: line,
|
||||
column: 1,
|
||||
scope: scope,
|
||||
expression: expression);
|
||||
}
|
||||
|
||||
void checkResult(
|
||||
TestCompilationResult result, {
|
||||
String? expectedError,
|
||||
String? expectedResult,
|
||||
}) {
|
||||
var success = expectedError == null;
|
||||
var message = success ? expectedResult! : expectedError;
|
||||
|
||||
expect(
|
||||
result,
|
||||
const TypeMatcher<TestCompilationResult>()
|
||||
.having((r) => _normalize(r.result), 'result', _matches(message))
|
||||
.having((r) => r.isSuccess, 'isSuccess', success));
|
||||
}
|
||||
|
||||
Future<void> check({
|
||||
TestCompiler? compiler,
|
||||
required Map<String, String> scope,
|
||||
required String expression,
|
||||
String? expectedError,
|
||||
String? expectedResult,
|
||||
}) async {
|
||||
compiler ??= await createCompiler();
|
||||
var result =
|
||||
await compile(compiler: compiler, scope: scope, expression: expression);
|
||||
|
||||
checkResult(result,
|
||||
expectedError: expectedError, expectedResult: expectedResult);
|
||||
}
|
||||
|
||||
String _normalize(String text) {
|
||||
return text
|
||||
.replaceAll(RegExp('\'.*foo.dart\''), '\'foo.dart\'')
|
||||
.replaceAll(RegExp('".*foo.dart"'), '\'foo.dart\'');
|
||||
}
|
||||
|
||||
Matcher _matches(String text) {
|
||||
var unIndented = RegExp.escape(text).replaceAll(RegExp('[ ]+'), '[ ]*');
|
||||
return matches(RegExp(unIndented, multiLine: true));
|
||||
}
|
||||
|
||||
static int _getEvaluationLine(String source) {
|
||||
var placeholderRegExp = RegExp(r'/\* evaluation placeholder \*/');
|
||||
|
||||
var lines = source.split('\n');
|
||||
for (var line = 0; line < lines.length; line++) {
|
||||
var content = lines[line];
|
||||
if (placeholderRegExp.firstMatch(content) != null) {
|
||||
return line + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
void main(List<String> args) {
|
||||
for (var moduleFormat in [ModuleFormat.amd, ModuleFormat.ddc]) {
|
||||
group('Module format: $moduleFormat |', () {
|
||||
group('Unsound null safety |', () {
|
||||
runUnsoundTests(moduleFormat);
|
||||
runTests(SetupCompilerOptions(
|
||||
soundNullSafety: false,
|
||||
moduleFormat: moduleFormat,
|
||||
args: args,
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -287,33 +24,31 @@ void main() {
|
|||
for (var moduleFormat in [ModuleFormat.amd, ModuleFormat.ddc]) {
|
||||
group('Module format: $moduleFormat |', () {
|
||||
group('Sound null safety |', () {
|
||||
runSoundTests(moduleFormat);
|
||||
runTests(SetupCompilerOptions(
|
||||
soundNullSafety: true,
|
||||
moduleFormat: moduleFormat,
|
||||
args: args,
|
||||
));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void runUnsoundTests(ModuleFormat moduleFormat) {
|
||||
var options = SetupCompilerOptions(
|
||||
soundNullSafety: false,
|
||||
moduleFormat: moduleFormat,
|
||||
);
|
||||
|
||||
void runTests(SetupCompilerOptions setup) {
|
||||
group('Expression compilations on the same expression compiler |', () {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
main() {
|
||||
}
|
||||
main() {
|
||||
}
|
||||
|
||||
void foo() {
|
||||
/* evaluation placeholder */
|
||||
}
|
||||
''';
|
||||
void foo() {
|
||||
// Breakpoint
|
||||
}
|
||||
''';
|
||||
|
||||
late TestDriver driver;
|
||||
late ExpressionCompilerTestDriver driver;
|
||||
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
driver = ExpressionCompilerTestDriver(setup, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
|
@ -326,24 +61,12 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
|||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'true',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return true;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return true;'));
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'false',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return false;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return false;'));
|
||||
});
|
||||
|
||||
test('some successful expression compilations', () async {
|
||||
|
@ -352,13 +75,7 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
|||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'true',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return true;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return true;'));
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
|
@ -369,13 +86,7 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
|||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'false',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return false;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return false;'));
|
||||
});
|
||||
|
||||
test('failing expression compilations', () async {
|
||||
|
@ -397,26 +108,25 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
|||
|
||||
group('Expression compiler import tests', () {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
import 'dart:io' show Directory;
|
||||
import 'dart:io' as p;
|
||||
import 'dart:convert' as p;
|
||||
|
||||
main() {
|
||||
print(Directory.systemTemp);
|
||||
print(p.Directory.systemTemp);
|
||||
print(p.utf.decoder);
|
||||
}
|
||||
import 'dart:io' show Directory;
|
||||
import 'dart:io' as p;
|
||||
import 'dart:convert' as p;
|
||||
|
||||
void foo() {
|
||||
/* evaluation placeholder */
|
||||
}
|
||||
''';
|
||||
main() {
|
||||
print(Directory.systemTemp);
|
||||
print(p.Directory.systemTemp);
|
||||
print(p.utf8.decoder);
|
||||
}
|
||||
|
||||
late TestDriver driver;
|
||||
void foo() {
|
||||
// Breakpoint
|
||||
}
|
||||
''';
|
||||
|
||||
late ExpressionCompilerTestDriver driver;
|
||||
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
driver = ExpressionCompilerTestDriver(setup, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
|
@ -427,30 +137,14 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
|||
await driver.check(
|
||||
scope: <String, String>{},
|
||||
expression: 'Directory.systemTemp',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const io = dart_sdk.io;
|
||||
return io.Directory.systemTemp;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return io.Directory.systemTemp;'));
|
||||
});
|
||||
|
||||
test('expression referencing named import', () async {
|
||||
await driver.check(
|
||||
scope: <String, String>{},
|
||||
expression: 'p.Directory.systemTemp',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const io = dart_sdk.io;
|
||||
return io.Directory.systemTemp;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return io.Directory.systemTemp;'));
|
||||
});
|
||||
|
||||
test('expression referencing another library with the same named import',
|
||||
|
@ -458,412 +152,7 @@ void runUnsoundTests(ModuleFormat moduleFormat) {
|
|||
await driver.check(
|
||||
scope: <String, String>{},
|
||||
expression: 'p.utf8.decoder',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const convert = dart_sdk.convert;
|
||||
return convert.utf8.decoder;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
});
|
||||
|
||||
group('Expression compiler tests for interactions with module containers:',
|
||||
() {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
class B {
|
||||
const B();
|
||||
}
|
||||
void foo() {
|
||||
const a = A();
|
||||
var check = a is int;
|
||||
/* evaluation placeholder */
|
||||
return;
|
||||
}
|
||||
|
||||
void main() => foo();
|
||||
''';
|
||||
|
||||
late TestDriver driver;
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
driver.delete();
|
||||
});
|
||||
|
||||
test('evaluation that non-destructively appends to the type container',
|
||||
() async {
|
||||
await driver.check(
|
||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
||||
expression: 'a is String',
|
||||
expectedResult: '''
|
||||
(function(a, check) {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const core = dart_sdk.core;
|
||||
const dart = dart_sdk.dart;
|
||||
var T = {
|
||||
StringL: () => (T.StringL = dart.constFn(dart.legacy(core.String)))()
|
||||
};
|
||||
return T.StringL().is(a);
|
||||
}(
|
||||
null,
|
||||
null
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test('evaluation that reuses the type container', () async {
|
||||
await driver.check(
|
||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
||||
expression: 'a is int',
|
||||
expectedResult: '''
|
||||
(function(a, check) {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const core = dart_sdk.core;
|
||||
const dart = dart_sdk.dart;
|
||||
var T = {
|
||||
intL: () => (T.intL = dart.constFn(dart.legacy(core.int)))()
|
||||
};
|
||||
return T.intL().is(a);
|
||||
}(
|
||||
null,
|
||||
null
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test('evaluation that non-destructively appends to the constant container',
|
||||
() async {
|
||||
await driver.check(
|
||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
||||
expression: 'const B()',
|
||||
expectedResult: '''
|
||||
(function(a, check) {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const dart = dart_sdk.dart;
|
||||
const foo\$46dart = ${options.loadModule}('foo.dart');
|
||||
const foo = foo\$46dart.foo;
|
||||
const CT = Object.create(null);
|
||||
dart.defineLazy(CT, {
|
||||
get C0() {
|
||||
return C[0] = dart.const(Object.setPrototypeOf({
|
||||
}, foo.B.prototype));
|
||||
}
|
||||
}, false);
|
||||
var C = [void 0];
|
||||
return C[0] || CT.C0;
|
||||
}(
|
||||
null,
|
||||
null
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test(
|
||||
'evaluation that reuses the constant container and canonicalizes properly',
|
||||
() async {
|
||||
await driver.check(
|
||||
scope: <String, String>{'a': 'null', 'check': 'null'},
|
||||
expression: 'a == const A()',
|
||||
expectedResult: '''
|
||||
(function(a, check) {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const dart = dart_sdk.dart;
|
||||
const foo\$46dart = ${options.loadModule}('foo.dart');
|
||||
const foo = foo\$46dart.foo;
|
||||
const CT = Object.create(null);
|
||||
dart.defineLazy(CT, {
|
||||
get C0() {
|
||||
return C[0] = dart.const(Object.setPrototypeOf({
|
||||
}, foo.A.prototype));
|
||||
}
|
||||
}, false);
|
||||
var C = [void 0];
|
||||
return dart.equals(a, C[0] || CT.C0);
|
||||
}(
|
||||
null,
|
||||
null
|
||||
))
|
||||
''');
|
||||
});
|
||||
});
|
||||
|
||||
group('Expression compiler tests using extension symbols', () {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
void bar() {
|
||||
/* evaluation placeholder */
|
||||
}
|
||||
|
||||
void main() => bar();
|
||||
''';
|
||||
|
||||
late TestDriver driver;
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
driver.delete();
|
||||
});
|
||||
|
||||
test('map access', () async {
|
||||
await driver.check(
|
||||
scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
|
||||
expression:
|
||||
'(Map<String, String> params) { return params["index"]; }({})',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const core = dart_sdk.core;
|
||||
const _js_helper = dart_sdk._js_helper;
|
||||
const dart = dart_sdk.dart;
|
||||
const dartx = dart_sdk.dartx;
|
||||
var T = {
|
||||
StringL: () => (T.StringL = dart.constFn(dart.legacy(core.String)))(),
|
||||
MapOfStringL\$StringL: () => (T.MapOfStringL\$StringL = dart.constFn(core.Map\$(T.StringL(), T.StringL())))(),
|
||||
MapLOfStringL\$StringL: () => (T.MapLOfStringL\$StringL = dart.constFn(dart.legacy(T.MapOfStringL\$StringL())))(),
|
||||
MapLOfStringL\$StringLToStringL: () => (T.MapLOfStringL\$StringLToStringL = dart.constFn(dart.fnType(T.StringL(), [T.MapLOfStringL\$StringL()])))(),
|
||||
IdentityMapOfStringL\$StringL: () => (T.IdentityMapOfStringL\$StringL = dart.constFn(_js_helper.IdentityMap\$(T.StringL(), T.StringL())))()
|
||||
};
|
||||
var S = {\$_get: dartx._get};
|
||||
return dart.fn(params => params[S.\$_get]("index"), T.MapLOfStringL\$StringLToStringL())(new (T.IdentityMapOfStringL\$StringL()).new());
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void runSoundTests(ModuleFormat moduleFormat) {
|
||||
var options = SetupCompilerOptions(
|
||||
soundNullSafety: true,
|
||||
moduleFormat: moduleFormat,
|
||||
);
|
||||
|
||||
group('Expression compilations on the same expression compiler |', () {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
main() {
|
||||
}
|
||||
|
||||
void foo() {
|
||||
/* evaluation placeholder */
|
||||
}
|
||||
''';
|
||||
|
||||
late TestDriver driver;
|
||||
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
driver.delete();
|
||||
});
|
||||
|
||||
test('successful expression compilations', () async {
|
||||
var compiler = await driver.createCompiler();
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'true',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return true;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'false',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return false;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test('some successful expression compilations', () async {
|
||||
var compiler = await driver.createCompiler();
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'true',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return true;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'blah',
|
||||
expectedError: "Undefined name 'blah'",
|
||||
);
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'false',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
return false;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test('failing expression compilations', () async {
|
||||
var compiler = await driver.createCompiler();
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'blah1',
|
||||
expectedError: "Undefined name 'blah1'",
|
||||
);
|
||||
await driver.check(
|
||||
compiler: compiler,
|
||||
scope: <String, String>{},
|
||||
expression: 'blah2',
|
||||
expectedError: "Undefined name 'blah2'",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('Expression compiler import tests', () {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
import 'dart:io' show Directory;
|
||||
import 'dart:io' as p;
|
||||
import 'dart:convert' as p;
|
||||
|
||||
main() {
|
||||
print(Directory.systemTemp);
|
||||
print(p.Directory.systemTemp);
|
||||
print(p.utf.decoder);
|
||||
}
|
||||
|
||||
void foo() {
|
||||
/* evaluation placeholder */
|
||||
}
|
||||
''';
|
||||
|
||||
late TestDriver driver;
|
||||
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
driver.delete();
|
||||
});
|
||||
|
||||
test('expression referencing unnamed import', () async {
|
||||
await driver.check(
|
||||
scope: <String, String>{},
|
||||
expression: 'Directory.systemTemp',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const io = dart_sdk.io;
|
||||
return io.Directory.systemTemp;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test('expression referencing named import', () async {
|
||||
await driver.check(
|
||||
scope: <String, String>{},
|
||||
expression: 'p.Directory.systemTemp',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const io = dart_sdk.io;
|
||||
return io.Directory.systemTemp;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
|
||||
test('expression referencing another library with the same named import',
|
||||
() async {
|
||||
await driver.check(
|
||||
scope: <String, String>{},
|
||||
expression: 'p.utf8.decoder',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const convert = dart_sdk.convert;
|
||||
return convert.utf8.decoder;
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
});
|
||||
});
|
||||
|
||||
group('Expression compiler expressions that import extension symbols', () {
|
||||
var source = '''
|
||||
${options.dartLangComment}
|
||||
void bar() {
|
||||
/* evaluation placeholder */
|
||||
}
|
||||
|
||||
void main() => bar();
|
||||
''';
|
||||
|
||||
late TestDriver driver;
|
||||
setUp(() {
|
||||
driver = TestDriver(options, source);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
driver.delete();
|
||||
});
|
||||
|
||||
test('map access', () async {
|
||||
await driver.check(
|
||||
scope: <String, String>{'inScope': '1', 'innerInScope': '0'},
|
||||
expression:
|
||||
'(Map<String, String> params) { return params["index"]; }({})',
|
||||
expectedResult: '''
|
||||
(function() {
|
||||
const dart_sdk = ${options.loadModule}('dart_sdk');
|
||||
const core = dart_sdk.core;
|
||||
const _js_helper = dart_sdk._js_helper;
|
||||
const dart = dart_sdk.dart;
|
||||
const dartx = dart_sdk.dartx;
|
||||
var T = {
|
||||
StringN: () => (T.StringN = dart.constFn(dart.nullable(core.String)))(),
|
||||
MapOfString\$String: () => (T.MapOfString\$String = dart.constFn(core.Map\$(core.String, core.String)))(),
|
||||
MapOfString\$StringToStringN: () => (T.MapOfString\$StringToStringN = dart.constFn(dart.fnType(T.StringN(), [T.MapOfString\$String()])))(),
|
||||
IdentityMapOfString\$String: () => (T.IdentityMapOfString\$String = dart.constFn(_js_helper.IdentityMap\$(core.String, core.String)))()
|
||||
};
|
||||
var S = {\$_get: dartx._get};
|
||||
return dart.fn(params => params[S.\$_get]("index"), T.MapOfString\$StringToStringN())(new (T.IdentityMapOfString\$String()).new());
|
||||
}(
|
||||
|
||||
))
|
||||
''');
|
||||
expectedResult: contains('return convert.utf8.decoder;'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
import 'package:dev_compiler/dev_compiler.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_worker_shared.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
// Set to true to enable debug output
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
import 'package:dev_compiler/dev_compiler.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_worker_shared.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
// Set to true to enable debug output
|
||||
|
|
|
@ -22,7 +22,7 @@ import 'package:shelf/shelf.dart';
|
|||
import 'package:shelf/shelf_io.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'setup_compiler_options.dart';
|
||||
import '../shared_test_options.dart';
|
||||
|
||||
void runTests(SetupCompilerOptions setup, {bool verbose = false}) {
|
||||
group('expression compiler worker on startup', () {
|
||||
|
@ -77,37 +77,20 @@ void runTests(SetupCompilerOptions setup, {bool verbose = false}) {
|
|||
});
|
||||
|
||||
group('reading assets using standard file system - ', () {
|
||||
runExpressionCompilationTests(StandardFileSystemTestDriver(
|
||||
setup.soundNullSafety,
|
||||
setup.moduleFormat,
|
||||
setup.canaryFeatures,
|
||||
setup.enableAsserts,
|
||||
verbose,
|
||||
));
|
||||
runExpressionCompilationTests(StandardFileSystemTestDriver(setup, verbose));
|
||||
});
|
||||
|
||||
group('reading assets using multiroot file system - ', () {
|
||||
runExpressionCompilationTests(MultiRootFileSystemTestDriver(
|
||||
setup.soundNullSafety,
|
||||
setup.moduleFormat,
|
||||
setup.canaryFeatures,
|
||||
setup.enableAsserts,
|
||||
verbose,
|
||||
));
|
||||
runExpressionCompilationTests(
|
||||
MultiRootFileSystemTestDriver(setup, verbose));
|
||||
});
|
||||
|
||||
group('reading assets using asset file system -', () {
|
||||
runExpressionCompilationTests(AssetFileSystemTestDriver(
|
||||
setup.soundNullSafety,
|
||||
setup.moduleFormat,
|
||||
setup.canaryFeatures,
|
||||
setup.enableAsserts,
|
||||
verbose,
|
||||
));
|
||||
runExpressionCompilationTests(AssetFileSystemTestDriver(setup, verbose));
|
||||
});
|
||||
}
|
||||
|
||||
void runExpressionCompilationTests(TestDriver driver) {
|
||||
void runExpressionCompilationTests(ExpressionCompilerWorkerTestDriver driver) {
|
||||
group('expression compiler worker', () {
|
||||
setUpAll(() async {
|
||||
await driver.setUpAll();
|
||||
|
@ -963,13 +946,9 @@ class E {
|
|||
}
|
||||
}
|
||||
|
||||
abstract class TestDriver {
|
||||
final bool soundNullSafety;
|
||||
final ModuleFormat moduleFormat;
|
||||
final bool canaryFeatures;
|
||||
final bool enableAsserts;
|
||||
final bool verbose;
|
||||
|
||||
abstract class ExpressionCompilerWorkerTestDriver {
|
||||
SetupCompilerOptions setup;
|
||||
bool verbose;
|
||||
late FileSystem assetFileSystem;
|
||||
|
||||
late Directory tempDir;
|
||||
|
@ -981,13 +960,7 @@ abstract class TestDriver {
|
|||
ExpressionCompilerWorker? worker;
|
||||
Future<void>? workerDone;
|
||||
|
||||
TestDriver(
|
||||
this.soundNullSafety,
|
||||
this.moduleFormat,
|
||||
this.canaryFeatures,
|
||||
this.enableAsserts,
|
||||
this.verbose,
|
||||
);
|
||||
ExpressionCompilerWorkerTestDriver(this.setup, this.verbose);
|
||||
|
||||
/// Initialize file systems, inputs, and start servers if needed.
|
||||
Future<void> start();
|
||||
|
@ -996,7 +969,8 @@ abstract class TestDriver {
|
|||
|
||||
Future<void> setUpAll() async {
|
||||
tempDir = Directory.systemTemp.createTempSync('foo bar');
|
||||
config = TestProjectConfiguration(tempDir, soundNullSafety, moduleFormat)
|
||||
config = TestProjectConfiguration(
|
||||
tempDir, setup.soundNullSafety, setup.moduleFormat)
|
||||
..initialize();
|
||||
|
||||
await start();
|
||||
|
@ -1026,10 +1000,10 @@ abstract class TestDriver {
|
|||
fileSystem: assetFileSystem,
|
||||
requestStream: requestController.stream,
|
||||
sendResponse: responseController.add,
|
||||
soundNullSafety: soundNullSafety,
|
||||
moduleFormat: moduleFormat,
|
||||
canaryFeatures: canaryFeatures,
|
||||
enableAsserts: enableAsserts,
|
||||
soundNullSafety: setup.soundNullSafety,
|
||||
moduleFormat: setup.moduleFormat,
|
||||
canaryFeatures: setup.canaryFeatures,
|
||||
enableAsserts: setup.enableAsserts,
|
||||
verbose: verbose,
|
||||
);
|
||||
workerDone = worker?.run();
|
||||
|
@ -1043,15 +1017,9 @@ abstract class TestDriver {
|
|||
}
|
||||
}
|
||||
|
||||
class StandardFileSystemTestDriver extends TestDriver {
|
||||
StandardFileSystemTestDriver(
|
||||
bool soundNullSafety,
|
||||
ModuleFormat moduleFormat,
|
||||
bool canaryFeatures,
|
||||
bool enableAsserts,
|
||||
bool verbose,
|
||||
) : super(soundNullSafety, moduleFormat, canaryFeatures, enableAsserts,
|
||||
verbose);
|
||||
class StandardFileSystemTestDriver extends ExpressionCompilerWorkerTestDriver {
|
||||
StandardFileSystemTestDriver(SetupCompilerOptions setup, bool verbose)
|
||||
: super(setup, verbose);
|
||||
|
||||
@override
|
||||
Future<void> start() async {
|
||||
|
@ -1060,15 +1028,9 @@ class StandardFileSystemTestDriver extends TestDriver {
|
|||
}
|
||||
}
|
||||
|
||||
class MultiRootFileSystemTestDriver extends TestDriver {
|
||||
MultiRootFileSystemTestDriver(
|
||||
bool soundNullSafety,
|
||||
ModuleFormat moduleFormat,
|
||||
bool canaryFeatures,
|
||||
bool enableAsserts,
|
||||
bool verbose,
|
||||
) : super(soundNullSafety, moduleFormat, canaryFeatures, enableAsserts,
|
||||
verbose);
|
||||
class MultiRootFileSystemTestDriver extends ExpressionCompilerWorkerTestDriver {
|
||||
MultiRootFileSystemTestDriver(SetupCompilerOptions setup, bool verbose)
|
||||
: super(setup, verbose);
|
||||
|
||||
@override
|
||||
Future<void> start() async {
|
||||
|
@ -1079,18 +1041,12 @@ class MultiRootFileSystemTestDriver extends TestDriver {
|
|||
}
|
||||
}
|
||||
|
||||
class AssetFileSystemTestDriver extends TestDriver {
|
||||
class AssetFileSystemTestDriver extends ExpressionCompilerWorkerTestDriver {
|
||||
late TestAssetServer server;
|
||||
late int port;
|
||||
|
||||
AssetFileSystemTestDriver(
|
||||
bool soundNullSafety,
|
||||
ModuleFormat moduleFormat,
|
||||
bool canaryFeatures,
|
||||
bool enableAsserts,
|
||||
bool verbose,
|
||||
) : super(soundNullSafety, moduleFormat, canaryFeatures, enableAsserts,
|
||||
verbose);
|
||||
AssetFileSystemTestDriver(SetupCompilerOptions setup, bool verbose)
|
||||
: super(setup, verbose);
|
||||
|
||||
@override
|
||||
Future<void> start() async {
|
||||
|
|
|
@ -6,11 +6,11 @@ import 'package:dev_compiler/src/compiler/module_builder.dart'
|
|||
show ModuleFormat;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
import 'expression_compiler_e2e_suite.dart';
|
||||
import 'setup_compiler_options.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
var driver = await TestDriver.init();
|
||||
var driver = await ExpressionEvaluationTestDriver.init();
|
||||
|
||||
tearDownAll(() async {
|
||||
await driver.finish();
|
||||
|
@ -116,7 +116,8 @@ main() {
|
|||
}
|
||||
''';
|
||||
|
||||
void runSharedTests(SetupCompilerOptions setup, TestDriver driver) {
|
||||
void runSharedTests(
|
||||
SetupCompilerOptions setup, ExpressionEvaluationTestDriver driver) {
|
||||
group('Runtime debugging API |', () {
|
||||
var source = simpleClassSource;
|
||||
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
// 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 'package:dev_compiler/src/compiler/module_builder.dart';
|
||||
import 'package:dev_compiler/src/kernel/command.dart';
|
||||
import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
|
||||
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
||||
import 'package:front_end/src/compute_platform_binaries_location.dart' as fe;
|
||||
import 'package:kernel/target/targets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
|
||||
class SetupCompilerOptions {
|
||||
static final sdkRoot = fe.computePlatformBinariesLocation();
|
||||
static final buildRoot =
|
||||
fe.computePlatformBinariesLocation(forceBuildDir: true);
|
||||
static final sdkUnsoundSummaryPath =
|
||||
buildRoot.resolve('ddc_outline_unsound.dill').toFilePath();
|
||||
static final sdkSoundSummaryPath =
|
||||
buildRoot.resolve('ddc_outline.dill').toFilePath();
|
||||
static final librariesSpecificationUri =
|
||||
buildRoot.resolve('lib/libraries.json').toFilePath();
|
||||
|
||||
final bool legacyCode;
|
||||
final List<String> errors = [];
|
||||
final List<String> diagnosticMessages = [];
|
||||
final ModuleFormat moduleFormat;
|
||||
final fe.CompilerOptions options;
|
||||
final bool soundNullSafety;
|
||||
final bool canaryFeatures;
|
||||
final bool enableAsserts;
|
||||
|
||||
static fe.CompilerOptions _getOptions(
|
||||
{required bool enableAsserts, required bool soundNullSafety}) {
|
||||
var options = fe.CompilerOptions()
|
||||
..verbose = false // set to true for debugging
|
||||
..sdkRoot = sdkRoot
|
||||
..target =
|
||||
DevCompilerTarget(TargetFlags(soundNullSafety: soundNullSafety))
|
||||
..librariesSpecificationUri = p.toUri('sdk/lib/libraries.json')
|
||||
..omitPlatform = true
|
||||
..sdkSummary =
|
||||
p.toUri(soundNullSafety ? sdkSoundSummaryPath : sdkUnsoundSummaryPath)
|
||||
..environmentDefines =
|
||||
addGeneratedVariables({}, enableAsserts: enableAsserts)
|
||||
..nnbdMode = soundNullSafety ? fe.NnbdMode.Strong : fe.NnbdMode.Weak;
|
||||
return options;
|
||||
}
|
||||
|
||||
SetupCompilerOptions._({
|
||||
this.enableAsserts = true,
|
||||
this.soundNullSafety = true,
|
||||
this.legacyCode = false,
|
||||
this.moduleFormat = ModuleFormat.amd,
|
||||
this.canaryFeatures = false,
|
||||
}) : options = _getOptions(
|
||||
soundNullSafety: soundNullSafety, enableAsserts: enableAsserts) {
|
||||
options.onDiagnostic = (fe.DiagnosticMessage m) {
|
||||
diagnosticMessages.addAll(m.plainTextFormatted);
|
||||
if (m.severity == fe.Severity.error ||
|
||||
m.severity == fe.Severity.internalProblem) {
|
||||
errors.addAll(m.plainTextFormatted);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Creates current compiler setup options.
|
||||
///
|
||||
/// Reads options determined by the test configuration from the configuration
|
||||
/// environment variable set by the test runner.
|
||||
///
|
||||
/// To run tests locally using test.py, pass a vm option defining required
|
||||
/// configuration, for example:
|
||||
///
|
||||
/// `./tools/test.py -n web-dev-canary-unittest-asserts-mac`
|
||||
///
|
||||
/// To run a single test locally, pass the --canary or --enable-asserts flags
|
||||
/// to the command line to enable corresponding features, for example:
|
||||
///
|
||||
/// `dart test/expression_compiler/assertions_enabled_test.dart --canary --enable-asserts`
|
||||
factory SetupCompilerOptions({
|
||||
bool soundNullSafety = true,
|
||||
bool legacyCode = false,
|
||||
ModuleFormat moduleFormat = ModuleFormat.amd,
|
||||
List<String> args = const <String>[],
|
||||
}) {
|
||||
// Find if the test is run with arguments overriding the configuration
|
||||
late bool enableAsserts;
|
||||
late bool canaryFeatures;
|
||||
|
||||
// Read configuration settings from matrix.json
|
||||
var configuration = String.fromEnvironment('test_runner.configuration');
|
||||
if (configuration.isEmpty) {
|
||||
// If not running from test runner, read options from the args
|
||||
enableAsserts = args.contains('--enable-asserts');
|
||||
canaryFeatures = args.contains('--canary');
|
||||
} else {
|
||||
// If running from the test runner, read options from the environment
|
||||
// (set to configuration settings from matrix.json).
|
||||
enableAsserts = configuration.contains('-asserts-');
|
||||
canaryFeatures = configuration.contains('-canary-');
|
||||
}
|
||||
return SetupCompilerOptions._(
|
||||
enableAsserts: enableAsserts,
|
||||
soundNullSafety: soundNullSafety,
|
||||
legacyCode: legacyCode,
|
||||
moduleFormat: moduleFormat,
|
||||
canaryFeatures: canaryFeatures,
|
||||
);
|
||||
}
|
||||
}
|
154
pkg/dev_compiler/test/expression_compiler/test_compiler.dart
Normal file
154
pkg/dev_compiler/test/expression_compiler/test_compiler.dart
Normal file
|
@ -0,0 +1,154 @@
|
|||
// 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:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io' show File;
|
||||
|
||||
import 'package:dev_compiler/src/compiler/shared_command.dart'
|
||||
show SharedCompilerOptions;
|
||||
import 'package:dev_compiler/src/kernel/command.dart';
|
||||
import 'package:dev_compiler/src/kernel/compiler.dart' show ProgramCompiler;
|
||||
import 'package:dev_compiler/src/kernel/expression_compiler.dart'
|
||||
show ExpressionCompiler;
|
||||
import 'package:dev_compiler/src/kernel/module_metadata.dart';
|
||||
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
||||
import 'package:kernel/ast.dart' show Component, Library;
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:source_maps/source_maps.dart' as source_maps;
|
||||
|
||||
import '../shared_test_options.dart';
|
||||
|
||||
class TestCompilationResult {
|
||||
final String? result;
|
||||
final bool isSuccess;
|
||||
|
||||
TestCompilationResult(this.result, this.isSuccess);
|
||||
}
|
||||
|
||||
class TestExpressionCompiler {
|
||||
final SetupCompilerOptions setup;
|
||||
final Component component;
|
||||
final ExpressionCompiler compiler;
|
||||
final ModuleMetadata? metadata;
|
||||
final source_maps.SingleMapping sourceMap;
|
||||
|
||||
TestExpressionCompiler._(
|
||||
this.setup, this.component, this.compiler, this.metadata, this.sourceMap);
|
||||
|
||||
static Future<TestExpressionCompiler> init(SetupCompilerOptions setup,
|
||||
{required Uri input,
|
||||
required Uri output,
|
||||
Uri? packages,
|
||||
Map<String, bool> experiments = const {}}) async {
|
||||
setup.diagnosticMessages.clear();
|
||||
setup.errors.clear();
|
||||
// Initialize the incremental compiler and module component.
|
||||
// TODO: extend this for multi-module compilations by storing separate
|
||||
// compilers/components/names per module.
|
||||
setup.options.packagesFileUri = packages;
|
||||
setup.options.explicitExperimentalFlags.addAll(fe.parseExperimentalFlags(
|
||||
experiments,
|
||||
onError: (message) => throw Exception(message)));
|
||||
var frontend = DevelopmentIncrementalCompiler(setup.options, input);
|
||||
var compilerResult = await frontend.computeDelta();
|
||||
var component = compilerResult.component;
|
||||
component.computeCanonicalNames();
|
||||
// Initialize DDC.
|
||||
var moduleName = p.basenameWithoutExtension(output.toFilePath());
|
||||
|
||||
var classHierarchy = compilerResult.classHierarchy!;
|
||||
var compilerOptions = SharedCompilerOptions(
|
||||
replCompile: true,
|
||||
moduleName: moduleName,
|
||||
experiments: experiments,
|
||||
soundNullSafety: setup.soundNullSafety,
|
||||
emitDebugMetadata: true,
|
||||
canaryFeatures: setup.canaryFeatures,
|
||||
enableAsserts: setup.enableAsserts,
|
||||
);
|
||||
var coreTypes = compilerResult.coreTypes;
|
||||
|
||||
final importToSummary = Map<Library, Component>.identity();
|
||||
final summaryToModule = Map<Component, String>.identity();
|
||||
for (var lib in component.libraries) {
|
||||
importToSummary[lib] = component;
|
||||
}
|
||||
summaryToModule[component] = moduleName;
|
||||
|
||||
var kernel2jsCompiler = ProgramCompiler(component, classHierarchy,
|
||||
compilerOptions, importToSummary, summaryToModule,
|
||||
coreTypes: coreTypes);
|
||||
var module = kernel2jsCompiler.emitModule(component);
|
||||
|
||||
// Perform a full compile, writing the compiled JS + sourcemap.
|
||||
var code = jsProgramToCode(
|
||||
module,
|
||||
setup.moduleFormat,
|
||||
inlineSourceMap: compilerOptions.inlineSourceMap,
|
||||
buildSourceMap: compilerOptions.sourceMap,
|
||||
emitDebugMetadata: compilerOptions.emitDebugMetadata,
|
||||
emitDebugSymbols: compilerOptions.emitDebugSymbols,
|
||||
jsUrl: '$output',
|
||||
mapUrl: '$output.map',
|
||||
compiler: kernel2jsCompiler,
|
||||
component: component,
|
||||
);
|
||||
var codeBytes = utf8.encode(code.code);
|
||||
var sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
|
||||
|
||||
File(output.toFilePath()).writeAsBytesSync(codeBytes);
|
||||
File('${output.toFilePath()}.map').writeAsBytesSync(sourceMapBytes);
|
||||
|
||||
// Save the expression compiler for future compilation.
|
||||
var compiler = ExpressionCompiler(
|
||||
setup.options,
|
||||
setup.moduleFormat,
|
||||
setup.errors,
|
||||
frontend,
|
||||
kernel2jsCompiler,
|
||||
component,
|
||||
);
|
||||
|
||||
if (setup.errors.isNotEmpty) {
|
||||
throw Exception('Compilation failed with: ${setup.errors}');
|
||||
}
|
||||
setup.diagnosticMessages.clear();
|
||||
setup.errors.clear();
|
||||
|
||||
var sourceMap = source_maps.SingleMapping.fromJson(
|
||||
code.sourceMap!.cast<String, dynamic>());
|
||||
return TestExpressionCompiler._(
|
||||
setup, component, compiler, code.metadata, sourceMap);
|
||||
}
|
||||
|
||||
Future<TestCompilationResult> compileExpression(
|
||||
{required Uri input,
|
||||
required int line,
|
||||
required int column,
|
||||
required Map<String, String> scope,
|
||||
required String expression}) async {
|
||||
// clear previous errors
|
||||
setup.errors.clear();
|
||||
|
||||
var libraryUri = metadataForLibraryUri(input);
|
||||
var jsExpression = await compiler.compileExpressionToJs(
|
||||
libraryUri.importUri, line, column, scope, expression);
|
||||
if (setup.errors.isNotEmpty) {
|
||||
jsExpression = setup.errors.toString().replaceAll(
|
||||
RegExp(
|
||||
r'org-dartlang-debug:synthetic_debug_expression:[0-9]*:[0-9]*:'),
|
||||
'');
|
||||
|
||||
return TestCompilationResult(jsExpression, false);
|
||||
}
|
||||
|
||||
return TestCompilationResult(jsExpression, true);
|
||||
}
|
||||
|
||||
LibraryMetadata metadataForLibraryUri(Uri libraryUri) =>
|
||||
metadata!.libraries.entries
|
||||
.firstWhere((entry) => entry.value.fileUri == '$libraryUri')
|
||||
.value;
|
||||
}
|
|
@ -5,97 +5,139 @@
|
|||
import 'package:dev_compiler/src/compiler/module_builder.dart'
|
||||
show ModuleFormat;
|
||||
import 'package:dev_compiler/src/kernel/command.dart'
|
||||
show addGeneratedVariables, getSdkPath;
|
||||
show addGeneratedVariables;
|
||||
import 'package:dev_compiler/src/kernel/target.dart' show DevCompilerTarget;
|
||||
import 'package:front_end/src/api_unstable/ddc.dart';
|
||||
import 'package:front_end/src/compute_platform_binaries_location.dart';
|
||||
import 'package:front_end/src/fasta/incremental_serializer.dart';
|
||||
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
|
||||
import 'package:front_end/src/compute_platform_binaries_location.dart' as fe;
|
||||
import 'package:front_end/src/fasta/incremental_serializer.dart' as fe;
|
||||
import 'package:kernel/ast.dart' show Component;
|
||||
import 'package:kernel/target/targets.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:kernel/target/targets.dart' show TargetFlags;
|
||||
|
||||
class DevelopmentIncrementalCompiler extends IncrementalCompiler {
|
||||
class DevelopmentIncrementalCompiler extends fe.IncrementalCompiler {
|
||||
Uri entryPoint;
|
||||
|
||||
DevelopmentIncrementalCompiler(CompilerOptions options, this.entryPoint,
|
||||
DevelopmentIncrementalCompiler(fe.CompilerOptions options, this.entryPoint,
|
||||
[Uri? initializeFrom,
|
||||
bool? outlineOnly,
|
||||
IncrementalSerializer? incrementalSerializer])
|
||||
fe.IncrementalSerializer? incrementalSerializer])
|
||||
: super(
|
||||
CompilerContext(
|
||||
ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||
fe.CompilerContext(
|
||||
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||
initializeFrom,
|
||||
outlineOnly,
|
||||
incrementalSerializer);
|
||||
|
||||
DevelopmentIncrementalCompiler.fromComponent(CompilerOptions options,
|
||||
DevelopmentIncrementalCompiler.fromComponent(fe.CompilerOptions options,
|
||||
this.entryPoint, Component componentToInitializeFrom,
|
||||
[bool? outlineOnly, IncrementalSerializer? incrementalSerializer])
|
||||
[bool? outlineOnly, fe.IncrementalSerializer? incrementalSerializer])
|
||||
: super.fromComponent(
|
||||
CompilerContext(
|
||||
ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||
fe.CompilerContext(
|
||||
fe.ProcessedOptions(options: options, inputs: [entryPoint])),
|
||||
componentToInitializeFrom,
|
||||
outlineOnly,
|
||||
incrementalSerializer);
|
||||
}
|
||||
|
||||
class SetupCompilerOptions {
|
||||
static final sdkRoot = computePlatformBinariesLocation();
|
||||
// Unsound .dill files are not longer in the released SDK so this file must be
|
||||
// read from the build output directory.
|
||||
static final sdkUnsoundSummaryPath =
|
||||
computePlatformBinariesLocation(forceBuildDir: true)
|
||||
.resolve('ddc_outline_unsound.dill');
|
||||
// Use the outline copied to the released SDK.
|
||||
static final sdkSoundSummaryPath = sdkRoot.resolve('ddc_outline.dill');
|
||||
static final librariesSpecificationUri =
|
||||
p.join(p.dirname(p.dirname(getSdkPath())), 'libraries.json');
|
||||
static final sdkRoot = fe.computePlatformBinariesLocation();
|
||||
static final buildRoot =
|
||||
fe.computePlatformBinariesLocation(forceBuildDir: true);
|
||||
static final _sdkUnsoundSummaryPath =
|
||||
buildRoot.resolve('ddc_outline_unsound.dill');
|
||||
static final _sdkSoundSummaryPath = buildRoot.resolve('ddc_outline.dill');
|
||||
|
||||
static CompilerOptions getOptions(bool soundNullSafety) {
|
||||
var options = CompilerOptions()
|
||||
static final _dartUnsoundComment = '// @dart = 2.9';
|
||||
static final _dartSoundComment = '//';
|
||||
String get dartLangComment =>
|
||||
soundNullSafety ? _dartSoundComment : _dartUnsoundComment;
|
||||
|
||||
final bool legacyCode;
|
||||
final List<String> errors = [];
|
||||
final List<String> diagnosticMessages = [];
|
||||
final ModuleFormat moduleFormat;
|
||||
final fe.CompilerOptions options;
|
||||
final bool soundNullSafety;
|
||||
final bool canaryFeatures;
|
||||
final bool enableAsserts;
|
||||
|
||||
static fe.CompilerOptions _getOptions(
|
||||
{required bool enableAsserts, required bool soundNullSafety}) {
|
||||
var options = fe.CompilerOptions()
|
||||
..verbose = false // set to true for debugging
|
||||
..sdkRoot = sdkRoot
|
||||
..target =
|
||||
DevCompilerTarget(TargetFlags(soundNullSafety: soundNullSafety))
|
||||
..librariesSpecificationUri = Uri.base.resolve('sdk/lib/libraries.json')
|
||||
..omitPlatform = true
|
||||
..sdkSummary =
|
||||
soundNullSafety ? sdkSoundSummaryPath : sdkUnsoundSummaryPath
|
||||
..environmentDefines = addGeneratedVariables({}, enableAsserts: true)
|
||||
..nnbdMode = soundNullSafety ? NnbdMode.Strong : NnbdMode.Weak;
|
||||
soundNullSafety ? _sdkSoundSummaryPath : _sdkUnsoundSummaryPath
|
||||
..environmentDefines =
|
||||
addGeneratedVariables({}, enableAsserts: enableAsserts)
|
||||
..nnbdMode = soundNullSafety ? fe.NnbdMode.Strong : fe.NnbdMode.Weak;
|
||||
return options;
|
||||
}
|
||||
|
||||
static final String dartUnsoundComment = '// @dart = 2.9';
|
||||
static final String dartSoundComment = '//';
|
||||
|
||||
final List<String> errors = [];
|
||||
final CompilerOptions options;
|
||||
final String dartLangComment;
|
||||
final ModuleFormat moduleFormat;
|
||||
final bool soundNullSafety;
|
||||
final bool canaryFeatures;
|
||||
|
||||
SetupCompilerOptions({
|
||||
SetupCompilerOptions._({
|
||||
this.enableAsserts = true,
|
||||
this.soundNullSafety = true,
|
||||
this.legacyCode = false,
|
||||
this.moduleFormat = ModuleFormat.amd,
|
||||
this.canaryFeatures = false,
|
||||
}) : options = getOptions(soundNullSafety),
|
||||
dartLangComment =
|
||||
soundNullSafety ? dartSoundComment : dartUnsoundComment {
|
||||
options.onDiagnostic = (DiagnosticMessage m) {
|
||||
errors.addAll(m.plainTextFormatted);
|
||||
}) : options = _getOptions(
|
||||
soundNullSafety: soundNullSafety, enableAsserts: enableAsserts) {
|
||||
options.onDiagnostic = (fe.DiagnosticMessage m) {
|
||||
diagnosticMessages.addAll(m.plainTextFormatted);
|
||||
if (m.severity == fe.Severity.error ||
|
||||
m.severity == fe.Severity.internalProblem) {
|
||||
errors.addAll(m.plainTextFormatted);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
String get loadModule {
|
||||
switch (moduleFormat) {
|
||||
case ModuleFormat.amd:
|
||||
return 'require';
|
||||
case ModuleFormat.ddc:
|
||||
return 'dart_library.import';
|
||||
default:
|
||||
throw UnsupportedError('Module format: $moduleFormat');
|
||||
/// Creates current compiler setup options.
|
||||
///
|
||||
/// Reads options determined by the test configuration from the configuration
|
||||
/// environment variable set by the test runner.
|
||||
///
|
||||
/// To run tests locally using test.py, pass a vm option defining required
|
||||
/// configuration, for example:
|
||||
///
|
||||
/// `./tools/test.py -n web-dev-canary-unittest-asserts-mac`
|
||||
///
|
||||
/// To run a single test locally, pass the --canary or --enable-asserts flags
|
||||
/// to the command line to enable corresponding features, for example:
|
||||
///
|
||||
/// `dart test/expression_compiler/assertions_enabled_test.dart --canary --enable-asserts`
|
||||
factory SetupCompilerOptions({
|
||||
bool soundNullSafety = true,
|
||||
bool legacyCode = false,
|
||||
ModuleFormat moduleFormat = ModuleFormat.amd,
|
||||
List<String> args = const <String>[],
|
||||
}) {
|
||||
// Find if the test is run with arguments overriding the configuration
|
||||
late bool enableAsserts;
|
||||
late bool canaryFeatures;
|
||||
|
||||
// Read configuration settings from matrix.json
|
||||
var configuration = String.fromEnvironment('test_runner.configuration');
|
||||
if (configuration.isEmpty) {
|
||||
// If not running from test runner, read options from the args
|
||||
enableAsserts = args.contains('--enable-asserts');
|
||||
canaryFeatures = args.contains('--canary');
|
||||
} else {
|
||||
// If running from the test runner, read options from the environment
|
||||
// (set to configuration settings from matrix.json).
|
||||
enableAsserts = configuration.contains('-asserts-');
|
||||
canaryFeatures = configuration.contains('-canary-');
|
||||
}
|
||||
return SetupCompilerOptions._(
|
||||
enableAsserts: enableAsserts,
|
||||
soundNullSafety: soundNullSafety,
|
||||
legacyCode: legacyCode,
|
||||
moduleFormat: moduleFormat,
|
||||
canaryFeatures: canaryFeatures,
|
||||
);
|
||||
}
|
||||
|
||||
String get loadModule =>
|
||||
moduleFormat == ModuleFormat.amd ? 'require' : 'dart_library.import';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue