OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 // Test that the optimized algorithm for mixin applications matches the mixins |
| 6 // generated by fasta. |
| 7 library dart2js.kernel.mixins_test; |
| 8 |
| 9 import 'package:async_helper/async_helper.dart'; |
| 10 import 'package:compiler/src/commandline_options.dart'; |
| 11 import 'package:compiler/src/common_elements.dart'; |
| 12 import 'package:compiler/src/compiler.dart'; |
| 13 import 'package:compiler/src/elements/entities.dart'; |
| 14 import 'package:compiler/src/elements/types.dart'; |
| 15 import 'package:compiler/src/kernel/kernel_strategy.dart'; |
| 16 import 'package:compiler/src/resolution/class_hierarchy.dart'; |
| 17 import 'package:compiler/src/universe/class_set.dart'; |
| 18 import 'package:compiler/src/world.dart'; |
| 19 import 'package:expect/expect.dart'; |
| 20 import '../memory_compiler.dart'; |
| 21 import '../equivalence/check_helpers.dart'; |
| 22 import 'test_helpers.dart'; |
| 23 import 'compiler_helper.dart'; |
| 24 |
| 25 const SOURCE = const { |
| 26 'main.dart': ''' |
| 27 |
| 28 class Super {} |
| 29 class Mixin1 {} |
| 30 class Mixin2 {} |
| 31 class Sub1 extends Super with Mixin1 {} |
| 32 class Sub2 extends Super with Mixin1, Mixin2 {} |
| 33 class NamedSub1 = Super with Mixin1; |
| 34 class NamedSub2 = Super with Mixin1, Mixin2; |
| 35 |
| 36 |
| 37 class GenericSuper<T> {} |
| 38 class GenericMixin1<T> {} |
| 39 class GenericMixin2<T> {} |
| 40 class GenericSub1<T> extends GenericSuper<T> with GenericMixin1<T> {} |
| 41 class GenericSub2<T> extends GenericSuper<T> |
| 42 with GenericMixin1<T>, GenericMixin2<T> {} |
| 43 class GenericNamedSub1<T> = GenericSuper<T> with GenericMixin1<T>; |
| 44 class GenericNamedSub2<T> = GenericSuper<T> |
| 45 with GenericMixin1<T>, GenericMixin2<T>; |
| 46 |
| 47 class FixedSub1a extends GenericSuper<int> with GenericMixin1<int> {} |
| 48 class FixedSub1b extends GenericSuper<int> with GenericMixin1<double> {} |
| 49 class FixedSub2a extends GenericSuper<int> |
| 50 with GenericMixin1<int>, GenericMixin2<int> {} |
| 51 class FixedSub2b extends GenericSuper<double> |
| 52 with GenericMixin1<double>, GenericMixin2<double> {} |
| 53 |
| 54 |
| 55 main() { |
| 56 new Super(); |
| 57 new Mixin1(); |
| 58 new Mixin2(); |
| 59 new Sub1(); |
| 60 new Sub2(); |
| 61 new NamedSub1(); |
| 62 new NamedSub2(); |
| 63 |
| 64 new GenericSuper<int>(); |
| 65 new GenericMixin1<int>(); |
| 66 new GenericMixin2<int>(); |
| 67 new GenericSub1<int>(); |
| 68 new GenericSub2<int>(); |
| 69 new GenericNamedSub1<int>(); |
| 70 new GenericNamedSub2<int>(); |
| 71 |
| 72 new FixedSub1a(); |
| 73 new FixedSub1b(); |
| 74 new FixedSub2a(); |
| 75 new FixedSub2b(); |
| 76 } |
| 77 ''' |
| 78 }; |
| 79 |
| 80 Map<ClassEntity, String> generateClassEnv( |
| 81 ElementEnvironment env, DartTypes types) { |
| 82 Map<ClassEntity, String> classEnv = <ClassEntity, String>{}; |
| 83 |
| 84 void createEnv(ClassEntity cls) { |
| 85 classEnv.putIfAbsent(cls, () { |
| 86 InterfaceType thisType = env.getThisType(cls); |
| 87 StringBuffer sb = new StringBuffer(); |
| 88 sb.write('class '); |
| 89 sb.write(env.getThisType(cls)); |
| 90 ClassEntity superclass = env.getSuperClass(cls); |
| 91 if (superclass != null) { |
| 92 createEnv(superclass); |
| 93 sb.write(' extends '); |
| 94 sb.write(types.asInstanceOf(thisType, superclass)); |
| 95 } |
| 96 return sb.toString(); |
| 97 }); |
| 98 } |
| 99 |
| 100 env.forEachClass(env.mainLibrary, createEnv); |
| 101 |
| 102 return classEnv; |
| 103 } |
| 104 |
| 105 main(List<String> args) { |
| 106 asyncTest(() async { |
| 107 useOptimizedMixins = true; |
| 108 |
| 109 Uri entryPoint = await createTemp(Uri.parse('memory:main.dart'), SOURCE, |
| 110 printSteps: true); |
| 111 |
| 112 print( |
| 113 '---- compiler from ast -----------------------------------------------'
); |
| 114 var result = |
| 115 await runCompiler(entryPoint: entryPoint, options: [Flags.analyzeOnly]); |
| 116 Compiler compiler1 = result.compiler; |
| 117 |
| 118 Compiler compiler2 = await compileWithDill( |
| 119 entryPoint, {}, [Flags.analyzeOnly], |
| 120 printSteps: true); |
| 121 |
| 122 ElementEnvironment env1 = compiler1.frontendStrategy.elementEnvironment; |
| 123 DartTypes types1 = compiler1.frontendStrategy.dartTypes; |
| 124 ClosedWorld closedWorld1 = compiler1.resolutionWorldBuilder.closeWorld(); |
| 125 |
| 126 KernelFrontEndStrategy frontendStrategy = compiler2.frontendStrategy; |
| 127 ElementEnvironment env2 = frontendStrategy.elementEnvironment; |
| 128 DartTypes types2 = frontendStrategy.dartTypes; |
| 129 ClosedWorld closedWorld2 = compiler2.resolutionWorldBuilder.closeWorld(); |
| 130 |
| 131 KernelEquivalence equivalence = |
| 132 new KernelEquivalence(frontendStrategy.elementMap); |
| 133 |
| 134 if (args.contains('-v')) { |
| 135 Map<ClassEntity, String> classEnv1 = generateClassEnv(env1, types1); |
| 136 Map<ClassEntity, String> classEnv2 = generateClassEnv(env2, types2); |
| 137 |
| 138 print('----'); |
| 139 classEnv1.forEach((ClassEntity cls, String env) { |
| 140 print(env); |
| 141 }); |
| 142 print('----'); |
| 143 classEnv2.forEach((ClassEntity cls, String env) { |
| 144 print(env); |
| 145 }); |
| 146 } |
| 147 |
| 148 void checkClasses(ClassEntity cls1, ClassEntity cls2) { |
| 149 if (cls1 == cls2) return; |
| 150 Expect.isNotNull(cls1, 'Missing class ${cls2.name}'); |
| 151 Expect.isNotNull(cls2, 'Missing class ${cls1.name}'); |
| 152 |
| 153 check(cls1.library, cls2.library, 'class ${cls1.name}', cls1, cls2, |
| 154 equivalence.entityEquivalence); |
| 155 InterfaceType thisType1 = types1.getThisType(cls1); |
| 156 InterfaceType thisType2 = types2.getThisType(cls2); |
| 157 check(cls1, cls2, 'thisType', thisType1, thisType2, |
| 158 equivalence.typeEquivalence); |
| 159 check(cls1, cls2, 'supertype', types1.getSupertype(cls1), |
| 160 types2.getSupertype(cls2), equivalence.typeEquivalence); |
| 161 checkClasses(env1.getSuperClass(cls1), env2.getSuperClass(cls2)); |
| 162 |
| 163 List<DartType> mixins1 = <DartType>[]; |
| 164 env1.forEachMixin(cls1, (ClassEntity mixin) { |
| 165 mixins1.add(types1.asInstanceOf(thisType1, mixin)); |
| 166 }); |
| 167 List<DartType> mixins2 = <DartType>[]; |
| 168 env2.forEachMixin(cls2, (ClassEntity mixin) { |
| 169 mixins2.add(types2.asInstanceOf(thisType2, mixin)); |
| 170 }); |
| 171 checkLists( |
| 172 mixins1, mixins2, '${cls1.name} mixins', equivalence.typeEquivalence); |
| 173 |
| 174 checkLists( |
| 175 types1.getInterfaces(cls1).toList(), |
| 176 types2.getInterfaces(cls2).toList(), |
| 177 '${cls1.name} interfaces', |
| 178 equivalence.typeEquivalence); |
| 179 checkLists( |
| 180 types1.getSupertypes(cls1).toList(), |
| 181 types2.getSupertypes(cls2).toList(), |
| 182 '${cls1.name} supertypes', |
| 183 equivalence.typeEquivalence); |
| 184 |
| 185 if (cls1 == compiler1.frontendStrategy.commonElements.objectClass) return; |
| 186 |
| 187 ClassHierarchyNode node1 = closedWorld1.getClassHierarchyNode(cls1); |
| 188 ClassHierarchyNode node2 = closedWorld2.getClassHierarchyNode(cls2); |
| 189 checkSets( |
| 190 new Set.from(node1.directSubclasses), |
| 191 new Set.from(node2.directSubclasses), |
| 192 '${cls1.name} direct subclasses', |
| 193 (a, b) => equivalence.entityEquivalence(a.cls, b.cls)); |
| 194 } |
| 195 |
| 196 env1.forEachClass(env1.mainLibrary, (ClassEntity cls1) { |
| 197 ClassEntity cls2 = env2.lookupClass(env2.mainLibrary, cls1.name); |
| 198 checkClasses(cls1, cls2); |
| 199 }); |
| 200 }); |
| 201 } |
OLD | NEW |