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