| 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 library world_test; | 5 library world_test; |
| 6 | 6 |
| 7 import 'package:expect/expect.dart'; | 7 import 'package:expect/expect.dart'; |
| 8 import 'package:async_helper/async_helper.dart'; | 8 import 'package:async_helper/async_helper.dart'; |
| 9 import 'type_test_helper.dart'; | 9 import 'type_test_helper.dart'; |
| 10 import 'package:compiler/src/common.dart'; | |
| 11 import 'package:compiler/src/elements/elements.dart' | 10 import 'package:compiler/src/elements/elements.dart' |
| 12 show Element, ClassElement; | 11 show Element, ClassElement; |
| 13 import 'package:compiler/src/universe/class_set.dart'; | |
| 14 import 'package:compiler/src/world.dart' show ClassWorld; | 12 import 'package:compiler/src/world.dart' show ClassWorld; |
| 15 | 13 |
| 16 void main() { | 14 void main() { |
| 17 asyncTest(() async { | 15 asyncTest(() => TypeEnvironment.create(r""" |
| 18 await testClassSets(); | |
| 19 await testProperties(); | |
| 20 }); | |
| 21 } | |
| 22 | |
| 23 testClassSets() async { | |
| 24 var env = await TypeEnvironment.create(r""" | |
| 25 class A {} | 16 class A {} |
| 26 class B {} | 17 class B {} |
| 27 class C_Super extends A {} | 18 class C_Super extends A {} |
| 28 class C extends C_Super {} | 19 class C extends C_Super {} |
| 29 class D implements A {} | 20 class D implements A {} |
| 30 class E extends B implements A {} | 21 class E extends B implements A {} |
| 31 class F extends Object with A implements B {} | 22 class F extends Object with A implements B {} |
| 32 class G extends Object with A, B {} | 23 class G extends Object with A, B {} |
| 33 """, | 24 """, |
| 34 mainSource: r""" | 25 mainSource: r""" |
| 35 main() { | 26 main() { |
| 36 new A(); | 27 new A(); |
| 37 new B(); | 28 new B(); |
| 38 new C(); | 29 new C(); |
| 39 new D(); | 30 new D(); |
| 40 new E(); | 31 new E(); |
| 41 new F(); | 32 new F(); |
| 42 new G(); | 33 new G(); |
| 43 } | 34 } |
| 44 """, | 35 """, |
| 45 useMockCompiler: false); | 36 useMockCompiler: false).then((env) { |
| 46 ClassWorld classWorld = env.compiler.world; | 37 ClassWorld classWorld = env.compiler.world; |
| 47 | 38 |
| 48 ClassElement Object_ = env.getElement("Object"); | 39 ClassElement Object_ = env.getElement("Object"); |
| 49 ClassElement A = env.getElement("A"); | 40 ClassElement A = env.getElement("A"); |
| 50 ClassElement B = env.getElement("B"); | 41 ClassElement B = env.getElement("B"); |
| 51 ClassElement C = env.getElement("C"); | 42 ClassElement C = env.getElement("C"); |
| 52 ClassElement D = env.getElement("D"); | 43 ClassElement D = env.getElement("D"); |
| 53 ClassElement E = env.getElement("E"); | 44 ClassElement E = env.getElement("E"); |
| 54 ClassElement F = env.getElement("F"); | 45 ClassElement F = env.getElement("F"); |
| 55 ClassElement G = env.getElement("G"); | 46 ClassElement G = env.getElement("G"); |
| 56 | 47 |
| 57 void checkClasses( | 48 void check( |
| 58 String property, | 49 String property, |
| 59 ClassElement cls, | 50 ClassElement cls, |
| 60 Iterable<ClassElement> foundClasses, | 51 Iterable<ClassElement> foundClasses, |
| 61 List<ClassElement> expectedClasses, | 52 List<ClassElement> expectedClasses, |
| 62 {bool exact: true}) { | 53 {bool exact: true}) { |
| 63 | 54 for (ClassElement expectedClass in expectedClasses) { |
| 64 for (ClassElement expectedClass in expectedClasses) { | 55 Expect.isTrue(foundClasses.contains(expectedClass), |
| 65 Expect.isTrue(foundClasses.contains(expectedClass), | 56 "Expect $expectedClass in '$property' on $cls. " |
| 66 "Expect $expectedClass in '$property' on $cls. " | 57 "Found:\n ${foundClasses.join('\n ')}"); |
| 67 "Found:\n ${foundClasses.join('\n ')}"); | 58 } |
| 68 } | 59 if (exact) { |
| 69 if (exact) { | 60 Expect.equals(expectedClasses.length, foundClasses.length, |
| 70 Expect.equals(expectedClasses.length, foundClasses.length, | 61 "Unexpected classes " |
| 71 "Unexpected classes " | 62 "${foundClasses.where((c) => !expectedClasses.contains(c))} " |
| 72 "${foundClasses.where((c) => !expectedClasses.contains(c))} " | 63 "in '$property' on $cls."); |
| 73 "in '$property' on $cls."); | 64 } |
| 74 } | |
| 75 } | |
| 76 | |
| 77 void check( | |
| 78 String property, | |
| 79 ClassElement cls, | |
| 80 Iterable<ClassElement> foundClasses, | |
| 81 List<ClassElement> expectedClasses, | |
| 82 {bool exact: true, | |
| 83 void forEach(ClassElement cls, ForEachFunction f), | |
| 84 int getCount(ClassElement cls)}) { | |
| 85 checkClasses(property, cls, foundClasses, expectedClasses, exact: exact); | |
| 86 | |
| 87 if (forEach != null) { | |
| 88 List<ClassElement> visited = <ClassElement>[]; | |
| 89 forEach(cls, (ClassElement c) { | |
| 90 visited.add(c); | |
| 91 }); | |
| 92 checkClasses( | |
| 93 'forEach($property)', cls, visited, expectedClasses, exact: exact); | |
| 94 } | 65 } |
| 95 | 66 |
| 96 if (getCount != null && exact) { | 67 void testSubclasses( |
| 97 int count = getCount(cls); | 68 ClassElement cls, |
| 98 Expect.equals(expectedClasses.length, count, | 69 List<ClassElement> expectedClasses, |
| 99 "Unexpected class count in '$property' on $cls."); | 70 {bool exact: true}) { |
| 71 check( |
| 72 'subclassesOf', |
| 73 cls, |
| 74 classWorld.subclassesOf(cls), |
| 75 expectedClasses, |
| 76 exact: exact); |
| 100 } | 77 } |
| 101 | 78 |
| 102 } | 79 void testStrictSubclasses( |
| 80 ClassElement cls, |
| 81 List<ClassElement> expectedClasses, |
| 82 {bool exact: true}) { |
| 83 check( |
| 84 'strictSubclassesOf', |
| 85 cls, |
| 86 classWorld.strictSubclassesOf(cls), |
| 87 expectedClasses, |
| 88 exact: exact); |
| 89 } |
| 103 | 90 |
| 104 void testSubclasses( | 91 void testStrictSubtypes( |
| 105 ClassElement cls, | 92 ClassElement cls, |
| 106 List<ClassElement> expectedClasses, | 93 List<ClassElement> expectedClasses, |
| 107 {bool exact: true}) { | 94 {bool exact: true}) { |
| 108 check( | 95 check( |
| 109 'subclassesOf', | 96 'strictSubtypesOf', |
| 110 cls, | 97 cls, |
| 111 classWorld.subclassesOf(cls), | 98 classWorld.strictSubtypesOf(cls), |
| 112 expectedClasses, | 99 expectedClasses, |
| 113 exact: exact); | 100 exact: exact); |
| 114 } | 101 } |
| 115 | 102 |
| 116 void testStrictSubclasses( | 103 void testMixinUses( |
| 117 ClassElement cls, | 104 ClassElement cls, |
| 118 List<ClassElement> expectedClasses, | 105 List<ClassElement> expectedClasses, |
| 119 {bool exact: true}) { | 106 {bool exact: true}) { |
| 120 check( | 107 check( |
| 121 'strictSubclassesOf', | 108 'mixinUsesOf', |
| 122 cls, | 109 cls, |
| 123 classWorld.strictSubclassesOf(cls), | 110 classWorld.mixinUsesOf(cls), |
| 124 expectedClasses, | 111 expectedClasses, |
| 125 exact: exact, | 112 exact: exact); |
| 126 forEach: classWorld.forEachStrictSubclassOf, | 113 } |
| 127 getCount: classWorld.strictSubclassCount); | |
| 128 } | |
| 129 | 114 |
| 130 void testStrictSubtypes( | 115 testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); |
| 131 ClassElement cls, | 116 testSubclasses(A, [A, C]); |
| 132 List<ClassElement> expectedClasses, | 117 testSubclasses(B, [B, E]); |
| 133 {bool exact: true}) { | 118 testSubclasses(C, [C]); |
| 134 check( | 119 testSubclasses(D, [D]); |
| 135 'strictSubtypesOf', | 120 testSubclasses(E, [E]); |
| 136 cls, | 121 testSubclasses(F, [F]); |
| 137 classWorld.strictSubtypesOf(cls), | 122 testSubclasses(G, [G]); |
| 138 expectedClasses, | |
| 139 exact: exact, | |
| 140 forEach: classWorld.forEachStrictSubtypeOf, | |
| 141 getCount: classWorld.strictSubtypeCount); | |
| 142 } | |
| 143 | 123 |
| 144 void testMixinUses( | 124 testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); |
| 145 ClassElement cls, | 125 testStrictSubclasses(A, [C]); |
| 146 List<ClassElement> expectedClasses, | 126 testStrictSubclasses(B, [E]); |
| 147 {bool exact: true}) { | 127 testStrictSubclasses(C, []); |
| 148 check( | 128 testStrictSubclasses(D, []); |
| 149 'mixinUsesOf', | 129 testStrictSubclasses(E, []); |
| 150 cls, | 130 testStrictSubclasses(F, []); |
| 151 classWorld.mixinUsesOf(cls), | 131 testStrictSubclasses(G, []); |
| 152 expectedClasses, | |
| 153 exact: exact); | |
| 154 } | |
| 155 | 132 |
| 156 testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); | 133 testStrictSubtypes(Object_, [A, B, C, D, E, F, G], exact: false); |
| 157 testSubclasses(A, [A, C]); | 134 testStrictSubtypes(A, [C, D, E, F, G]); |
| 158 testSubclasses(B, [B, E]); | 135 testStrictSubtypes(B, [E, F, G]); |
| 159 testSubclasses(C, [C]); | 136 testStrictSubtypes(C, []); |
| 160 testSubclasses(D, [D]); | 137 testStrictSubtypes(D, []); |
| 161 testSubclasses(E, [E]); | 138 testStrictSubtypes(E, []); |
| 162 testSubclasses(F, [F]); | 139 testStrictSubtypes(F, []); |
| 163 testSubclasses(G, [G]); | 140 testStrictSubtypes(G, []); |
| 164 | 141 |
| 165 testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); | 142 testMixinUses(Object_, []); |
| 166 testStrictSubclasses(A, [C]); | 143 testMixinUses(A, [F.superclass, G.superclass.superclass]); |
| 167 testStrictSubclasses(B, [E]); | 144 testMixinUses(B, [G.superclass]); |
| 168 testStrictSubclasses(C, []); | 145 testMixinUses(C, []); |
| 169 testStrictSubclasses(D, []); | 146 testMixinUses(D, []); |
| 170 testStrictSubclasses(E, []); | 147 testMixinUses(E, []); |
| 171 testStrictSubclasses(F, []); | 148 testMixinUses(F, []); |
| 172 testStrictSubclasses(G, []); | 149 testMixinUses(G, []); |
| 173 | 150 |
| 174 testStrictSubtypes(Object_, [A, B, C, D, E, F, G], exact: false); | 151 })); |
| 175 testStrictSubtypes(A, [C, D, E, F, G]); | |
| 176 testStrictSubtypes(B, [E, F, G]); | |
| 177 testStrictSubtypes(C, []); | |
| 178 testStrictSubtypes(D, []); | |
| 179 testStrictSubtypes(E, []); | |
| 180 testStrictSubtypes(F, []); | |
| 181 testStrictSubtypes(G, []); | |
| 182 | |
| 183 testMixinUses(Object_, []); | |
| 184 testMixinUses(A, [F.superclass, G.superclass.superclass]); | |
| 185 testMixinUses(B, [G.superclass]); | |
| 186 testMixinUses(C, []); | |
| 187 testMixinUses(D, []); | |
| 188 testMixinUses(E, []); | |
| 189 testMixinUses(F, []); | |
| 190 testMixinUses(G, []); | |
| 191 } | 152 } |
| 192 | |
| 193 testProperties() async { | |
| 194 var env = await TypeEnvironment.create(r""" | |
| 195 class A {} | |
| 196 class A1 extends A {} | |
| 197 class A2 implements A {} | |
| 198 class A3 extends Object with A {} | |
| 199 | |
| 200 class B {} | |
| 201 class B1 extends B {} | |
| 202 class B2 implements B {} | |
| 203 class B3 extends Object with B {} | |
| 204 | |
| 205 class C {} | |
| 206 class C1 extends C {} | |
| 207 class C2 implements C {} | |
| 208 class C3 extends Object with C {} | |
| 209 | |
| 210 class D {} | |
| 211 class D1 extends D {} | |
| 212 class D2 implements D {} | |
| 213 class D3 extends Object with D {} | |
| 214 | |
| 215 class E {} | |
| 216 class E1 extends E {} | |
| 217 class E2 implements E {} | |
| 218 class E3 extends Object with E {} | |
| 219 | |
| 220 class F {} | |
| 221 class F1 extends F {} | |
| 222 class F2 implements F {} | |
| 223 class F3 extends Object with F {} | |
| 224 | |
| 225 class G {} | |
| 226 class G1 extends G {} | |
| 227 class G2 extends G1 {} | |
| 228 class G3 extends G2 implements G {} | |
| 229 class G4 extends G2 with G {} | |
| 230 | |
| 231 class H {} | |
| 232 class H1 extends H {} | |
| 233 class H2 extends H1 {} | |
| 234 class H3 extends H2 implements H {} | |
| 235 class H4 extends H2 with H {} | |
| 236 """, | |
| 237 mainSource: r""" | |
| 238 main() { | |
| 239 new B(); | |
| 240 new C1(); | |
| 241 new D2(); | |
| 242 new E3(); | |
| 243 new F1(); | |
| 244 new F2(); | |
| 245 new G2(); | |
| 246 new G3(); | |
| 247 new H4(); | |
| 248 } | |
| 249 """, | |
| 250 useMockCompiler: false); | |
| 251 ClassWorld classWorld = env.compiler.world; | |
| 252 | |
| 253 check(String name, | |
| 254 {bool hasStrictSubtype, | |
| 255 bool hasOnlySubclasses}) { | |
| 256 ClassElement cls = env.getElement(name); | |
| 257 Expect.equals(hasStrictSubtype, classWorld.hasAnyStrictSubtype(cls), | |
| 258 "Unexpected hasAnyStrictSubtype property on $cls."); | |
| 259 Expect.equals(hasOnlySubclasses, classWorld.hasOnlySubclasses(cls), | |
| 260 "Unexpected hasOnlySubclasses property on $cls."); | |
| 261 } | |
| 262 | |
| 263 check("Object", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 264 | |
| 265 // No instantiated Ax classes. | |
| 266 check("A", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 267 check("A1", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 268 check("A2", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 269 check("A3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 270 | |
| 271 // class B instantiated | |
| 272 check("B", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 273 check("B1", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 274 check("B2", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 275 check("B3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 276 | |
| 277 // class C1 extends C instantiated | |
| 278 check("C", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 279 check("C1", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 280 check("C2", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 281 check("C3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 282 | |
| 283 // class D2 implements D instantiated | |
| 284 check("D", hasStrictSubtype: true, hasOnlySubclasses: false); | |
| 285 check("D1", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 286 check("D2", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 287 check("D3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 288 | |
| 289 // class E2 extends Object with E instantiated | |
| 290 check("E", hasStrictSubtype: true, hasOnlySubclasses: false); | |
| 291 check("E1", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 292 check("E2", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 293 check("E3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 294 | |
| 295 // class F1 extends F instantiated | |
| 296 // class F2 implements F instantiated | |
| 297 check("F", hasStrictSubtype: true, hasOnlySubclasses: false); | |
| 298 check("F1", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 299 check("F2", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 300 check("F3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 301 | |
| 302 // class G2 extends G1 extends G instantiated | |
| 303 // class G3 extends G2 extends G1 extends G instantiated | |
| 304 check("G", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 305 check("G1", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 306 check("G2", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 307 check("G3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 308 check("G4", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 309 | |
| 310 // class H4 extends H2 with H extends H1 extends H instantiated | |
| 311 check("H", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 312 check("H1", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 313 check("H2", hasStrictSubtype: true, hasOnlySubclasses: true); | |
| 314 check("H3", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 315 check("H4", hasStrictSubtype: false, hasOnlySubclasses: true); | |
| 316 } | |
| OLD | NEW |