c878108cc8
All non-pubspec changes generated by `dart format pkg/compiler`. Change-Id: Iadaa70974816d96ccb47813fe72d5a2bb83d6bda Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400181 Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Mayank Patke <fishythefish@google.com>
224 lines
6.3 KiB
Dart
224 lines
6.3 KiB
Dart
// Copyright (c) 2016, 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:io';
|
|
|
|
import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
|
|
import 'package:compiler/compiler_api.dart' as api;
|
|
import 'package:expect/async_helper.dart';
|
|
import 'package:expect/expect.dart';
|
|
import 'package:source_maps/source_maps.dart';
|
|
|
|
import 'package:compiler/src/util/memory_compiler.dart';
|
|
|
|
const List<String> TESTS = const <String>[
|
|
'''
|
|
@{main}main() {
|
|
@{main}}
|
|
''',
|
|
'''
|
|
@{main}main() {
|
|
@{main}throw '';
|
|
@{main}}
|
|
''',
|
|
'''
|
|
@{main}main() {
|
|
@{main}return 0;
|
|
@{main}}
|
|
''',
|
|
'''
|
|
import 'package:expect/expect.dart';
|
|
@{main}main() {
|
|
@{main}test();
|
|
@{main}}
|
|
|
|
@pragma('dart2js:noInline')
|
|
@{test}test() {
|
|
@{test}}
|
|
''',
|
|
];
|
|
|
|
class Test {
|
|
final String annotatedCode;
|
|
final String code;
|
|
final List<SourceLocation> expectedLocations;
|
|
|
|
Test(this.annotatedCode, this.code, this.expectedLocations);
|
|
}
|
|
|
|
Test processTestCode(String code) {
|
|
List<SourceLocation> expectedLocations = <SourceLocation>[];
|
|
AnnotatedCode annotatedCode = AnnotatedCode.fromText(code);
|
|
for (Annotation annotation in annotatedCode.annotations) {
|
|
String methodName = annotation.text;
|
|
expectedLocations.add(
|
|
SourceLocation(methodName, annotation.lineNo, annotation.columnNo),
|
|
);
|
|
}
|
|
return Test(code, annotatedCode.sourceCode, expectedLocations);
|
|
}
|
|
|
|
void main(List<String> arguments) {
|
|
bool verbose = false;
|
|
bool printJs = false;
|
|
bool writeJs = false;
|
|
List<int>? indices;
|
|
for (String arg in arguments) {
|
|
if (arg == '-v') {
|
|
verbose = true;
|
|
} else if (arg == '--print-js') {
|
|
printJs = true;
|
|
} else if (arg == '--write-js') {
|
|
writeJs = true;
|
|
} else {
|
|
int? index = int.tryParse(arg);
|
|
if (index != null) {
|
|
indices ??= <int>[];
|
|
if (index < 0 || index >= TESTS.length) {
|
|
print('Index $index out of bounds: [0;${TESTS.length - 1}]');
|
|
} else {
|
|
indices.add(index);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (indices == null) {
|
|
indices = List<int>.generate(TESTS.length, (i) => i);
|
|
}
|
|
asyncTest(() async {
|
|
for (int index in indices!) {
|
|
await runTest(
|
|
index,
|
|
processTestCode(TESTS[index]),
|
|
printJs: printJs,
|
|
writeJs: writeJs,
|
|
verbose: verbose,
|
|
);
|
|
}
|
|
});
|
|
}
|
|
|
|
Future runTest(
|
|
int index,
|
|
Test test, {
|
|
bool printJs = false,
|
|
required bool writeJs,
|
|
bool verbose = false,
|
|
}) async {
|
|
print("--$index------------------------------------------------------------");
|
|
print("Compiling dart2js\n ${test.annotatedCode}");
|
|
OutputCollector collector = OutputCollector();
|
|
List<String> options = <String>['--out=out.js', '--source-map=out.js.map'];
|
|
CompilationResult compilationResult = await runCompiler(
|
|
entryPoint: Uri.parse('memory:main.dart'),
|
|
memorySourceFiles: {'main.dart': test.code},
|
|
outputProvider: collector,
|
|
options: options,
|
|
);
|
|
Expect.isTrue(
|
|
compilationResult.isSuccess,
|
|
"Unsuccessful compilation of test:\n${test.code}",
|
|
);
|
|
String sourceMapText = collector.getOutput('', api.OutputType.sourceMap)!;
|
|
final sourceMap = parse(sourceMapText) as SingleMapping;
|
|
if (writeJs) {
|
|
File(
|
|
'out.js',
|
|
).writeAsStringSync(collector.getOutput('', api.OutputType.js)!);
|
|
File('out.js.map').writeAsStringSync(sourceMapText);
|
|
}
|
|
|
|
Set<SourceLocation> expectedLocations = test.expectedLocations.toSet();
|
|
List<SourceLocation> actualLocations = <SourceLocation>[];
|
|
List<SourceLocation> extraLocations = <SourceLocation>[];
|
|
for (TargetLineEntry targetLineEntry in sourceMap.lines) {
|
|
for (TargetEntry targetEntry in targetLineEntry.entries) {
|
|
if (targetEntry.sourceUrlId != null &&
|
|
sourceMap.urls[targetEntry.sourceUrlId!] == 'memory:main.dart') {
|
|
String? methodName;
|
|
if (targetEntry.sourceNameId != null) {
|
|
methodName = sourceMap.names[targetEntry.sourceNameId!];
|
|
}
|
|
SourceLocation location = SourceLocation(
|
|
methodName,
|
|
targetEntry.sourceLine! + 1,
|
|
targetEntry.sourceColumn! + 1,
|
|
);
|
|
actualLocations.add(location);
|
|
if (!expectedLocations.remove(location)) {
|
|
extraLocations.add(location);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (expectedLocations.isNotEmpty) {
|
|
print('--Missing source locations:---------------------------------------');
|
|
AnnotatedCode annotatedCode = AnnotatedCode(test.code, test.code, []);
|
|
expectedLocations.forEach(
|
|
(l) => annotatedCode.addAnnotation(
|
|
l.lineNo,
|
|
l.columnNo,
|
|
'/*',
|
|
l.methodName!,
|
|
'*/',
|
|
),
|
|
);
|
|
print(annotatedCode.toText());
|
|
print('------------------------------------------------------------------');
|
|
Expect.isTrue(
|
|
expectedLocations.isEmpty,
|
|
"Missing source locations:\n${test.code}\n"
|
|
"Actual:\n${actualLocations.join('\n')}\n"
|
|
"Missing:\n${expectedLocations.join('\n')}\n",
|
|
);
|
|
}
|
|
if (extraLocations.isNotEmpty) {
|
|
print('--Extra source locations:-----------------------------------------');
|
|
AnnotatedCode annotatedCode = AnnotatedCode(test.code, test.code, []);
|
|
extraLocations.forEach(
|
|
(l) => annotatedCode.addAnnotation(
|
|
l.lineNo,
|
|
l.columnNo,
|
|
'/*',
|
|
l.methodName!,
|
|
'*/',
|
|
),
|
|
);
|
|
print(annotatedCode.toText());
|
|
print('------------------------------------------------------------------');
|
|
Expect.isTrue(
|
|
extraLocations.isEmpty,
|
|
"Extra source locations:\n${test.code}\n"
|
|
"Actual:\n${actualLocations.join('\n')}\n"
|
|
"Extra:\n${extraLocations.join('\n')}\n",
|
|
);
|
|
}
|
|
}
|
|
|
|
class SourceLocation {
|
|
final String? methodName;
|
|
final int lineNo;
|
|
final int columnNo;
|
|
|
|
SourceLocation(this.methodName, this.lineNo, this.columnNo);
|
|
|
|
@override
|
|
int get hashCode =>
|
|
methodName.hashCode * 13 + lineNo.hashCode * 17 + columnNo.hashCode * 19;
|
|
|
|
@override
|
|
bool operator ==(other) {
|
|
if (identical(this, other)) return true;
|
|
if (other is! SourceLocation) return false;
|
|
return methodName == other.methodName &&
|
|
lineNo == other.lineNo &&
|
|
columnNo == other.columnNo;
|
|
}
|
|
|
|
@override
|
|
String toString() => '$methodName:$lineNo:$columnNo';
|
|
}
|