| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Test for iterators on for [SubclassNode]. | 5 // Test for iterators on for [SubclassNode]. |
| 6 | 6 |
| 7 library class_set_test; | 7 library class_set_test; |
| 8 | 8 |
| 9 import 'package:expect/expect.dart'; | 9 import 'package:expect/expect.dart'; |
| 10 import 'package:async_helper/async_helper.dart'; | 10 import 'package:async_helper/async_helper.dart'; |
| 11 import 'type_test_helper.dart'; | 11 import 'type_test_helper.dart'; |
| 12 import 'package:compiler/src/elements/elements.dart' | 12 import 'package:compiler/src/elements/elements.dart' |
| 13 show Element, ClassElement; | 13 show Element, ClassElement; |
| 14 import 'package:compiler/src/universe/class_set.dart'; | 14 import 'package:compiler/src/universe/class_set.dart'; |
| 15 import 'package:compiler/src/util/enumset.dart'; | 15 import 'package:compiler/src/util/enumset.dart'; |
| 16 import 'package:compiler/src/util/util.dart'; | 16 import 'package:compiler/src/util/util.dart'; |
| 17 import 'package:compiler/src/world.dart'; | 17 import 'package:compiler/src/world.dart'; |
| 18 | 18 |
| 19 void main() { | 19 void main() { |
| 20 asyncTest(() async { | 20 asyncTest(() => TypeEnvironment.create(r""" |
| 21 await testIterators(); | |
| 22 await testForEach(); | |
| 23 }); | |
| 24 } | |
| 25 | |
| 26 testIterators() async { | |
| 27 var env = await TypeEnvironment.create(r""" | |
| 28 /// A | 21 /// A |
| 29 /// / \ | 22 /// / \ |
| 30 /// B C | 23 /// B C |
| 31 /// / /|\ | 24 /// / /|\ |
| 32 /// D E F G | 25 /// D E F G |
| 33 /// | 26 /// |
| 34 class A {} | 27 class A {} |
| 35 class B extends A {} | 28 class B extends A {} |
| 36 class C extends A {} | 29 class C extends A {} |
| 37 class D extends B {} | 30 class D extends B {} |
| 38 class E extends C {} | 31 class E extends C {} |
| 39 class F extends C {} | 32 class F extends C {} |
| 40 class G extends C {} | 33 class G extends C {} |
| 41 """, | 34 """, |
| 42 mainSource: r""" | 35 mainSource: r""" |
| 43 main() { | 36 main() { |
| 44 new A(); | 37 new A(); |
| 45 new C(); | 38 new C(); |
| 46 new D(); | 39 new D(); |
| 47 new E(); | 40 new E(); |
| 48 new F(); | 41 new F(); |
| 49 new G(); | 42 new G(); |
| 50 } | 43 } |
| 51 """, | 44 """, |
| 52 useMockCompiler: false); | 45 useMockCompiler: false).then((env) { |
| 53 World world = env.compiler.world; | 46 World world = env.compiler.world; |
| 54 | 47 |
| 55 ClassElement A = env.getElement("A"); | 48 ClassElement A = env.getElement("A"); |
| 56 ClassElement B = env.getElement("B"); | 49 ClassElement B = env.getElement("B"); |
| 57 ClassElement C = env.getElement("C"); | 50 ClassElement C = env.getElement("C"); |
| 58 ClassElement D = env.getElement("D"); | 51 ClassElement D = env.getElement("D"); |
| 59 ClassElement E = env.getElement("E"); | 52 ClassElement E = env.getElement("E"); |
| 60 ClassElement F = env.getElement("F"); | 53 ClassElement F = env.getElement("F"); |
| 61 ClassElement G = env.getElement("G"); | 54 ClassElement G = env.getElement("G"); |
| 62 | 55 |
| 63 void checkClass(ClassElement cls, | 56 void checkClass(ClassElement cls, |
| 64 {bool directlyInstantiated: false, | 57 {bool directlyInstantiated: false, |
| 65 bool indirectlyInstantiated: false}) { | 58 bool indirectlyInstantiated: false}) { |
| 66 ClassHierarchyNode node = world.getClassHierarchyNode(cls); | 59 ClassHierarchyNode node = world.getClassHierarchyNode(cls); |
| 67 Expect.isNotNull(node, "Expected ClassHierarchyNode for $cls."); | 60 Expect.isNotNull(node, "Expected ClassHierarchyNode for $cls."); |
| 68 Expect.equals( | 61 Expect.equals( |
| 69 directlyInstantiated || indirectlyInstantiated, | 62 directlyInstantiated || indirectlyInstantiated, |
| 70 node.isInstantiated, | 63 node.isInstantiated, |
| 71 "Unexpected `isInstantiated` on ClassHierarchyNode for $cls."); | 64 "Unexpected `isInstantiated` on ClassHierarchyNode for $cls."); |
| 72 Expect.equals( | 65 Expect.equals( |
| 73 directlyInstantiated, | 66 directlyInstantiated, |
| 74 node.isDirectlyInstantiated, | 67 node.isDirectlyInstantiated, |
| 75 "Unexpected `isDirectlyInstantiated` on ClassHierarchyNode for " | 68 "Unexpected `isDirectlyInstantiated` on ClassHierarchyNode for " |
| 76 "$cls."); | 69 "$cls."); |
| 77 Expect.equals( | 70 Expect.equals( |
| 78 indirectlyInstantiated, | 71 indirectlyInstantiated, |
| 79 node.isIndirectlyInstantiated, | 72 node.isIndirectlyInstantiated, |
| 80 "Unexpected `isIndirectlyInstantiated` on ClassHierarchyNode for " | 73 "Unexpected `isIndirectlyInstantiated` on ClassHierarchyNode for " |
| 81 "$cls."); | 74 "$cls."); |
| 82 } | |
| 83 | |
| 84 | |
| 85 checkClass(A, directlyInstantiated: true, indirectlyInstantiated: true); | |
| 86 checkClass(B, indirectlyInstantiated: true); | |
| 87 checkClass(C, directlyInstantiated: true, indirectlyInstantiated: true); | |
| 88 checkClass(D, directlyInstantiated: true); | |
| 89 checkClass(E, directlyInstantiated: true); | |
| 90 checkClass(F, directlyInstantiated: true); | |
| 91 checkClass(G, directlyInstantiated: true); | |
| 92 | |
| 93 ClassHierarchyNodeIterator iterator; | |
| 94 | |
| 95 void checkState( | |
| 96 ClassElement root, | |
| 97 {ClassElement currentNode, | |
| 98 List<List<ClassElement>> stack}) { | |
| 99 | |
| 100 ClassElement classOf(ClassHierarchyNode node) { | |
| 101 return node != null ? node.cls : null; | |
| 102 } | 75 } |
| 103 | 76 |
| 104 List<ClassElement> classesOf(Link<ClassHierarchyNode> link) { | 77 |
| 105 if (link == null) return null; | 78 checkClass(A, directlyInstantiated: true, indirectlyInstantiated: true); |
| 106 return link.map(classOf).toList(); | 79 checkClass(B, indirectlyInstantiated: true); |
| 80 checkClass(C, directlyInstantiated: true, indirectlyInstantiated: true); |
| 81 checkClass(D, directlyInstantiated: true); |
| 82 checkClass(E, directlyInstantiated: true); |
| 83 checkClass(F, directlyInstantiated: true); |
| 84 checkClass(G, directlyInstantiated: true); |
| 85 |
| 86 ClassHierarchyNodeIterator iterator; |
| 87 |
| 88 void checkState( |
| 89 ClassElement root, |
| 90 {ClassElement currentNode, |
| 91 List<List<ClassElement>> stack}) { |
| 92 |
| 93 ClassElement classOf(ClassHierarchyNode node) { |
| 94 return node != null ? node.cls : null; |
| 95 } |
| 96 |
| 97 List<ClassElement> classesOf(Link<ClassHierarchyNode> link) { |
| 98 if (link == null) return null; |
| 99 return link.map(classOf).toList(); |
| 100 } |
| 101 |
| 102 ClassElement foundRoot = iterator.root.cls; |
| 103 ClassElement foundCurrentNode = classOf(iterator.currentNode); |
| 104 List<ClassElement> foundStack = classesOf(iterator.stack); |
| 105 |
| 106 StringBuffer sb = new StringBuffer(); |
| 107 sb.write('{\n root: $foundRoot'); |
| 108 sb.write('\n currentNode: $foundCurrentNode'); |
| 109 sb.write('\n stack: $foundStack\n}'); |
| 110 |
| 111 Expect.equals(root, foundRoot, |
| 112 "Expected root $root in $sb."); |
| 113 if (currentNode == null) { |
| 114 Expect.isNull(iterator.currentNode, |
| 115 "Unexpected non-null currentNode in $sb."); |
| 116 } else { |
| 117 Expect.isNotNull(foundCurrentNode, |
| 118 "Expected non-null currentNode ${currentNode} in $sb."); |
| 119 Expect.equals(currentNode, foundCurrentNode, |
| 120 "Expected currentNode $currentNode in $sb."); |
| 121 } |
| 122 if (stack == null) { |
| 123 Expect.isNull(foundStack, |
| 124 "Unexpected non-null stack in $sb."); |
| 125 } else { |
| 126 Expect.isNotNull(foundStack, |
| 127 "Expected non-null stack ${stack} in $sb."); |
| 128 Expect.listEquals(stack, foundStack, |
| 129 "Expected stack ${stack}, " |
| 130 "found ${foundStack} in $sb."); |
| 131 } |
| 107 } | 132 } |
| 108 | 133 |
| 109 ClassElement foundRoot = iterator.root.cls; | 134 iterator = new ClassHierarchyNodeIterable( |
| 110 ClassElement foundCurrentNode = classOf(iterator.currentNode); | 135 world.getClassHierarchyNode(G), |
| 111 List<ClassElement> foundStack = classesOf(iterator.stack); | 136 ClassHierarchyNode.ALL).iterator; |
| 112 | 137 checkState(G, currentNode: null, stack: null); |
| 113 StringBuffer sb = new StringBuffer(); | 138 Expect.isNull(iterator.current); |
| 114 sb.write('{\n root: $foundRoot'); | 139 Expect.isTrue(iterator.moveNext()); |
| 115 sb.write('\n currentNode: $foundCurrentNode'); | 140 checkState(G, currentNode: G, stack: []); |
| 116 sb.write('\n stack: $foundStack\n}'); | 141 Expect.equals(G, iterator.current); |
| 117 | 142 Expect.isFalse(iterator.moveNext()); |
| 118 Expect.equals(root, foundRoot, | 143 checkState(G, currentNode: null, stack: []); |
| 119 "Expected root $root in $sb."); | 144 Expect.isNull(iterator.current); |
| 120 if (currentNode == null) { | 145 |
| 121 Expect.isNull(iterator.currentNode, | 146 iterator = new ClassHierarchyNodeIterable( |
| 122 "Unexpected non-null currentNode in $sb."); | 147 world.getClassHierarchyNode(G), |
| 123 } else { | 148 ClassHierarchyNode.ALL, |
| 124 Expect.isNotNull(foundCurrentNode, | 149 includeRoot: false).iterator; |
| 125 "Expected non-null currentNode ${currentNode} in $sb."); | 150 checkState(G, currentNode: null, stack: null); |
| 126 Expect.equals(currentNode, foundCurrentNode, | 151 Expect.isNull(iterator.current); |
| 127 "Expected currentNode $currentNode in $sb."); | 152 Expect.isFalse(iterator.moveNext()); |
| 128 } | 153 checkState(G, currentNode: null, stack: []); |
| 129 if (stack == null) { | 154 Expect.isNull(iterator.current); |
| 130 Expect.isNull(foundStack, | 155 |
| 131 "Unexpected non-null stack in $sb."); | 156 iterator = new ClassHierarchyNodeIterable( |
| 132 } else { | 157 world.getClassHierarchyNode(C), |
| 133 Expect.isNotNull(foundStack, | 158 ClassHierarchyNode.ALL).iterator; |
| 134 "Expected non-null stack ${stack} in $sb."); | 159 checkState(C, currentNode: null, stack: null); |
| 135 Expect.listEquals(stack, foundStack, | 160 Expect.isNull(iterator.current); |
| 136 "Expected stack ${stack}, " | 161 Expect.isTrue(iterator.moveNext()); |
| 137 "found ${foundStack} in $sb."); | 162 checkState(C, currentNode: C, stack: [E, F, G]); |
| 138 } | 163 Expect.equals(C, iterator.current); |
| 139 } | 164 Expect.isTrue(iterator.moveNext()); |
| 140 | 165 checkState(C, currentNode: E, stack: [F, G]); |
| 141 iterator = new ClassHierarchyNodeIterable( | 166 Expect.equals(E, iterator.current); |
| 142 world.getClassHierarchyNode(G), | 167 Expect.isTrue(iterator.moveNext()); |
| 143 ClassHierarchyNode.ALL).iterator; | 168 checkState(C, currentNode: F, stack: [G]); |
| 144 checkState(G, currentNode: null, stack: null); | 169 Expect.equals(F, iterator.current); |
| 145 Expect.isNull(iterator.current); | 170 Expect.isTrue(iterator.moveNext()); |
| 146 Expect.isTrue(iterator.moveNext()); | 171 checkState(C, currentNode: G, stack: []); |
| 147 checkState(G, currentNode: G, stack: []); | 172 Expect.equals(G, iterator.current); |
| 148 Expect.equals(G, iterator.current); | 173 Expect.isFalse(iterator.moveNext()); |
| 149 Expect.isFalse(iterator.moveNext()); | 174 checkState(C, currentNode: null, stack: []); |
| 150 checkState(G, currentNode: null, stack: []); | 175 Expect.isNull(iterator.current); |
| 151 Expect.isNull(iterator.current); | 176 |
| 152 | 177 iterator = new ClassHierarchyNodeIterable( |
| 153 iterator = new ClassHierarchyNodeIterable( | 178 world.getClassHierarchyNode(D), |
| 154 world.getClassHierarchyNode(G), | 179 ClassHierarchyNode.ALL).iterator; |
| 155 ClassHierarchyNode.ALL, | 180 checkState(D, currentNode: null, stack: null); |
| 156 includeRoot: false).iterator; | 181 Expect.isNull(iterator.current); |
| 157 checkState(G, currentNode: null, stack: null); | 182 Expect.isTrue(iterator.moveNext()); |
| 158 Expect.isNull(iterator.current); | 183 checkState(D, currentNode: D, stack: []); |
| 159 Expect.isFalse(iterator.moveNext()); | 184 Expect.equals(D, iterator.current); |
| 160 checkState(G, currentNode: null, stack: []); | 185 Expect.isFalse(iterator.moveNext()); |
| 161 Expect.isNull(iterator.current); | 186 checkState(D, currentNode: null, stack: []); |
| 162 | 187 Expect.isNull(iterator.current); |
| 163 iterator = new ClassHierarchyNodeIterable( | 188 |
| 164 world.getClassHierarchyNode(C), | 189 iterator = new ClassHierarchyNodeIterable( |
| 165 ClassHierarchyNode.ALL).iterator; | 190 world.getClassHierarchyNode(B), |
| 166 checkState(C, currentNode: null, stack: null); | 191 ClassHierarchyNode.ALL).iterator; |
| 167 Expect.isNull(iterator.current); | 192 checkState(B, currentNode: null, stack: null); |
| 168 Expect.isTrue(iterator.moveNext()); | 193 Expect.isNull(iterator.current); |
| 169 checkState(C, currentNode: C, stack: [E, F, G]); | 194 Expect.isTrue(iterator.moveNext()); |
| 170 Expect.equals(C, iterator.current); | 195 checkState(B, currentNode: B, stack: [D]); |
| 171 Expect.isTrue(iterator.moveNext()); | 196 Expect.equals(B, iterator.current); |
| 172 checkState(C, currentNode: E, stack: [F, G]); | 197 Expect.isTrue(iterator.moveNext()); |
| 173 Expect.equals(E, iterator.current); | 198 checkState(B, currentNode: D, stack: []); |
| 174 Expect.isTrue(iterator.moveNext()); | 199 Expect.equals(D, iterator.current); |
| 175 checkState(C, currentNode: F, stack: [G]); | 200 Expect.isFalse(iterator.moveNext()); |
| 176 Expect.equals(F, iterator.current); | 201 checkState(B, currentNode: null, stack: []); |
| 177 Expect.isTrue(iterator.moveNext()); | 202 Expect.isNull(iterator.current); |
| 178 checkState(C, currentNode: G, stack: []); | 203 |
| 179 Expect.equals(G, iterator.current); | 204 iterator = new ClassHierarchyNodeIterable( |
| 180 Expect.isFalse(iterator.moveNext()); | 205 world.getClassHierarchyNode(B), |
| 181 checkState(C, currentNode: null, stack: []); | 206 ClassHierarchyNode.ALL, |
| 182 Expect.isNull(iterator.current); | 207 includeRoot: false).iterator; |
| 183 | 208 checkState(B, currentNode: null, stack: null); |
| 184 iterator = new ClassHierarchyNodeIterable( | 209 Expect.isNull(iterator.current); |
| 185 world.getClassHierarchyNode(D), | 210 Expect.isTrue(iterator.moveNext()); |
| 186 ClassHierarchyNode.ALL).iterator; | 211 checkState(B, currentNode: D, stack: []); |
| 187 checkState(D, currentNode: null, stack: null); | 212 Expect.equals(D, iterator.current); |
| 188 Expect.isNull(iterator.current); | 213 Expect.isFalse(iterator.moveNext()); |
| 189 Expect.isTrue(iterator.moveNext()); | 214 checkState(B, currentNode: null, stack: []); |
| 190 checkState(D, currentNode: D, stack: []); | 215 Expect.isNull(iterator.current); |
| 191 Expect.equals(D, iterator.current); | 216 |
| 192 Expect.isFalse(iterator.moveNext()); | 217 iterator = new ClassHierarchyNodeIterable( |
| 193 checkState(D, currentNode: null, stack: []); | 218 world.getClassHierarchyNode(B), |
| 194 Expect.isNull(iterator.current); | 219 new EnumSet<Instantiation>.fromValues(<Instantiation>[ |
| 195 | 220 Instantiation.DIRECTLY_INSTANTIATED, |
| 196 iterator = new ClassHierarchyNodeIterable( | 221 Instantiation.UNINSTANTIATED])).iterator; |
| 197 world.getClassHierarchyNode(B), | 222 checkState(B, currentNode: null, stack: null); |
| 198 ClassHierarchyNode.ALL).iterator; | 223 Expect.isNull(iterator.current); |
| 199 checkState(B, currentNode: null, stack: null); | 224 Expect.isTrue(iterator.moveNext()); |
| 200 Expect.isNull(iterator.current); | 225 checkState(B, currentNode: D, stack: []); |
| 201 Expect.isTrue(iterator.moveNext()); | 226 Expect.equals(D, iterator.current); |
| 202 checkState(B, currentNode: B, stack: [D]); | 227 Expect.isFalse(iterator.moveNext()); |
| 203 Expect.equals(B, iterator.current); | 228 checkState(B, currentNode: null, stack: []); |
| 204 Expect.isTrue(iterator.moveNext()); | 229 Expect.isNull(iterator.current); |
| 205 checkState(B, currentNode: D, stack: []); | 230 |
| 206 Expect.equals(D, iterator.current); | 231 iterator = new ClassHierarchyNodeIterable( |
| 207 Expect.isFalse(iterator.moveNext()); | 232 world.getClassHierarchyNode(A), |
| 208 checkState(B, currentNode: null, stack: []); | 233 ClassHierarchyNode.ALL).iterator; |
| 209 Expect.isNull(iterator.current); | 234 checkState(A, currentNode: null, stack: null); |
| 210 | 235 Expect.isNull(iterator.current); |
| 211 iterator = new ClassHierarchyNodeIterable( | 236 Expect.isTrue(iterator.moveNext()); |
| 212 world.getClassHierarchyNode(B), | 237 checkState(A, currentNode: A, stack: [C, B]); |
| 213 ClassHierarchyNode.ALL, | 238 Expect.equals(A, iterator.current); |
| 214 includeRoot: false).iterator; | 239 Expect.isTrue(iterator.moveNext()); |
| 215 checkState(B, currentNode: null, stack: null); | 240 checkState(A, currentNode: C, stack: [E, F, G, B]); |
| 216 Expect.isNull(iterator.current); | 241 Expect.equals(C, iterator.current); |
| 217 Expect.isTrue(iterator.moveNext()); | 242 Expect.isTrue(iterator.moveNext()); |
| 218 checkState(B, currentNode: D, stack: []); | 243 checkState(A, currentNode: E, stack: [F, G, B]); |
| 219 Expect.equals(D, iterator.current); | 244 Expect.equals(E, iterator.current); |
| 220 Expect.isFalse(iterator.moveNext()); | 245 Expect.isTrue(iterator.moveNext()); |
| 221 checkState(B, currentNode: null, stack: []); | 246 checkState(A, currentNode: F, stack: [G, B]); |
| 222 Expect.isNull(iterator.current); | 247 Expect.equals(F, iterator.current); |
| 223 | 248 Expect.isTrue(iterator.moveNext()); |
| 224 iterator = new ClassHierarchyNodeIterable( | 249 checkState(A, currentNode: G, stack: [B]); |
| 225 world.getClassHierarchyNode(B), | 250 Expect.equals(G, iterator.current); |
| 226 new EnumSet<Instantiation>.fromValues(<Instantiation>[ | 251 Expect.isTrue(iterator.moveNext()); |
| 227 Instantiation.DIRECTLY_INSTANTIATED, | 252 checkState(A, currentNode: B, stack: [D]); |
| 228 Instantiation.UNINSTANTIATED])).iterator; | 253 Expect.equals(B, iterator.current); |
| 229 checkState(B, currentNode: null, stack: null); | 254 Expect.isTrue(iterator.moveNext()); |
| 230 Expect.isNull(iterator.current); | 255 checkState(A, currentNode: D, stack: []); |
| 231 Expect.isTrue(iterator.moveNext()); | 256 Expect.equals(D, iterator.current); |
| 232 checkState(B, currentNode: D, stack: []); | 257 Expect.isFalse(iterator.moveNext()); |
| 233 Expect.equals(D, iterator.current); | 258 checkState(A, currentNode: null, stack: []); |
| 234 Expect.isFalse(iterator.moveNext()); | 259 Expect.isNull(iterator.current); |
| 235 checkState(B, currentNode: null, stack: []); | 260 |
| 236 Expect.isNull(iterator.current); | 261 iterator = new ClassHierarchyNodeIterable( |
| 237 | 262 world.getClassHierarchyNode(A), |
| 238 iterator = new ClassHierarchyNodeIterable( | 263 ClassHierarchyNode.ALL, |
| 239 world.getClassHierarchyNode(A), | 264 includeRoot: false).iterator; |
| 240 ClassHierarchyNode.ALL).iterator; | 265 checkState(A, currentNode: null, stack: null); |
| 241 checkState(A, currentNode: null, stack: null); | 266 Expect.isNull(iterator.current); |
| 242 Expect.isNull(iterator.current); | 267 Expect.isTrue(iterator.moveNext()); |
| 243 Expect.isTrue(iterator.moveNext()); | 268 checkState(A, currentNode: C, stack: [E, F, G, B]); |
| 244 checkState(A, currentNode: A, stack: [C, B]); | 269 Expect.equals(C, iterator.current); |
| 245 Expect.equals(A, iterator.current); | 270 Expect.isTrue(iterator.moveNext()); |
| 246 Expect.isTrue(iterator.moveNext()); | 271 checkState(A, currentNode: E, stack: [F, G, B]); |
| 247 checkState(A, currentNode: C, stack: [E, F, G, B]); | 272 Expect.equals(E, iterator.current); |
| 248 Expect.equals(C, iterator.current); | 273 Expect.isTrue(iterator.moveNext()); |
| 249 Expect.isTrue(iterator.moveNext()); | 274 checkState(A, currentNode: F, stack: [G, B]); |
| 250 checkState(A, currentNode: E, stack: [F, G, B]); | 275 Expect.equals(F, iterator.current); |
| 251 Expect.equals(E, iterator.current); | 276 Expect.isTrue(iterator.moveNext()); |
| 252 Expect.isTrue(iterator.moveNext()); | 277 checkState(A, currentNode: G, stack: [B]); |
| 253 checkState(A, currentNode: F, stack: [G, B]); | 278 Expect.equals(G, iterator.current); |
| 254 Expect.equals(F, iterator.current); | 279 Expect.isTrue(iterator.moveNext()); |
| 255 Expect.isTrue(iterator.moveNext()); | 280 checkState(A, currentNode: B, stack: [D]); |
| 256 checkState(A, currentNode: G, stack: [B]); | 281 Expect.equals(B, iterator.current); |
| 257 Expect.equals(G, iterator.current); | 282 Expect.isTrue(iterator.moveNext()); |
| 258 Expect.isTrue(iterator.moveNext()); | 283 checkState(A, currentNode: D, stack: []); |
| 259 checkState(A, currentNode: B, stack: [D]); | 284 Expect.equals(D, iterator.current); |
| 260 Expect.equals(B, iterator.current); | 285 Expect.isFalse(iterator.moveNext()); |
| 261 Expect.isTrue(iterator.moveNext()); | 286 checkState(A, currentNode: null, stack: []); |
| 262 checkState(A, currentNode: D, stack: []); | 287 Expect.isNull(iterator.current); |
| 263 Expect.equals(D, iterator.current); | 288 |
| 264 Expect.isFalse(iterator.moveNext()); | 289 iterator = new ClassHierarchyNodeIterable( |
| 265 checkState(A, currentNode: null, stack: []); | 290 world.getClassHierarchyNode(A), |
| 266 Expect.isNull(iterator.current); | 291 new EnumSet<Instantiation>.fromValues(<Instantiation>[ |
| 267 | 292 Instantiation.DIRECTLY_INSTANTIATED, |
| 268 iterator = new ClassHierarchyNodeIterable( | 293 Instantiation.UNINSTANTIATED])).iterator; |
| 269 world.getClassHierarchyNode(A), | 294 checkState(A, currentNode: null, stack: null); |
| 270 ClassHierarchyNode.ALL, | 295 Expect.isNull(iterator.current); |
| 271 includeRoot: false).iterator; | 296 Expect.isTrue(iterator.moveNext()); |
| 272 checkState(A, currentNode: null, stack: null); | 297 checkState(A, currentNode: A, stack: [C, B]); |
| 273 Expect.isNull(iterator.current); | 298 Expect.equals(A, iterator.current); |
| 274 Expect.isTrue(iterator.moveNext()); | 299 Expect.isTrue(iterator.moveNext()); |
| 275 checkState(A, currentNode: C, stack: [E, F, G, B]); | 300 checkState(A, currentNode: C, stack: [E, F, G, B]); |
| 276 Expect.equals(C, iterator.current); | 301 Expect.equals(C, iterator.current); |
| 277 Expect.isTrue(iterator.moveNext()); | 302 Expect.isTrue(iterator.moveNext()); |
| 278 checkState(A, currentNode: E, stack: [F, G, B]); | 303 checkState(A, currentNode: E, stack: [F, G, B]); |
| 279 Expect.equals(E, iterator.current); | 304 Expect.equals(E, iterator.current); |
| 280 Expect.isTrue(iterator.moveNext()); | 305 Expect.isTrue(iterator.moveNext()); |
| 281 checkState(A, currentNode: F, stack: [G, B]); | 306 checkState(A, currentNode: F, stack: [G, B]); |
| 282 Expect.equals(F, iterator.current); | 307 Expect.equals(F, iterator.current); |
| 283 Expect.isTrue(iterator.moveNext()); | 308 Expect.isTrue(iterator.moveNext()); |
| 284 checkState(A, currentNode: G, stack: [B]); | 309 checkState(A, currentNode: G, stack: [B]); |
| 285 Expect.equals(G, iterator.current); | 310 Expect.equals(G, iterator.current); |
| 286 Expect.isTrue(iterator.moveNext()); | 311 Expect.isTrue(iterator.moveNext()); |
| 287 checkState(A, currentNode: B, stack: [D]); | 312 checkState(A, currentNode: D, stack: []); |
| 288 Expect.equals(B, iterator.current); | 313 Expect.equals(D, iterator.current); |
| 289 Expect.isTrue(iterator.moveNext()); | 314 Expect.isFalse(iterator.moveNext()); |
| 290 checkState(A, currentNode: D, stack: []); | 315 checkState(A, currentNode: null, stack: []); |
| 291 Expect.equals(D, iterator.current); | 316 Expect.isNull(iterator.current); |
| 292 Expect.isFalse(iterator.moveNext()); | 317 |
| 293 checkState(A, currentNode: null, stack: []); | 318 iterator = new ClassHierarchyNodeIterable( |
| 294 Expect.isNull(iterator.current); | 319 world.getClassHierarchyNode(A), |
| 295 | 320 new EnumSet<Instantiation>.fromValues(<Instantiation>[ |
| 296 iterator = new ClassHierarchyNodeIterable( | 321 Instantiation.DIRECTLY_INSTANTIATED, |
| 297 world.getClassHierarchyNode(A), | 322 Instantiation.UNINSTANTIATED]), |
| 298 new EnumSet<Instantiation>.fromValues(<Instantiation>[ | 323 includeRoot: false).iterator; |
| 299 Instantiation.DIRECTLY_INSTANTIATED, | 324 checkState(A, currentNode: null, stack: null); |
| 300 Instantiation.UNINSTANTIATED])).iterator; | 325 Expect.isNull(iterator.current); |
| 301 checkState(A, currentNode: null, stack: null); | 326 Expect.isTrue(iterator.moveNext()); |
| 302 Expect.isNull(iterator.current); | 327 checkState(A, currentNode: C, stack: [E, F, G, B]); |
| 303 Expect.isTrue(iterator.moveNext()); | 328 Expect.equals(C, iterator.current); |
| 304 checkState(A, currentNode: A, stack: [C, B]); | 329 Expect.isTrue(iterator.moveNext()); |
| 305 Expect.equals(A, iterator.current); | 330 checkState(A, currentNode: E, stack: [F, G, B]); |
| 306 Expect.isTrue(iterator.moveNext()); | 331 Expect.equals(E, iterator.current); |
| 307 checkState(A, currentNode: C, stack: [E, F, G, B]); | 332 Expect.isTrue(iterator.moveNext()); |
| 308 Expect.equals(C, iterator.current); | 333 checkState(A, currentNode: F, stack: [G, B]); |
| 309 Expect.isTrue(iterator.moveNext()); | 334 Expect.equals(F, iterator.current); |
| 310 checkState(A, currentNode: E, stack: [F, G, B]); | 335 Expect.isTrue(iterator.moveNext()); |
| 311 Expect.equals(E, iterator.current); | 336 checkState(A, currentNode: G, stack: [B]); |
| 312 Expect.isTrue(iterator.moveNext()); | 337 Expect.equals(G, iterator.current); |
| 313 checkState(A, currentNode: F, stack: [G, B]); | 338 Expect.isTrue(iterator.moveNext()); |
| 314 Expect.equals(F, iterator.current); | 339 checkState(A, currentNode: D, stack: []); |
| 315 Expect.isTrue(iterator.moveNext()); | 340 Expect.equals(D, iterator.current); |
| 316 checkState(A, currentNode: G, stack: [B]); | 341 Expect.isFalse(iterator.moveNext()); |
| 317 Expect.equals(G, iterator.current); | 342 checkState(A, currentNode: null, stack: []); |
| 318 Expect.isTrue(iterator.moveNext()); | 343 Expect.isNull(iterator.current); |
| 319 checkState(A, currentNode: D, stack: []); | 344 })); |
| 320 Expect.equals(D, iterator.current); | |
| 321 Expect.isFalse(iterator.moveNext()); | |
| 322 checkState(A, currentNode: null, stack: []); | |
| 323 Expect.isNull(iterator.current); | |
| 324 | |
| 325 iterator = new ClassHierarchyNodeIterable( | |
| 326 world.getClassHierarchyNode(A), | |
| 327 new EnumSet<Instantiation>.fromValues(<Instantiation>[ | |
| 328 Instantiation.DIRECTLY_INSTANTIATED, | |
| 329 Instantiation.UNINSTANTIATED]), | |
| 330 includeRoot: false).iterator; | |
| 331 checkState(A, currentNode: null, stack: null); | |
| 332 Expect.isNull(iterator.current); | |
| 333 Expect.isTrue(iterator.moveNext()); | |
| 334 checkState(A, currentNode: C, stack: [E, F, G, B]); | |
| 335 Expect.equals(C, iterator.current); | |
| 336 Expect.isTrue(iterator.moveNext()); | |
| 337 checkState(A, currentNode: E, stack: [F, G, B]); | |
| 338 Expect.equals(E, iterator.current); | |
| 339 Expect.isTrue(iterator.moveNext()); | |
| 340 checkState(A, currentNode: F, stack: [G, B]); | |
| 341 Expect.equals(F, iterator.current); | |
| 342 Expect.isTrue(iterator.moveNext()); | |
| 343 checkState(A, currentNode: G, stack: [B]); | |
| 344 Expect.equals(G, iterator.current); | |
| 345 Expect.isTrue(iterator.moveNext()); | |
| 346 checkState(A, currentNode: D, stack: []); | |
| 347 Expect.equals(D, iterator.current); | |
| 348 Expect.isFalse(iterator.moveNext()); | |
| 349 checkState(A, currentNode: null, stack: []); | |
| 350 Expect.isNull(iterator.current); | |
| 351 } | 345 } |
| 352 | 346 |
| 353 testForEach() async { | |
| 354 var env = await TypeEnvironment.create(r""" | |
| 355 /// A | |
| 356 /// / \ | |
| 357 /// B C | |
| 358 /// / /|\ | |
| 359 /// D E F G | |
| 360 /// / \ | |
| 361 /// H I | |
| 362 /// | |
| 363 class A {} | |
| 364 class B extends A {} | |
| 365 class C extends A {} | |
| 366 class D extends B {} | |
| 367 class E extends C {} | |
| 368 class F extends C implements B {} | |
| 369 class G extends C implements D {} | |
| 370 class H extends F {} | |
| 371 class I extends F {} | |
| 372 """, | |
| 373 mainSource: r""" | |
| 374 main() { | |
| 375 new A(); | |
| 376 new C(); | |
| 377 new D(); | |
| 378 new E(); | |
| 379 new F(); | |
| 380 new G(); | |
| 381 new H(); | |
| 382 new I(); | |
| 383 } | |
| 384 """, | |
| 385 useMockCompiler: false); | |
| 386 World world = env.compiler.world; | |
| 387 | |
| 388 ClassElement A = env.getElement("A"); | |
| 389 ClassElement B = env.getElement("B"); | |
| 390 ClassElement C = env.getElement("C"); | |
| 391 ClassElement D = env.getElement("D"); | |
| 392 ClassElement E = env.getElement("E"); | |
| 393 ClassElement F = env.getElement("F"); | |
| 394 ClassElement G = env.getElement("G"); | |
| 395 ClassElement H = env.getElement("H"); | |
| 396 ClassElement I = env.getElement("I"); | |
| 397 | |
| 398 void checkForEachSubclass(ClassElement cls, List<ClassElement> expected) { | |
| 399 ClassSet classSet = world.getClassSet(cls); | |
| 400 List<ClassElement> visited = <ClassElement>[]; | |
| 401 classSet.forEachSubclass((ClassElement cls) { | |
| 402 visited.add(cls); | |
| 403 }, ClassHierarchyNode.ALL); | |
| 404 | |
| 405 Expect.listEquals(expected, visited, | |
| 406 "Unexpected classes on $cls.forEachSubclass:\n" | |
| 407 "Actual: $visited, expected: $expected\n$classSet"); | |
| 408 | |
| 409 visited = <ClassElement>[]; | |
| 410 classSet.forEachSubclass((ClassElement cls) { | |
| 411 visited.add(cls); | |
| 412 return ForEach.CONTINUE; | |
| 413 }, ClassHierarchyNode.ALL); | |
| 414 | |
| 415 Expect.listEquals(expected, visited, | |
| 416 "Unexpected classes on $cls.forEachSubclass:\n" | |
| 417 "Actual: $visited, expected: $expected\n$classSet"); | |
| 418 } | |
| 419 | |
| 420 checkForEachSubclass(A, [A, B, D, C, G, F, I, H, E]); | |
| 421 checkForEachSubclass(B, [B, D]); | |
| 422 checkForEachSubclass(C, [C, G, F, I, H, E]); | |
| 423 checkForEachSubclass(D, [D]); | |
| 424 checkForEachSubclass(E, [E]); | |
| 425 checkForEachSubclass(F, [F, I, H]); | |
| 426 checkForEachSubclass(G, [G]); | |
| 427 checkForEachSubclass(H, [H]); | |
| 428 checkForEachSubclass(I, [I]); | |
| 429 | |
| 430 void checkForEachSubtype(ClassElement cls, List<ClassElement> expected) { | |
| 431 ClassSet classSet = world.getClassSet(cls); | |
| 432 List<ClassElement> visited = <ClassElement>[]; | |
| 433 classSet.forEachSubtype((ClassElement cls) { | |
| 434 visited.add(cls); | |
| 435 }, ClassHierarchyNode.ALL); | |
| 436 | |
| 437 Expect.listEquals(expected, visited, | |
| 438 "Unexpected classes on $cls.forEachSubtype:\n" | |
| 439 "Actual: $visited, expected: $expected\n$classSet"); | |
| 440 | |
| 441 visited = <ClassElement>[]; | |
| 442 classSet.forEachSubtype((ClassElement cls) { | |
| 443 visited.add(cls); | |
| 444 return ForEach.CONTINUE; | |
| 445 }, ClassHierarchyNode.ALL); | |
| 446 | |
| 447 Expect.listEquals(expected, visited, | |
| 448 "Unexpected classes on $cls.forEachSubtype:\n" | |
| 449 "Actual: $visited, expected: $expected\n$classSet"); | |
| 450 } | |
| 451 | |
| 452 checkForEachSubtype(A, [A, B, D, C, G, F, I, H, E]); | |
| 453 checkForEachSubtype(B, [B, D, F, I, H, G]); | |
| 454 checkForEachSubtype(C, [C, G, F, I, H, E]); | |
| 455 checkForEachSubtype(D, [D, G]); | |
| 456 checkForEachSubtype(E, [E]); | |
| 457 checkForEachSubtype(F, [F, I, H]); | |
| 458 checkForEachSubtype(G, [G]); | |
| 459 checkForEachSubtype(H, [H]); | |
| 460 checkForEachSubtype(I, [I]); | |
| 461 | |
| 462 void checkForEach( | |
| 463 ClassElement cls, | |
| 464 List<ClassElement> expected, | |
| 465 {ClassElement stop, | |
| 466 List<ClassElement> skipChildren: const <ClassElement>[], | |
| 467 bool forEachSubtype: false}) { | |
| 468 ClassSet classSet = world.getClassSet(cls); | |
| 469 List<ClassElement> visited = <ClassElement>[]; | |
| 470 | |
| 471 ForEach visit(ClassElement cls) { | |
| 472 visited.add(cls); | |
| 473 if (cls == stop) { | |
| 474 return ForEach.STOP; | |
| 475 } else if (skipChildren.contains(cls)) { | |
| 476 return ForEach.SKIP_CHILDREN; | |
| 477 } | |
| 478 return ForEach.CONTINUE; | |
| 479 } | |
| 480 | |
| 481 if (forEachSubtype) { | |
| 482 classSet.forEachSubtype(visit, ClassHierarchyNode.ALL); | |
| 483 } else { | |
| 484 classSet.forEachSubclass(visit, ClassHierarchyNode.ALL); | |
| 485 } | |
| 486 | |
| 487 Expect.listEquals(expected, visited, | |
| 488 "Unexpected classes on $cls." | |
| 489 "forEach${forEachSubtype ? 'Subtype' : 'Subclass'} " | |
| 490 "(stop:$stop, skipChildren:$skipChildren):\n" | |
| 491 "Actual: $visited, expected: $expected\n$classSet"); | |
| 492 } | |
| 493 | |
| 494 checkForEach(A, [A, B, D, C, G, F, I, H, E]); | |
| 495 checkForEach(A, [A], stop: A); | |
| 496 checkForEach(A, [A, B, C, G, F, I, H, E], skipChildren: [B]); | |
| 497 checkForEach(A, [A, B, C], skipChildren: [B, C]); | |
| 498 checkForEach(A, [A, B, C, G], stop: G, skipChildren: [B]); | |
| 499 | |
| 500 checkForEach(B, [B, D, F, I, H, G], forEachSubtype: true); | |
| 501 checkForEach(B, [B, D], stop: D, forEachSubtype: true); | |
| 502 checkForEach(B, [B, D, F, G], skipChildren: [F], forEachSubtype: true); | |
| 503 checkForEach(B, [B], skipChildren: [B], forEachSubtype: true); | |
| 504 checkForEach(B, [B, D, F, I, H, G], skipChildren: [D], forEachSubtype: true); | |
| 505 | |
| 506 void checkAny( | |
| 507 ClassElement cls, | |
| 508 List<ClassElement> expected, | |
| 509 {ClassElement find, | |
| 510 bool expectedResult, | |
| 511 bool anySubtype: false}) { | |
| 512 ClassSet classSet = world.getClassSet(cls); | |
| 513 List<ClassElement> visited = <ClassElement>[]; | |
| 514 | |
| 515 bool visit(ClassElement cls) { | |
| 516 visited.add(cls); | |
| 517 return cls == find; | |
| 518 } | |
| 519 | |
| 520 bool result; | |
| 521 if (anySubtype) { | |
| 522 result = classSet.anySubtype(visit, ClassHierarchyNode.ALL); | |
| 523 } else { | |
| 524 result = classSet.anySubclass(visit, ClassHierarchyNode.ALL); | |
| 525 } | |
| 526 | |
| 527 Expect.equals(expectedResult, result, | |
| 528 "Unexpected result on $cls." | |
| 529 "any${anySubtype ? 'Subtype' : 'Subclass'} " | |
| 530 "(find:$find)."); | |
| 531 | |
| 532 Expect.listEquals(expected, visited, | |
| 533 "Unexpected classes on $cls." | |
| 534 "any${anySubtype ? 'Subtype' : 'Subclass'} " | |
| 535 "(find:$find):\n" | |
| 536 "Actual: $visited, expected: $expected\n$classSet"); | |
| 537 } | |
| 538 | |
| 539 checkAny(A, [A, B, D, C, G, F, I, H, E], expectedResult: false); | |
| 540 checkAny(A, [A], find: A, expectedResult: true); | |
| 541 checkAny(A, [A, B, D, C, G, F, I], find: I, expectedResult: true); | |
| 542 | |
| 543 checkAny(B, [B, D, F, I, H, G], anySubtype: true, expectedResult: false); | |
| 544 checkAny(B, [B, D, F, I, H, G], | |
| 545 find: A, anySubtype: true, expectedResult: false); | |
| 546 checkAny(B, [B, D], | |
| 547 find: D, anySubtype: true, expectedResult: true); | |
| 548 checkAny(B, [B, D, F, I], | |
| 549 find: I, anySubtype: true, expectedResult: true); | |
| 550 } | |
| OLD | NEW |