Index: tests/compiler/dart2js/inference/inference_test_helper.dart |
diff --git a/tests/compiler/dart2js/inference/inference_test_helper.dart b/tests/compiler/dart2js/inference/inference_test_helper.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4a916afe0df34900c57938c3e3e1b98c32664275 |
--- /dev/null |
+++ b/tests/compiler/dart2js/inference/inference_test_helper.dart |
@@ -0,0 +1,106 @@ |
+// Copyright (c) 2017, 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:compiler/src/common.dart'; |
+import 'package:compiler/src/compiler.dart'; |
+import 'package:compiler/src/elements/elements.dart'; |
+import 'package:compiler/src/resolution/tree_elements.dart'; |
+import 'package:compiler/src/tree/nodes.dart'; |
+import 'package:compiler/src/types/types.dart'; |
+import 'package:expect/expect.dart'; |
+ |
+import '../annotated_code_helper.dart'; |
+import '../memory_compiler.dart'; |
+import 'enumerator.dart'; |
+ |
+checkCode(String annotatedCode) async { |
+ AnnotatedCode code = new AnnotatedCode(annotatedCode); |
+ Map<Id, String> expectedMap = computeExpectedMap(code); |
+ Compiler compiler = |
+ compilerFor(memorySourceFiles: {'main.dart': code.sourceCode}); |
+ compiler.stopAfterTypeInference = true; |
+ Uri mainUri = Uri.parse('memory:main.dart'); |
+ await compiler.run(mainUri); |
+ compiler.mainApp.forEachLocalMember((member) { |
+ if (member.isFunction) { |
+ checkMember(compiler, expectedMap, member); |
+ } else if (member.isClass) { |
+ member.forEachLocalMember((member) { |
+ checkMember(compiler, expectedMap, member); |
+ }); |
+ } |
+ }); |
+ expectedMap.forEach((Id id, String expected) { |
+ reportHere( |
+ compiler.reporter, |
+ new SourceSpan(mainUri, id.value, id.value + 1), |
+ 'expected:${expected},actual:null'); |
+ }); |
+} |
+ |
+void checkMember( |
+ Compiler compiler, Map<Id, String> expectedMap, MemberElement member) { |
+ ResolvedAst resolvedAst = member.resolvedAst; |
+ if (resolvedAst.kind != ResolvedAstKind.PARSED) return; |
+ compiler.reporter.withCurrentElement(member.implementation, () { |
+ resolvedAst.node.accept(new TypeMaskChecker( |
+ compiler.reporter, |
+ expectedMap, |
+ resolvedAst.elements, |
+ compiler.globalInference.results.resultOf(member))); |
+ }); |
+} |
+ |
+Map<Id, String> computeExpectedMap(AnnotatedCode code) { |
+ Map<Id, String> map = <Id, String>{}; |
+ for (Annotation annotation in code.annotations) { |
+ map[new Id(annotation.offset)] = annotation.text; |
+ } |
+ return map; |
+} |
+ |
+class TypeMaskChecker extends Visitor with AstEnumeratorMixin { |
+ final DiagnosticReporter reporter; |
+ final Map<Id, String> expectedMap; |
+ final TreeElements elements; |
+ final GlobalTypeInferenceElementResult result; |
+ |
+ TypeMaskChecker(this.reporter, this.expectedMap, this.elements, this.result); |
+ |
+ visitNode(Node node) { |
+ node.visitChildren(this); |
+ } |
+ |
+ String annotationForId(Id id) { |
+ if (id == null) return null; |
+ return expectedMap.remove(id); |
+ } |
+ |
+ void checkValue(Node node, String expected, TypeMask value) { |
+ if (value != null || expected != null) { |
+ String valueText = '$value'; |
+ if (valueText != expected) { |
+ reportHere(reporter, node, 'expected:${expected},actual:${value}'); |
+ } |
+ Expect.equals(expected, valueText); |
+ } |
+ } |
+ |
+ void checkSend(Send node) { |
+ Id id = computeId(node); |
+ TypeMask value = result.typeOfSend(node); |
+ String expected = annotationForId(id); |
+ checkValue(node, expected, value); |
+ } |
+ |
+ visitSend(Send node) { |
+ checkSend(node); |
+ visitNode(node); |
+ } |
+ |
+ visitSendSet(SendSet node) { |
+ checkSend(node); |
+ visitNode(node); |
+ } |
+} |