| 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 { |
| 18 await testClassSets(); |
| 19 await testProperties(); |
| 20 }); |
| 21 } |
| 22 |
| 23 testClassSets() async { |
| 24 var env = await TypeEnvironment.create(r""" |
| 16 class A {} | 25 class A {} |
| 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 {} |
| 24 """, | 33 """, |
| 25 mainSource: r""" | 34 mainSource: r""" |
| 26 main() { | 35 main() { |
| 27 new A(); | 36 new A(); |
| 28 new B(); | 37 new B(); |
| 29 new C(); | 38 new C(); |
| 30 new D(); | 39 new D(); |
| 31 new E(); | 40 new E(); |
| 32 new F(); | 41 new F(); |
| 33 new G(); | 42 new G(); |
| 34 } | 43 } |
| 35 """, | 44 """, |
| 36 useMockCompiler: false).then((env) { | 45 useMockCompiler: false); |
| 37 ClassWorld classWorld = env.compiler.world; | 46 ClassWorld classWorld = env.compiler.world; |
| 38 | 47 |
| 39 ClassElement Object_ = env.getElement("Object"); | 48 ClassElement Object_ = env.getElement("Object"); |
| 40 ClassElement A = env.getElement("A"); | 49 ClassElement A = env.getElement("A"); |
| 41 ClassElement B = env.getElement("B"); | 50 ClassElement B = env.getElement("B"); |
| 42 ClassElement C = env.getElement("C"); | 51 ClassElement C = env.getElement("C"); |
| 43 ClassElement D = env.getElement("D"); | 52 ClassElement D = env.getElement("D"); |
| 44 ClassElement E = env.getElement("E"); | 53 ClassElement E = env.getElement("E"); |
| 45 ClassElement F = env.getElement("F"); | 54 ClassElement F = env.getElement("F"); |
| 46 ClassElement G = env.getElement("G"); | 55 ClassElement G = env.getElement("G"); |
| 47 | 56 |
| 48 void check( | 57 void checkClasses( |
| 49 String property, | 58 String property, |
| 50 ClassElement cls, | 59 ClassElement cls, |
| 51 Iterable<ClassElement> foundClasses, | 60 Iterable<ClassElement> foundClasses, |
| 52 List<ClassElement> expectedClasses, | 61 List<ClassElement> expectedClasses, |
| 53 {bool exact: true}) { | 62 {bool exact: true}) { |
| 54 for (ClassElement expectedClass in expectedClasses) { | 63 |
| 55 Expect.isTrue(foundClasses.contains(expectedClass), | 64 for (ClassElement expectedClass in expectedClasses) { |
| 56 "Expect $expectedClass in '$property' on $cls. " | 65 Expect.isTrue(foundClasses.contains(expectedClass), |
| 57 "Found:\n ${foundClasses.join('\n ')}"); | 66 "Expect $expectedClass in '$property' on $cls. " |
| 67 "Found:\n ${foundClasses.join('\n ')}"); |
| 68 } |
| 69 if (exact) { |
| 70 Expect.equals(expectedClasses.length, foundClasses.length, |
| 71 "Unexpected classes " |
| 72 "${foundClasses.where((c) => !expectedClasses.contains(c))} " |
| 73 "in '$property' on $cls."); |
| 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 } |
| 95 |
| 96 if (getCount != null && exact) { |
| 97 int count = getCount(cls); |
| 98 Expect.equals(expectedClasses.length, count, |
| 99 "Unexpected class count in '$property' on $cls."); |
| 100 } |
| 101 |
| 102 } |
| 103 |
| 104 void testSubclasses( |
| 105 ClassElement cls, |
| 106 List<ClassElement> expectedClasses, |
| 107 {bool exact: true}) { |
| 108 check( |
| 109 'subclassesOf', |
| 110 cls, |
| 111 classWorld.subclassesOf(cls), |
| 112 expectedClasses, |
| 113 exact: exact); |
| 114 } |
| 115 |
| 116 void testStrictSubclasses( |
| 117 ClassElement cls, |
| 118 List<ClassElement> expectedClasses, |
| 119 {bool exact: true}) { |
| 120 check( |
| 121 'strictSubclassesOf', |
| 122 cls, |
| 123 classWorld.strictSubclassesOf(cls), |
| 124 expectedClasses, |
| 125 exact: exact, |
| 126 forEach: classWorld.forEachStrictSubclassOf, |
| 127 getCount: classWorld.strictSubclassCount); |
| 128 } |
| 129 |
| 130 void testStrictSubtypes( |
| 131 ClassElement cls, |
| 132 List<ClassElement> expectedClasses, |
| 133 {bool exact: true}) { |
| 134 check( |
| 135 'strictSubtypesOf', |
| 136 cls, |
| 137 classWorld.strictSubtypesOf(cls), |
| 138 expectedClasses, |
| 139 exact: exact, |
| 140 forEach: classWorld.forEachStrictSubtypeOf, |
| 141 getCount: classWorld.strictSubtypeCount); |
| 142 } |
| 143 |
| 144 void testMixinUses( |
| 145 ClassElement cls, |
| 146 List<ClassElement> expectedClasses, |
| 147 {bool exact: true}) { |
| 148 check( |
| 149 'mixinUsesOf', |
| 150 cls, |
| 151 classWorld.mixinUsesOf(cls), |
| 152 expectedClasses, |
| 153 exact: exact); |
| 154 } |
| 155 |
| 156 testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); |
| 157 testSubclasses(A, [A, C]); |
| 158 testSubclasses(B, [B, E]); |
| 159 testSubclasses(C, [C]); |
| 160 testSubclasses(D, [D]); |
| 161 testSubclasses(E, [E]); |
| 162 testSubclasses(F, [F]); |
| 163 testSubclasses(G, [G]); |
| 164 |
| 165 testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); |
| 166 testStrictSubclasses(A, [C]); |
| 167 testStrictSubclasses(B, [E]); |
| 168 testStrictSubclasses(C, []); |
| 169 testStrictSubclasses(D, []); |
| 170 testStrictSubclasses(E, []); |
| 171 testStrictSubclasses(F, []); |
| 172 testStrictSubclasses(G, []); |
| 173 |
| 174 testStrictSubtypes(Object_, [A, B, C, D, E, F, G], exact: false); |
| 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 } |
| 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(); |
| 58 } | 248 } |
| 59 if (exact) { | 249 """, |
| 60 Expect.equals(expectedClasses.length, foundClasses.length, | 250 useMockCompiler: false); |
| 61 "Unexpected classes " | 251 ClassWorld classWorld = env.compiler.world; |
| 62 "${foundClasses.where((c) => !expectedClasses.contains(c))} " | 252 |
| 63 "in '$property' on $cls."); | 253 check(String name, |
| 64 } | 254 {bool hasStrictSubtype, |
| 65 } | 255 bool hasOnlySubclasses}) { |
| 66 | 256 ClassElement cls = env.getElement(name); |
| 67 void testSubclasses( | 257 Expect.equals(hasStrictSubtype, classWorld.hasAnyStrictSubtype(cls), |
| 68 ClassElement cls, | 258 "Unexpected hasAnyStrictSubtype property on $cls."); |
| 69 List<ClassElement> expectedClasses, | 259 Expect.equals(hasOnlySubclasses, classWorld.hasOnlySubclasses(cls), |
| 70 {bool exact: true}) { | 260 "Unexpected hasOnlySubclasses property on $cls."); |
| 71 check( | 261 } |
| 72 'subclassesOf', | 262 |
| 73 cls, | 263 check("Object", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 74 classWorld.subclassesOf(cls), | 264 |
| 75 expectedClasses, | 265 // No instantiated Ax classes. |
| 76 exact: exact); | 266 check("A", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 77 } | 267 check("A1", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 78 | 268 check("A2", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 79 void testStrictSubclasses( | 269 check("A3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 80 ClassElement cls, | 270 |
| 81 List<ClassElement> expectedClasses, | 271 // class B instantiated |
| 82 {bool exact: true}) { | 272 check("B", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 83 check( | 273 check("B1", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 84 'strictSubclassesOf', | 274 check("B2", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 85 cls, | 275 check("B3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 86 classWorld.strictSubclassesOf(cls), | 276 |
| 87 expectedClasses, | 277 // class C1 extends C instantiated |
| 88 exact: exact); | 278 check("C", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 89 } | 279 check("C1", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 90 | 280 check("C2", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 91 void testStrictSubtypes( | 281 check("C3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 92 ClassElement cls, | 282 |
| 93 List<ClassElement> expectedClasses, | 283 // class D2 implements D instantiated |
| 94 {bool exact: true}) { | 284 check("D", hasStrictSubtype: true, hasOnlySubclasses: false); |
| 95 check( | 285 check("D1", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 96 'strictSubtypesOf', | 286 check("D2", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 97 cls, | 287 check("D3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 98 classWorld.strictSubtypesOf(cls), | 288 |
| 99 expectedClasses, | 289 // class E2 extends Object with E instantiated |
| 100 exact: exact); | 290 check("E", hasStrictSubtype: true, hasOnlySubclasses: false); |
| 101 } | 291 check("E1", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 102 | 292 check("E2", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 103 void testMixinUses( | 293 check("E3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 104 ClassElement cls, | 294 |
| 105 List<ClassElement> expectedClasses, | 295 // class F1 extends F instantiated |
| 106 {bool exact: true}) { | 296 // class F2 implements F instantiated |
| 107 check( | 297 check("F", hasStrictSubtype: true, hasOnlySubclasses: false); |
| 108 'mixinUsesOf', | 298 check("F1", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 109 cls, | 299 check("F2", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 110 classWorld.mixinUsesOf(cls), | 300 check("F3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 111 expectedClasses, | 301 |
| 112 exact: exact); | 302 // class G2 extends G1 extends G instantiated |
| 113 } | 303 // class G3 extends G2 extends G1 extends G instantiated |
| 114 | 304 check("G", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 115 testSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); | 305 check("G1", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 116 testSubclasses(A, [A, C]); | 306 check("G2", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 117 testSubclasses(B, [B, E]); | 307 check("G3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 118 testSubclasses(C, [C]); | 308 check("G4", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 119 testSubclasses(D, [D]); | 309 |
| 120 testSubclasses(E, [E]); | 310 // class H4 extends H2 with H extends H1 extends H instantiated |
| 121 testSubclasses(F, [F]); | 311 check("H", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 122 testSubclasses(G, [G]); | 312 check("H1", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 123 | 313 check("H2", hasStrictSubtype: true, hasOnlySubclasses: true); |
| 124 testStrictSubclasses(Object_, [A, B, C, D, E, F, G], exact: false); | 314 check("H3", hasStrictSubtype: false, hasOnlySubclasses: true); |
| 125 testStrictSubclasses(A, [C]); | 315 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 } | 316 } |
| OLD | NEW |