Index: tests/compiler/dart2js/needs_no_such_method_test.dart |
diff --git a/tests/compiler/dart2js/needs_no_such_method_test.dart b/tests/compiler/dart2js/needs_no_such_method_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3dadbb7f6949ec0295d303e66d1918d670355150 |
--- /dev/null |
+++ b/tests/compiler/dart2js/needs_no_such_method_test.dart |
@@ -0,0 +1,293 @@ |
+// 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 'package:async_helper/async_helper.dart'; |
+import 'package:expect/expect.dart'; |
+import 'package:compiler/src/common.dart'; |
+import 'package:compiler/src/elements/elements.dart' |
+ show Element, ClassElement, PublicName; |
+import 'package:compiler/src/universe/call_structure.dart'; |
+import 'package:compiler/src/universe/selector.dart'; |
+import 'package:compiler/src/world.dart' show ClosedWorld, ClassQuery; |
+import 'type_test_helper.dart'; |
+ |
+void main() { |
+ asyncTest(() async { |
+ await testClassSets(); |
+ }); |
+} |
+ |
+const String CLASSES = r""" |
+class Superclass { |
+ foo() {} |
+} |
+class Subclass extends Superclass { |
+ bar() {} |
+} |
+class Subtype implements Superclass { |
+ bar() {} |
+} |
+"""; |
+ |
+testClassSets() async { |
+ Selector foo, bar, baz; |
+ ClosedWorld closedWorld; |
+ ClassElement superclass, subclass, subtype; |
+ |
+ Future run(List<String> instantiated) async { |
+ StringBuffer main = new StringBuffer(); |
+ main.write('main() {'); |
+ for (String cls in instantiated) { |
+ main.write('new $cls();'); |
+ } |
+ main.write('}'); |
+ |
+ var env = await TypeEnvironment.create(CLASSES, |
+ mainSource: main.toString(), useMockCompiler: false); |
+ foo = new Selector.call(const PublicName('foo'), CallStructure.NO_ARGS); |
+ bar = new Selector.call(const PublicName('bar'), CallStructure.NO_ARGS); |
+ baz = new Selector.call(const PublicName('baz'), CallStructure.NO_ARGS); |
+ |
+ closedWorld = env.compiler.closedWorld; |
+ superclass = env.getElement('Superclass'); |
+ subclass = env.getElement('Subclass'); |
+ subtype = env.getElement('Subtype'); |
+ } |
+ |
+ void check(ClassElement cls, ClassQuery query, Selector selector, |
+ bool expectedResult) { |
+ bool result = closedWorld.needsNoSuchMethod(cls, selector, query); |
+ Expect.equals(expectedResult, result, |
+ 'Unexpected result for $selector in $cls ($query)'); |
+ } |
+ |
+ await run([]); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(superclass)); |
+ Expect.isFalse(closedWorld.isImplemented(superclass)); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isImplemented(subclass)); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isImplemented(subtype)); |
+ |
+ check(superclass, ClassQuery.EXACT, foo, false); |
+ check(superclass, ClassQuery.EXACT, bar, false); |
+ check(superclass, ClassQuery.EXACT, baz, false); |
+ check(superclass, ClassQuery.SUBCLASS, foo, false); |
+ check(superclass, ClassQuery.SUBCLASS, bar, false); |
+ check(superclass, ClassQuery.SUBCLASS, baz, false); |
+ check(superclass, ClassQuery.SUBTYPE, foo, false); |
+ check(superclass, ClassQuery.SUBTYPE, bar, false); |
+ check(superclass, ClassQuery.SUBTYPE, baz, false); |
+ |
+ check(subclass, ClassQuery.EXACT, foo, false); |
+ check(subclass, ClassQuery.EXACT, bar, false); |
+ check(subclass, ClassQuery.EXACT, baz, false); |
+ check(subclass, ClassQuery.SUBCLASS, foo, false); |
+ check(subclass, ClassQuery.SUBCLASS, bar, false); |
+ check(subclass, ClassQuery.SUBCLASS, baz, false); |
+ check(subclass, ClassQuery.SUBTYPE, foo, false); |
+ check(subclass, ClassQuery.SUBTYPE, bar, false); |
+ check(subclass, ClassQuery.SUBTYPE, baz, false); |
+ |
+ check(subtype, ClassQuery.EXACT, foo, false); |
+ check(subtype, ClassQuery.EXACT, bar, false); |
+ check(subtype, ClassQuery.EXACT, baz, false); |
+ check(subtype, ClassQuery.SUBCLASS, foo, false); |
+ check(subtype, ClassQuery.SUBCLASS, bar, false); |
+ check(subtype, ClassQuery.SUBCLASS, baz, false); |
+ check(subtype, ClassQuery.SUBTYPE, foo, false); |
+ check(subtype, ClassQuery.SUBTYPE, bar, false); |
+ check(subtype, ClassQuery.SUBTYPE, baz, false); |
+ |
+ await run(['Superclass']); |
+ |
+ Expect.isTrue(closedWorld.isDirectlyInstantiated(superclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(superclass)); |
+ Expect.isTrue(closedWorld.isImplemented(superclass)); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isImplemented(subclass)); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isImplemented(subtype)); |
+ |
+ check(superclass, ClassQuery.EXACT, foo, false); |
+ check(superclass, ClassQuery.EXACT, bar, true); |
+ check(superclass, ClassQuery.EXACT, baz, true); |
+ check(superclass, ClassQuery.SUBCLASS, foo, false); |
+ check(superclass, ClassQuery.SUBCLASS, bar, true); |
+ check(superclass, ClassQuery.SUBCLASS, baz, true); |
+ check(superclass, ClassQuery.SUBTYPE, foo, false); |
+ check(superclass, ClassQuery.SUBTYPE, bar, true); |
+ check(superclass, ClassQuery.SUBTYPE, baz, true); |
+ |
+ check(subclass, ClassQuery.EXACT, foo, false); |
+ check(subclass, ClassQuery.EXACT, bar, false); |
+ check(subclass, ClassQuery.EXACT, baz, false); |
+ check(subclass, ClassQuery.SUBCLASS, foo, false); |
+ check(subclass, ClassQuery.SUBCLASS, bar, false); |
+ check(subclass, ClassQuery.SUBCLASS, baz, false); |
+ check(subclass, ClassQuery.SUBTYPE, foo, false); |
+ check(subclass, ClassQuery.SUBTYPE, bar, false); |
+ check(subclass, ClassQuery.SUBTYPE, baz, false); |
+ |
+ check(subtype, ClassQuery.EXACT, foo, false); |
+ check(subtype, ClassQuery.EXACT, bar, false); |
+ check(subtype, ClassQuery.EXACT, baz, false); |
+ check(subtype, ClassQuery.SUBCLASS, foo, false); |
+ check(subtype, ClassQuery.SUBCLASS, bar, false); |
+ check(subtype, ClassQuery.SUBCLASS, baz, false); |
+ check(subtype, ClassQuery.SUBTYPE, foo, false); |
+ check(subtype, ClassQuery.SUBTYPE, bar, false); |
+ check(subtype, ClassQuery.SUBTYPE, baz, false); |
+ |
+ await run(['Subclass']); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass)); |
+ Expect.isTrue(closedWorld.isIndirectlyInstantiated(superclass)); |
+ Expect.isTrue(closedWorld.isImplemented(superclass)); |
+ |
+ Expect.isTrue(closedWorld.isDirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass)); |
+ Expect.isTrue(closedWorld.isImplemented(subclass)); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isImplemented(subtype)); |
+ |
+ check(superclass, ClassQuery.EXACT, foo, false); |
+ // Should be false since the class is not directly instantiated: |
+ check(superclass, ClassQuery.EXACT, bar, true); |
+ // Should be false since the class is not directly instantiated: |
+ check(superclass, ClassQuery.EXACT, baz, true); |
+ check(superclass, ClassQuery.SUBCLASS, foo, false); |
+ // Should be false since all live subclasses have a concrete implementation: |
+ check(superclass, ClassQuery.SUBCLASS, bar, true); |
+ check(superclass, ClassQuery.SUBCLASS, baz, true); |
+ check(superclass, ClassQuery.SUBTYPE, foo, false); |
+ // Should be false since all live subtypes have a concrete implementation: |
+ check(superclass, ClassQuery.SUBTYPE, bar, true); |
+ check(superclass, ClassQuery.SUBTYPE, baz, true); |
+ |
+ check(subclass, ClassQuery.EXACT, foo, false); |
+ check(subclass, ClassQuery.EXACT, bar, false); |
+ check(subclass, ClassQuery.EXACT, baz, true); |
+ check(subclass, ClassQuery.SUBCLASS, foo, false); |
+ check(subclass, ClassQuery.SUBCLASS, bar, false); |
+ check(subclass, ClassQuery.SUBCLASS, baz, true); |
+ check(subclass, ClassQuery.SUBTYPE, foo, false); |
+ check(subclass, ClassQuery.SUBTYPE, bar, false); |
+ check(subclass, ClassQuery.SUBTYPE, baz, true); |
+ |
+ check(subtype, ClassQuery.EXACT, foo, false); |
+ check(subtype, ClassQuery.EXACT, bar, false); |
+ check(subtype, ClassQuery.EXACT, baz, false); |
+ check(subtype, ClassQuery.SUBCLASS, foo, false); |
+ check(subtype, ClassQuery.SUBCLASS, bar, false); |
+ check(subtype, ClassQuery.SUBCLASS, baz, false); |
+ check(subtype, ClassQuery.SUBTYPE, foo, false); |
+ check(subtype, ClassQuery.SUBTYPE, bar, false); |
+ check(subtype, ClassQuery.SUBTYPE, baz, false); |
+ |
+ await run(['Subtype']); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(superclass)); |
+ Expect.isTrue(closedWorld.isImplemented(superclass)); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isImplemented(subclass)); |
+ |
+ Expect.isTrue(closedWorld.isDirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype)); |
+ Expect.isTrue(closedWorld.isImplemented(subtype)); |
+ |
+ check(superclass, ClassQuery.EXACT, foo, false); |
+ check(superclass, ClassQuery.EXACT, bar, false); |
+ check(superclass, ClassQuery.EXACT, baz, false); |
+ check(superclass, ClassQuery.SUBCLASS, foo, false); |
+ check(superclass, ClassQuery.SUBCLASS, bar, false); |
+ check(superclass, ClassQuery.SUBCLASS, baz, false); |
+ check(superclass, ClassQuery.SUBTYPE, foo, true); |
+ check(superclass, ClassQuery.SUBTYPE, bar, false); |
+ check(superclass, ClassQuery.SUBTYPE, baz, true); |
+ |
+ check(subclass, ClassQuery.EXACT, foo, false); |
+ check(subclass, ClassQuery.EXACT, bar, false); |
+ check(subclass, ClassQuery.EXACT, baz, false); |
+ check(subclass, ClassQuery.SUBCLASS, foo, false); |
+ check(subclass, ClassQuery.SUBCLASS, bar, false); |
+ check(subclass, ClassQuery.SUBCLASS, baz, false); |
+ check(subclass, ClassQuery.SUBTYPE, foo, false); |
+ check(subclass, ClassQuery.SUBTYPE, bar, false); |
+ check(subclass, ClassQuery.SUBTYPE, baz, false); |
+ |
+ check(subtype, ClassQuery.EXACT, foo, true); |
+ check(subtype, ClassQuery.EXACT, bar, false); |
+ check(subtype, ClassQuery.EXACT, baz, true); |
+ check(subtype, ClassQuery.SUBCLASS, foo, true); |
+ check(subtype, ClassQuery.SUBCLASS, bar, false); |
+ check(subtype, ClassQuery.SUBCLASS, baz, true); |
+ check(subtype, ClassQuery.SUBTYPE, foo, true); |
+ check(subtype, ClassQuery.SUBTYPE, bar, false); |
+ check(subtype, ClassQuery.SUBTYPE, baz, true); |
+ |
+ await run(['Subclass', 'Subtype']); |
+ |
+ Expect.isFalse(closedWorld.isDirectlyInstantiated(superclass)); |
+ Expect.isTrue(closedWorld.isIndirectlyInstantiated(superclass)); |
+ Expect.isTrue(closedWorld.isImplemented(superclass)); |
+ |
+ Expect.isTrue(closedWorld.isDirectlyInstantiated(subclass)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subclass)); |
+ Expect.isTrue(closedWorld.isImplemented(subclass)); |
+ |
+ Expect.isTrue(closedWorld.isDirectlyInstantiated(subtype)); |
+ Expect.isFalse(closedWorld.isIndirectlyInstantiated(subtype)); |
+ Expect.isTrue(closedWorld.isImplemented(subtype)); |
+ |
+ check(superclass, ClassQuery.EXACT, foo, false); |
+ // Should be false since the class is not directly instantiated: |
+ check(superclass, ClassQuery.EXACT, bar, true); |
+ // Should be false since the class is not directly instantiated: |
+ check(superclass, ClassQuery.EXACT, baz, true); |
+ check(superclass, ClassQuery.SUBCLASS, foo, false); |
+ // Should be false since all live subclasses have a concrete implementation: |
+ check(superclass, ClassQuery.SUBCLASS, bar, true); |
+ check(superclass, ClassQuery.SUBCLASS, baz, true); |
+ check(superclass, ClassQuery.SUBTYPE, foo, true); |
+ // Should be false since all live subtypes have a concrete implementation: |
+ check(superclass, ClassQuery.SUBTYPE, bar, true); |
+ check(superclass, ClassQuery.SUBTYPE, baz, true); |
+ |
+ check(subclass, ClassQuery.EXACT, foo, false); |
+ check(subclass, ClassQuery.EXACT, bar, false); |
+ check(subclass, ClassQuery.EXACT, baz, true); |
+ check(subclass, ClassQuery.SUBCLASS, foo, false); |
+ check(subclass, ClassQuery.SUBCLASS, bar, false); |
+ check(subclass, ClassQuery.SUBCLASS, baz, true); |
+ check(subclass, ClassQuery.SUBTYPE, foo, false); |
+ check(subclass, ClassQuery.SUBTYPE, bar, false); |
+ check(subclass, ClassQuery.SUBTYPE, baz, true); |
+ |
+ check(subtype, ClassQuery.EXACT, foo, true); |
+ check(subtype, ClassQuery.EXACT, bar, false); |
+ check(subtype, ClassQuery.EXACT, baz, true); |
+ check(subtype, ClassQuery.SUBCLASS, foo, true); |
+ check(subtype, ClassQuery.SUBCLASS, bar, false); |
+ check(subtype, ClassQuery.SUBCLASS, baz, true); |
+ check(subtype, ClassQuery.SUBTYPE, foo, true); |
+ check(subtype, ClassQuery.SUBTYPE, bar, false); |
+ check(subtype, ClassQuery.SUBTYPE, baz, true); |
+} |