blob: 29a42adb91721ee62aa92f5ce52b30d2ae00310c [file] [log] [blame]
// Copyright (c) 2015, 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.
// VMOptions=-DUSE_CPS_IR=true
// Test that the CPS IR code generator generates source information.
library source_information_tests;
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
import 'package:compiler/src/apiimpl.dart'
show Compiler;
import 'memory_compiler.dart';
import 'package:compiler/src/cps_ir/cps_ir_nodes.dart' as ir;
import 'package:compiler/src/cps_ir/cps_ir_nodes_sexpr.dart' as ir;
import 'package:compiler/src/js/js.dart' as js;
import 'package:compiler/src/common.dart' show Element, ClassElement;
const String TEST_MAIN_FILE = 'test.dart';
class TestEntry {
final String source;
final List<String> expectation;
final String elementName;
const TestEntry(this.source, this.expectation)
: elementName = null;
const TestEntry.forMethod(this.elementName,
this.source, this.expectation);
}
String formatTest(Map test) {
return test[TEST_MAIN_FILE];
}
js.Node getCodeForMain(Compiler compiler) {
Element mainFunction = compiler.mainFunction;
return compiler.enqueuer.codegen.generatedCode[mainFunction];
}
js.Node getJsNodeForElement(Compiler compiler,
Element element) {
return compiler.enqueuer.codegen.generatedCode[element];
}
ir.ExecutableDefinition getIrNodeForElement(Compiler compiler,
Element element) {
return compiler.irBuilder.getIr(element);
}
String getCodeForMethod(Compiler compiler,
String name) {
Element foundElement;
for (Element element in compiler.enqueuer.codegen.generatedCode.keys) {
if (element.toString() == name) {
if (foundElement != null) {
Expect.fail('Multiple compiled elements are called $name');
}
foundElement = element;
}
}
if (foundElement == null) {
Expect.fail('There is no compiled element called $name');
}
js.Node ast = compiler.enqueuer.codegen.generatedCode[foundElement];
return js.prettyPrint(ast, compiler).getText();
}
runTests(List<TestEntry> tests) {
Expect.isTrue(const bool.fromEnvironment("USE_CPS_IR"),
'Run with USE_CPS_IR=true');
for (TestEntry test in tests) {
Map files = {TEST_MAIN_FILE: test.source};
asyncTest(() {
Compiler compiler = compilerFor(files);
Uri uri = Uri.parse('memory:$TEST_MAIN_FILE');
return compiler.run(uri).then((bool success) {
Expect.isTrue(success);
ir.Node irNode = getIrNodeForElement(compiler, compiler.mainFunction);
IrSourceInformationVisitor irVisitor = new IrSourceInformationVisitor();
irNode.accept(irVisitor);
js.Node jsNode = getJsNodeForElement(compiler, compiler.mainFunction);
JsSourceInformationVisitor jsVisitor = new JsSourceInformationVisitor();
jsNode.accept(jsVisitor);
List<String> expectation = test.expectation;
// Visiting of CPS is in structural order so we check for set equality.
Expect.setEquals(expectation, irVisitor.sourceInformation,
'Unexpected IR source information. '
'Expected:\n$expectation\n'
'but found\n${irVisitor.sourceInformation}\n'
'in\n${test.source}'
'CPS:\n${irNode.accept(new ir.SExpressionStringifier())}');
Expect.listEquals(expectation, jsVisitor.sourceInformation,
'Unexpected JS source information. '
'Expected:\n$expectation\n'
'but found\n${jsVisitor.sourceInformation}\n'
'in\n${test.source}');
}).catchError((e) {
print(e);
Expect.fail('The following test failed to compile:\n'
'${formatTest(files)}');
});
});
}
}
class JsSourceInformationVisitor extends js.BaseVisitor {
List<String> sourceInformation = <String>[];
@override
visitCall(js.Call node) {
sourceInformation.add('${node.sourceInformation}');
super.visitCall(node);
}
}
class IrSourceInformationVisitor extends ir.RecursiveVisitor {
List<String> sourceInformation = <String>[];
@override
processInvokeStatic(ir.InvokeStatic node) {
sourceInformation.add('${node.sourceInformation}');
}
}
const List<TestEntry> tests = const [
const TestEntry("""
main() { print('Hello World'); }
""", const ['memory:test.dart:[1,10]']),
const TestEntry("""
main() {
print('Hello');
print('World');
}
""", const ['memory:test.dart:[2,3]',
'memory:test.dart:[3,3]']),
];
void main() {
runTests(tests);
}