Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart

Issue 2954493002: Less inequivalence on Hello World! (Closed)
Patch Set: Fix Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 dart2js.js_emitter.runtime_type_generator; 5 library dart2js.js_emitter.runtime_type_generator;
6 6
7 import '../closure.dart' 7 import '../closure.dart'
8 show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask; 8 show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask;
9 import '../common.dart'; 9 import '../common.dart';
10 import '../common/names.dart' show Identifiers; 10 import '../common/names.dart' show Identifiers;
11 import '../common_elements.dart' show CommonElements; 11 import '../common_elements.dart' show CommonElements, ElementEnvironment;
12 import '../elements/resolution_types.dart'
13 show ResolutionDartType, ResolutionFunctionType, ResolutionInterfaceType;
14 import '../elements/elements.dart' 12 import '../elements/elements.dart'
15 show ClassElement, Element, FunctionElement, MixinApplicationElement; 13 show ClassElement, MethodElement, MixinApplicationElement;
16 import '../elements/entities.dart'; 14 import '../elements/entities.dart';
17 import '../elements/types.dart'; 15 import '../elements/types.dart';
18 import '../js/js.dart' as jsAst; 16 import '../js/js.dart' as jsAst;
19 import '../js/js.dart' show js; 17 import '../js/js.dart' show js;
20 import '../js_backend/js_interop_analysis.dart'; 18 import '../js_backend/js_interop_analysis.dart';
21 import '../js_backend/native_data.dart'; 19 import '../js_backend/native_data.dart';
22 import '../js_backend/namer.dart' show Namer; 20 import '../js_backend/namer.dart' show Namer;
23 import '../js_backend/runtime_types.dart' 21 import '../js_backend/runtime_types.dart'
24 show 22 show
25 RuntimeTypesChecks, 23 RuntimeTypesChecks,
26 RuntimeTypesNeed, 24 RuntimeTypesNeed,
27 RuntimeTypesEncoder, 25 RuntimeTypesEncoder,
28 RuntimeTypesSubstitutions, 26 RuntimeTypesSubstitutions,
29 Substitution, 27 Substitution,
30 TypeCheck, 28 TypeCheck,
31 TypeChecks; 29 TypeChecks;
32 import '../util/util.dart' show Setlet; 30 import '../util/util.dart' show Setlet;
31 import '../world.dart';
33 32
34 import 'code_emitter_task.dart' show CodeEmitterTask; 33 import 'code_emitter_task.dart' show CodeEmitterTask;
35 import 'type_test_registry.dart' show TypeTestRegistry; 34 import 'type_test_registry.dart' show TypeTestRegistry;
36 35
37 // Function signatures used in the generation of runtime type information. 36 // Function signatures used in the generation of runtime type information.
38 typedef void FunctionTypeSignatureEmitter( 37 typedef void FunctionTypeSignatureEmitter(
39 Element method, ResolutionFunctionType methodType); 38 FunctionEntity method, FunctionType methodType);
40 39
41 typedef void SubstitutionEmitter(Element element, {bool emitNull}); 40 typedef void SubstitutionEmitter(ClassEntity element, {bool emitNull});
42 41
43 class TypeTestProperties { 42 class TypeTestProperties {
44 /// The index of the function type into the metadata. 43 /// The index of the function type into the metadata.
45 /// 44 ///
46 /// If the class doesn't have a function type this field is `null`. 45 /// If the class doesn't have a function type this field is `null`.
47 /// 46 ///
48 /// If the is tests were generated with `storeFunctionTypeInMetadata` set to 47 /// If the is tests were generated with `storeFunctionTypeInMetadata` set to
49 /// `false`, this field is `null`, and the [properties] contain a property 48 /// `false`, this field is `null`, and the [properties] contain a property
50 /// that encodes the function type. 49 /// that encodes the function type.
51 jsAst.Expression functionTypeIndex; 50 jsAst.Expression functionTypeIndex;
52 51
53 /// The properties that must be installed on the prototype of the 52 /// The properties that must be installed on the prototype of the
54 /// JS constructor of the [ClassElement] for which the is checks were 53 /// JS constructor of the [ClassEntity] for which the is checks were
55 /// generated. 54 /// generated.
56 final Map<jsAst.Name, jsAst.Node> properties = <jsAst.Name, jsAst.Node>{}; 55 final Map<jsAst.Name, jsAst.Node> properties = <jsAst.Name, jsAst.Node>{};
57 } 56 }
58 57
59 class RuntimeTypeGenerator { 58 class RuntimeTypeGenerator {
59 final ElementEnvironment _elementEnvironment;
60 final CommonElements _commonElements; 60 final CommonElements _commonElements;
61 final DartTypes _types;
62 final ClosedWorld _closedWorld;
61 final ClosureConversionTask _closureDataLookup; 63 final ClosureConversionTask _closureDataLookup;
62 final CodeEmitterTask emitterTask; 64 final CodeEmitterTask emitterTask;
63 final Namer _namer; 65 final Namer _namer;
64 final NativeData _nativeData; 66 final NativeData _nativeData;
65 final RuntimeTypesChecks _rtiChecks; 67 final RuntimeTypesChecks _rtiChecks;
66 final RuntimeTypesEncoder _rtiEncoder; 68 final RuntimeTypesEncoder _rtiEncoder;
67 final RuntimeTypesNeed _rtiNeed; 69 final RuntimeTypesNeed _rtiNeed;
68 final RuntimeTypesSubstitutions _rtiSubstitutions; 70 final RuntimeTypesSubstitutions _rtiSubstitutions;
69 final JsInteropAnalysis _jsInteropAnalysis; 71 final JsInteropAnalysis _jsInteropAnalysis;
70 72
71 RuntimeTypeGenerator( 73 RuntimeTypeGenerator(
74 this._elementEnvironment,
72 this._commonElements, 75 this._commonElements,
76 this._types,
77 this._closedWorld,
73 this._closureDataLookup, 78 this._closureDataLookup,
74 this.emitterTask, 79 this.emitterTask,
75 this._namer, 80 this._namer,
76 this._nativeData, 81 this._nativeData,
77 this._rtiChecks, 82 this._rtiChecks,
78 this._rtiEncoder, 83 this._rtiEncoder,
79 this._rtiNeed, 84 this._rtiNeed,
80 this._rtiSubstitutions, 85 this._rtiSubstitutions,
81 this._jsInteropAnalysis); 86 this._jsInteropAnalysis);
82 87
(...skipping 10 matching lines...) Expand all
93 /// Generates all properties necessary for is-checks on the [classElement]. 98 /// Generates all properties necessary for is-checks on the [classElement].
94 /// 99 ///
95 /// Returns an instance of [TypeTestProperties] that contains the properties 100 /// Returns an instance of [TypeTestProperties] that contains the properties
96 /// that must be installed on the prototype of the JS constructor of the 101 /// that must be installed on the prototype of the JS constructor of the
97 /// [classElement]. 102 /// [classElement].
98 /// 103 ///
99 /// If [storeFunctionTypeInMetadata] is `true`, stores the reified function 104 /// If [storeFunctionTypeInMetadata] is `true`, stores the reified function
100 /// type (if class has one) in the metadata object and stores its index in 105 /// type (if class has one) in the metadata object and stores its index in
101 /// the result. This is only possible for function types that do not contain 106 /// the result. This is only possible for function types that do not contain
102 /// type variables. 107 /// type variables.
103 TypeTestProperties generateIsTests(ClassEntity cls, 108 TypeTestProperties generateIsTests(ClassEntity classElement,
104 {bool storeFunctionTypeInMetadata: true}) { 109 {bool storeFunctionTypeInMetadata: true}) {
105 TypeTestProperties result = new TypeTestProperties(); 110 TypeTestProperties result = new TypeTestProperties();
106 if (cls is! ClassElement) return result;
107 111
108 // TODO(johnniwinther): Handle class entities. 112 assert(!(classElement is ClassElement && !classElement.isDeclaration),
109 ClassElement classElement = cls; 113 failedAt(classElement));
110 assert(classElement.isDeclaration, failedAt(classElement));
111 114
112 /// Generates an is-test if the test is not inherited from a superclass 115 /// Generates an is-test if the test is not inherited from a superclass
113 /// This assumes that for every class an is-tests is generated 116 /// This assumes that for every class an is-tests is generated
114 /// dynamically at runtime. We also always generate tests against 117 /// dynamically at runtime. We also always generate tests against
115 /// native classes. 118 /// native classes.
116 /// TODO(herhut): Generate tests for native classes dynamically, as well. 119 /// TODO(herhut): Generate tests for native classes dynamically, as well.
117 void generateIsTest(ClassElement other) { 120 void generateIsTest(ClassEntity other) {
118 if (_nativeData.isNativeClass(classElement) || 121 if (_nativeData.isNativeClass(classElement) ||
119 !classElement.isSubclassOf(other)) { 122 !_closedWorld.isSubclassOf(classElement, other)) {
120 result.properties[_namer.operatorIs(other)] = js('1'); 123 result.properties[_namer.operatorIs(other)] = js('1');
121 } 124 }
122 } 125 }
123 126
124 void generateFunctionTypeSignature( 127 void generateFunctionTypeSignature(
125 FunctionElement method, ResolutionFunctionType type) { 128 FunctionEntity method, FunctionType type) {
126 assert(method.isImplementation); 129 assert(!(method is MethodElement && !method.isImplementation));
127 jsAst.Expression thisAccess = new jsAst.This(); 130 jsAst.Expression thisAccess = new jsAst.This();
128 if (!method.isAbstract) { 131 if (!method.isAbstract) {
129 ClosureRepresentationInfo closureData = 132 ClosureRepresentationInfo closureData =
130 _closureDataLookup.getClosureRepresentationInfo(method); 133 _closureDataLookup.getClosureRepresentationInfo(method);
131 if (closureData != null) { 134 if (closureData != null) {
132 ClosureFieldElement thisLocal = closureData.thisFieldEntity; 135 ClosureFieldElement thisLocal = closureData.thisFieldEntity;
133 if (thisLocal != null) { 136 if (thisLocal != null) {
134 jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal); 137 jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal);
135 thisAccess = js('this.#', thisName); 138 thisAccess = js('this.#', thisName);
136 } 139 }
137 } 140 }
138 } 141 }
139 142
140 if (storeFunctionTypeInMetadata && !type.containsTypeVariables) { 143 if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
141 result.functionTypeIndex = 144 result.functionTypeIndex =
142 emitterTask.metadataCollector.reifyType(type); 145 emitterTask.metadataCollector.reifyType(type);
143 } else { 146 } else {
144 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding( 147 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
145 emitterTask.emitter, type, thisAccess); 148 emitterTask.emitter, type, thisAccess);
146 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature); 149 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
147 result.properties[operatorSignature] = encoding; 150 result.properties[operatorSignature] = encoding;
148 } 151 }
149 } 152 }
150 153
151 void generateSubstitution(ClassElement cls, {bool emitNull: false}) { 154 void generateSubstitution(ClassEntity cls, {bool emitNull: false}) {
152 if (cls.typeVariables.isEmpty) return; 155 if (!_elementEnvironment.isGenericClass(cls)) return;
153 jsAst.Expression expression; 156 jsAst.Expression expression;
154 bool needsNativeCheck = 157 bool needsNativeCheck =
155 emitterTask.nativeEmitter.requiresNativeIsCheck(cls); 158 emitterTask.nativeEmitter.requiresNativeIsCheck(cls);
156 Substitution substitution = 159 Substitution substitution =
157 _rtiSubstitutions.getSubstitution(classElement, cls); 160 _rtiSubstitutions.getSubstitution(classElement, cls);
158 if (substitution != null) { 161 if (substitution != null) {
159 expression = 162 expression =
160 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution); 163 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution);
161 } 164 }
162 if (expression == null && (emitNull || needsNativeCheck)) { 165 if (expression == null && (emitNull || needsNativeCheck)) {
163 expression = new jsAst.LiteralNull(); 166 expression = new jsAst.LiteralNull();
164 } 167 }
165 if (expression != null) { 168 if (expression != null) {
166 result.properties[_namer.substitutionName(cls)] = expression; 169 result.properties[_namer.substitutionName(cls)] = expression;
167 } 170 }
168 } 171 }
169 172
170 void generateTypeCheck(TypeCheck check) { 173 void generateTypeCheck(TypeCheck check) {
171 ClassElement checkedClass = check.cls; 174 ClassEntity checkedClass = check.cls;
172 generateIsTest(checkedClass); 175 generateIsTest(checkedClass);
173 Substitution substitution = check.substitution; 176 Substitution substitution = check.substitution;
174 if (substitution != null) { 177 if (substitution != null) {
175 jsAst.Expression body = 178 jsAst.Expression body =
176 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution); 179 _rtiEncoder.getSubstitutionCode(emitterTask.emitter, substitution);
177 result.properties[_namer.substitutionName(checkedClass)] = body; 180 result.properties[_namer.substitutionName(checkedClass)] = body;
178 } 181 }
179 } 182 }
180 183
181 _generateIsTestsOn(classElement, (Element e) { 184 _generateIsTestsOn(
182 generateIsTest(e); 185 classElement,
183 }, (Element e, ResolutionFunctionType t) { 186 generateIsTest,
184 generateFunctionTypeSignature(e, t); 187 generateFunctionTypeSignature,
185 }, 188 (ClassEntity e, {bool emitNull: false}) =>
186 (Element e, {bool emitNull: false}) =>
187 generateSubstitution(e, emitNull: emitNull), 189 generateSubstitution(e, emitNull: emitNull),
188 generateTypeCheck); 190 generateTypeCheck);
189 191
190 if (classElement == _commonElements.jsJavaScriptFunctionClass) { 192 if (classElement == _commonElements.jsJavaScriptFunctionClass) {
191 var type = _jsInteropAnalysis.buildJsFunctionType(); 193 var type = _jsInteropAnalysis.buildJsFunctionType();
192 if (type != null) { 194 if (type != null) {
193 jsAst.Expression thisAccess = new jsAst.This(); 195 jsAst.Expression thisAccess = new jsAst.This();
194 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding( 196 jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
195 emitterTask.emitter, type, thisAccess); 197 emitterTask.emitter, type, thisAccess);
196 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature); 198 jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
197 result.properties[operatorSignature] = encoding; 199 result.properties[operatorSignature] = encoding;
198 } 200 }
199 } 201 }
200 return result; 202 return result;
201 } 203 }
202 204
203 /** 205 /**
204 * Generate "is tests" for [cls] itself, and the "is tests" for the 206 * Generate "is tests" for [cls] itself, and the "is tests" for the
205 * classes it implements and type argument substitution functions for these 207 * classes it implements and type argument substitution functions for these
206 * tests. We don't need to add the "is tests" of the super class because 208 * tests. We don't need to add the "is tests" of the super class because
207 * they will be inherited at runtime, but we may need to generate the 209 * they will be inherited at runtime, but we may need to generate the
208 * substitutions, because they may have changed. 210 * substitutions, because they may have changed.
209 */ 211 */
210 void _generateIsTestsOn( 212 void _generateIsTestsOn(
211 ClassElement cls, 213 ClassEntity cls,
212 void generateIsTest(Element element), 214 void generateIsTest(ClassEntity element),
213 FunctionTypeSignatureEmitter generateFunctionTypeSignature, 215 FunctionTypeSignatureEmitter generateFunctionTypeSignature,
214 SubstitutionEmitter generateSubstitution, 216 SubstitutionEmitter generateSubstitution,
215 void emitTypeCheck(TypeCheck check)) { 217 void emitTypeCheck(TypeCheck check)) {
216 Setlet<ClassElement> generated = new Setlet<ClassElement>(); 218 Setlet<ClassEntity> generated = new Setlet<ClassEntity>();
217 219
218 if (checkedClasses.contains(cls)) { 220 if (checkedClasses.contains(cls)) {
219 generateIsTest(cls); 221 generateIsTest(cls);
220 generateSubstitution(cls); 222 generateSubstitution(cls);
221 generated.add(cls); 223 generated.add(cls);
222 } 224 }
223 225
224 // Precomputed is checks. 226 // Precomputed is checks.
225 TypeChecks typeChecks = _rtiChecks.requiredChecks; 227 TypeChecks typeChecks = _rtiChecks.requiredChecks;
226 Iterable<TypeCheck> classChecks = typeChecks[cls]; 228 Iterable<TypeCheck> classChecks = typeChecks[cls];
227 if (classChecks != null) { 229 if (classChecks != null) {
228 for (TypeCheck check in classChecks) { 230 for (TypeCheck check in classChecks) {
229 if (!generated.contains(check.cls)) { 231 if (!generated.contains(check.cls)) {
230 emitTypeCheck(check); 232 emitTypeCheck(check);
231 generated.add(check.cls); 233 generated.add(check.cls);
232 } 234 }
233 } 235 }
234 } 236 }
235 237
236 ClassElement superclass = cls.superclass; 238 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
237 239
238 bool haveSameTypeVariables(ClassElement a, ClassElement b) { 240 bool haveSameTypeVariables(ClassEntity a, ClassEntity b) {
239 if (a.isClosure) return true; 241 if (a.isClosure) return true;
240 return _rtiSubstitutions.isTrivialSubstitution(a, b); 242 return _rtiSubstitutions.isTrivialSubstitution(a, b);
241 } 243 }
242 244
243 bool supertypesNeedSubstitutions = false; 245 bool supertypesNeedSubstitutions = false;
244 246
245 if (superclass != null && 247 if (superclass != null &&
246 superclass != _commonElements.objectClass && 248 superclass != _commonElements.objectClass &&
247 !haveSameTypeVariables(cls, superclass)) { 249 !haveSameTypeVariables(cls, superclass)) {
248 // We cannot inherit the generated substitutions, because the type 250 // We cannot inherit the generated substitutions, because the type
249 // variable layout for this class is different. Instead we generate 251 // variable layout for this class is different. Instead we generate
250 // substitutions for all checks and make emitSubstitution a NOP for the 252 // substitutions for all checks and make emitSubstitution a NOP for the
251 // rest of this function. 253 // rest of this function.
252 254
253 // TODO(karlklose): move the computation of these checks to 255 // TODO(karlklose): move the computation of these checks to
254 // RuntimeTypeInformation. 256 // RuntimeTypeInformation.
255 while (superclass != null) { 257 while (superclass != null) {
256 if (_rtiNeed.classNeedsRti(superclass)) { 258 if (_rtiNeed.classNeedsRti(superclass)) {
257 generateSubstitution(superclass, emitNull: true); 259 generateSubstitution(superclass, emitNull: true);
258 generated.add(superclass); 260 generated.add(superclass);
259 } 261 }
260 superclass = superclass.superclass; 262 superclass = _elementEnvironment.getSuperClass(superclass);
261 } 263 }
262 supertypesNeedSubstitutions = true; 264 supertypesNeedSubstitutions = true;
263 } 265 }
264 266
265 if (cls is MixinApplicationElement) { 267 if (cls is MixinApplicationElement) {
266 supertypesNeedSubstitutions = true; 268 supertypesNeedSubstitutions = true;
267 } 269 }
268 270
269 if (supertypesNeedSubstitutions) { 271 if (supertypesNeedSubstitutions) {
270 for (ResolutionInterfaceType supertype in cls.allSupertypes) { 272 _elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
271 ClassElement superclass = supertype.element; 273 ClassEntity superclass = supertype.element;
272 if (generated.contains(superclass)) continue; 274 if (generated.contains(superclass)) return;
273 275
274 if (classesUsingTypeVariableTests.contains(superclass) || 276 if (classesUsingTypeVariableTests.contains(superclass) ||
275 _rtiNeed.classUsesTypeVariableExpression(superclass) || 277 _rtiNeed.classUsesTypeVariableExpression(superclass) ||
276 checkedClasses.contains(superclass)) { 278 checkedClasses.contains(superclass)) {
277 // Generate substitution. If no substitution is necessary, emit 279 // Generate substitution. If no substitution is necessary, emit
278 // `null` to overwrite a (possibly) existing substitution from the 280 // `null` to overwrite a (possibly) existing substitution from the
279 // super classes. 281 // super classes.
280 generateSubstitution(superclass, emitNull: true); 282 generateSubstitution(superclass, emitNull: true);
281 } 283 }
282 } 284 });
283 285
284 void emitNothing(_, {emitNull}) {} 286 void emitNothing(_, {emitNull}) {}
285 287
286 generateSubstitution = emitNothing; 288 generateSubstitution = emitNothing;
287 } 289 }
288 290
289 // A class that defines a `call` method implicitly implements 291 // A class that defines a `call` method implicitly implements
290 // [Function] and needs checks for all typedefs that are used in is-checks. 292 // [Function] and needs checks for all typedefs that are used in is-checks.
291 if (checkedClasses.contains(_commonElements.functionClass) || 293 if (checkedClasses.contains(_commonElements.functionClass) ||
292 checkedFunctionTypes.isNotEmpty) { 294 checkedFunctionTypes.isNotEmpty) {
293 Element call = cls.lookupLocalMember(Identifiers.call); 295 MemberEntity call =
294 if (call == null) { 296 _elementEnvironment.lookupClassMember(cls, Identifiers.call);
295 // If [cls] is a closure, it has a synthetic call operator method.
296 call = cls.lookupConstructorBody(Identifiers.call);
Siggi Cherem (dart-lang) 2017/06/23 19:49:28 Was this basically dead code? I'm guessing this u
Johnni Winther 2017/06/26 09:17:44 Yes. Yes.
297 }
298 if (call != null && call.isFunction) { 297 if (call != null && call.isFunction) {
299 FunctionElement callFunction = call; 298 FunctionEntity callFunction = call;
300 // A superclass might already implement the Function interface. In such 299 // A superclass might already implement the Function interface. In such
301 // a case, we can avoid emiting the is test here. 300 // a case, we can avoid emitting the is test here.
302 if (!cls.superclass.implementsFunction(_commonElements)) { 301 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
302 if (!_closedWorld.isSubclassOf(
303 superclass, _commonElements.functionClass)) {
303 _generateInterfacesIsTests(_commonElements.functionClass, 304 _generateInterfacesIsTests(_commonElements.functionClass,
304 generateIsTest, generateSubstitution, generated); 305 generateIsTest, generateSubstitution, generated);
305 } 306 }
306 ResolutionFunctionType callType = callFunction.type; 307 FunctionType callType =
308 _elementEnvironment.getFunctionType(callFunction);
307 generateFunctionTypeSignature(callFunction, callType); 309 generateFunctionTypeSignature(callFunction, callType);
308 } 310 }
309 } 311 }
310 312
311 for (ResolutionDartType interfaceType in cls.interfaces) { 313 for (InterfaceType interfaceType in _types.getInterfaces(cls)) {
312 _generateInterfacesIsTests(interfaceType.element, generateIsTest, 314 _generateInterfacesIsTests(interfaceType.element, generateIsTest,
313 generateSubstitution, generated); 315 generateSubstitution, generated);
314 } 316 }
315 } 317 }
316 318
317 /** 319 /**
318 * Generate "is tests" where [cls] is being implemented. 320 * Generate "is tests" where [cls] is being implemented.
319 */ 321 */
320 void _generateInterfacesIsTests( 322 void _generateInterfacesIsTests(
321 ClassElement cls, 323 ClassEntity cls,
322 void generateIsTest(ClassElement element), 324 void generateIsTest(ClassEntity element),
323 SubstitutionEmitter generateSubstitution, 325 SubstitutionEmitter generateSubstitution,
324 Set<Element> alreadyGenerated) { 326 Set<ClassEntity> alreadyGenerated) {
325 void tryEmitTest(ClassElement check) { 327 void tryEmitTest(ClassEntity check) {
326 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) { 328 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) {
327 alreadyGenerated.add(check); 329 alreadyGenerated.add(check);
328 generateIsTest(check); 330 generateIsTest(check);
329 generateSubstitution(check); 331 generateSubstitution(check);
330 } 332 }
331 } 333 }
332 334
333 tryEmitTest(cls); 335 tryEmitTest(cls);
334 336
335 for (ResolutionDartType interfaceType in cls.interfaces) { 337 for (InterfaceType interfaceType in _types.getInterfaces(cls)) {
336 Element element = interfaceType.element; 338 ClassEntity element = interfaceType.element;
337 tryEmitTest(element); 339 tryEmitTest(element);
338 _generateInterfacesIsTests( 340 _generateInterfacesIsTests(
339 element, generateIsTest, generateSubstitution, alreadyGenerated); 341 element, generateIsTest, generateSubstitution, alreadyGenerated);
340 } 342 }
341 343
342 // We need to also emit "is checks" for the superclass and its supertypes. 344 // We need to also emit "is checks" for the superclass and its supertypes.
343 ClassElement superclass = cls.superclass; 345 ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
344 if (superclass != null) { 346 if (superclass != null) {
345 tryEmitTest(superclass); 347 tryEmitTest(superclass);
346 _generateInterfacesIsTests( 348 _generateInterfacesIsTests(
347 superclass, generateIsTest, generateSubstitution, alreadyGenerated); 349 superclass, generateIsTest, generateSubstitution, alreadyGenerated);
348 } 350 }
349 } 351 }
350 } 352 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698