OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection' show Queue; | 6 import 'dart:collection' show Queue; |
7 | 7 |
8 import 'package:kernel/ast.dart' as ir; | 8 import 'package:kernel/ast.dart' as ir; |
9 import 'package:kernel/checks.dart' show CheckParentPointers; | 9 import 'package:kernel/checks.dart' show CheckParentPointers; |
10 | 10 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 isAbstract: cls.isAbstract, | 187 isAbstract: cls.isAbstract, |
188 typeParameters: null, | 188 typeParameters: null, |
189 implementedTypes: null, | 189 implementedTypes: null, |
190 constructors: null, | 190 constructors: null, |
191 procedures: null, | 191 procedures: null, |
192 fields: null); | 192 fields: null); |
193 addWork(cls, () { | 193 addWork(cls, () { |
194 if (cls.supertype != null) { | 194 if (cls.supertype != null) { |
195 classNode.supertype = interfaceTypeToIr(cls.supertype); | 195 classNode.supertype = interfaceTypeToIr(cls.supertype); |
196 } | 196 } |
| 197 if (cls.isMixinApplication) { |
| 198 MixinApplicationElement mixinApplication = cls; |
| 199 classNode.mixedInType = interfaceTypeToIr(mixinApplication.mixinType); |
| 200 } |
197 classNode.parent = libraryToIr(cls.library); | 201 classNode.parent = libraryToIr(cls.library); |
198 if (cls.isUnnamedMixinApplication) { | 202 if (cls.isUnnamedMixinApplication) { |
199 classNode.enclosingLibrary.addClass(classNode); | 203 classNode.enclosingLibrary.addClass(classNode); |
200 } | 204 } |
201 cls.implementation | 205 cls.implementation |
202 .forEachMember((ClassElement enclosingClass, Element member) { | 206 .forEachMember((ClassElement enclosingClass, Element member) { |
203 if (member.enclosingClass.declaration != cls) { | 207 if (member.enclosingClass.declaration != cls) { |
204 // TODO(het): figure out why impact_test triggers this | 208 // TODO(het): figure out why impact_test triggers this |
205 //internalError(cls, "`$member` isn't mine."); | 209 //internalError(cls, "`$member` isn't mine."); |
206 } else if (member.isFunction || | 210 } else if (member.isFunction || |
207 member.isAccessor || | 211 member.isAccessor || |
208 member.isConstructor) { | 212 member.isConstructor) { |
209 classNode.addMember(functionToIr(member)); | 213 classNode.addMember(functionToIr(member)); |
210 } else if (member.isField) { | 214 } else if (member.isField) { |
211 classNode.addMember(fieldToIr(member)); | 215 classNode.addMember(fieldToIr(member)); |
212 } else { | 216 } else { |
213 internalError(member, "Unhandled class member: $member"); | 217 internalError(member, "Unhandled class member: $member"); |
214 } | 218 } |
215 }); | 219 }); |
216 classNode.typeParameters.addAll(typeVariablesToIr(cls.typeVariables)); | 220 classNode.typeParameters.addAll(typeVariablesToIr(cls.typeVariables)); |
217 for (ir.InterfaceType interface | 221 for (ir.InterfaceType interface |
218 in typesToIr(cls.interfaces.reverse().toList())) { | 222 in typesToIr(cls.interfaces.reverse().toList())) { |
219 classNode.implementedTypes.add(interface); | 223 classNode.implementedTypes.add(interface); |
220 } | 224 } |
| 225 addWork(cls, () { |
| 226 addDefaultInstanceFieldInitializers(classNode); |
| 227 }); |
221 }); | 228 }); |
222 addWork(cls.declaration, () { | 229 addWork(cls.declaration, () { |
223 for (MetadataAnnotation metadata in cls.declaration.metadata) { | 230 for (MetadataAnnotation metadata in cls.declaration.metadata) { |
224 classNode.addAnnotation( | 231 classNode.addAnnotation( |
225 const ConstantVisitor().visit(metadata.constant, this)); | 232 const ConstantVisitor().visit(metadata.constant, this)); |
226 } | 233 } |
227 }); | 234 }); |
228 return classNode; | 235 return classNode; |
229 }); | 236 }); |
230 } | 237 } |
231 | 238 |
| 239 /// Adds initializers to instance fields that are have no initializer and are |
| 240 /// not initialized by all constructors in the class. |
| 241 /// |
| 242 /// This is more or less copied directly from `ast_from_analyzer.dart` in |
| 243 /// dartk. |
| 244 void addDefaultInstanceFieldInitializers(ir.Class node) { |
| 245 List<ir.Field> uninitializedFields = new List<ir.Field>(); |
| 246 for (ir.Field field in node.fields) { |
| 247 if (field.initializer != null || field.isStatic) continue; |
| 248 uninitializedFields.add(field); |
| 249 } |
| 250 if (uninitializedFields.isEmpty) return; |
| 251 constructorLoop: |
| 252 for (ir.Constructor constructor in node.constructors) { |
| 253 Set<ir.Field> remainingFields = uninitializedFields.toSet(); |
| 254 for (ir.Initializer initializer in constructor.initializers) { |
| 255 if (initializer is ir.FieldInitializer) { |
| 256 remainingFields.remove(initializer.field); |
| 257 } else if (initializer is ir.RedirectingInitializer) { |
| 258 // The target constructor will be checked in another iteration. |
| 259 continue constructorLoop; |
| 260 } |
| 261 } |
| 262 for (ir.Field field in remainingFields) { |
| 263 if (field.initializer == null) { |
| 264 field.initializer = new ir.NullLiteral()..parent = field; |
| 265 } |
| 266 } |
| 267 } |
| 268 } |
| 269 |
232 bool hasHierarchyProblem(ClassElement cls) => cls.hasIncompleteHierarchy; | 270 bool hasHierarchyProblem(ClassElement cls) => cls.hasIncompleteHierarchy; |
233 | 271 |
234 ir.InterfaceType interfaceTypeToIr(InterfaceType type) { | 272 ir.InterfaceType interfaceTypeToIr(InterfaceType type) { |
235 ir.Class cls = classToIr(type.element); | 273 ir.Class cls = classToIr(type.element); |
236 if (type.typeArguments.isEmpty) { | 274 if (type.typeArguments.isEmpty) { |
237 return cls.rawType; | 275 return cls.rawType; |
238 } else { | 276 } else { |
239 return new ir.InterfaceType(cls, typesToIr(type.typeArguments)); | 277 return new ir.InterfaceType(cls, typesToIr(type.typeArguments)); |
240 } | 278 } |
241 } | 279 } |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 ir.DartType type = | 490 ir.DartType type = |
453 field.isMalformed ? const ir.InvalidType() : typeToIr(field.type); | 491 field.isMalformed ? const ir.InvalidType() : typeToIr(field.type); |
454 ir.Field fieldNode = new ir.Field(irName(field.memberName.text, field), | 492 ir.Field fieldNode = new ir.Field(irName(field.memberName.text, field), |
455 type: type, | 493 type: type, |
456 initializer: null, | 494 initializer: null, |
457 isFinal: field.isFinal, | 495 isFinal: field.isFinal, |
458 isStatic: field.isStatic || field.isTopLevel, | 496 isStatic: field.isStatic || field.isTopLevel, |
459 isConst: field.isConst); | 497 isConst: field.isConst); |
460 addWork(field, () { | 498 addWork(field, () { |
461 setParent(fieldNode, field); | 499 setParent(fieldNode, field); |
462 if (!field.isMalformed && field.initializer != null) { | 500 if (!field.isMalformed) { |
463 KernelVisitor visitor = | 501 if (field.initializer != null) { |
464 new KernelVisitor(field, field.treeElements, this); | 502 KernelVisitor visitor = |
465 fieldNode.initializer = visitor.buildInitializer() | 503 new KernelVisitor(field, field.treeElements, this); |
466 ..parent = fieldNode; | 504 fieldNode.initializer = visitor.buildInitializer() |
| 505 ..parent = fieldNode; |
| 506 } else if (!field.isInstanceMember) { |
| 507 fieldNode.initializer = new ir.NullLiteral()..parent = fieldNode; |
| 508 } |
467 } | 509 } |
468 }); | 510 }); |
469 addWork(field.declaration, () { | 511 addWork(field.declaration, () { |
470 for (MetadataAnnotation metadata in field.declaration.metadata) { | 512 for (MetadataAnnotation metadata in field.declaration.metadata) { |
471 fieldNode.addAnnotation( | 513 fieldNode.addAnnotation( |
472 const ConstantVisitor().visit(metadata.constant, this)); | 514 const ConstantVisitor().visit(metadata.constant, this)); |
473 } | 515 } |
474 }); | 516 }); |
475 return fieldNode; | 517 return fieldNode; |
476 }); | 518 }); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
690 } | 732 } |
691 | 733 |
692 class ConstructorTarget { | 734 class ConstructorTarget { |
693 final ConstructorElement element; | 735 final ConstructorElement element; |
694 final DartType type; | 736 final DartType type; |
695 | 737 |
696 ConstructorTarget(this.element, this.type); | 738 ConstructorTarget(this.element, this.type); |
697 | 739 |
698 String toString() => "ConstructorTarget($element, $type)"; | 740 String toString() => "ConstructorTarget($element, $type)"; |
699 } | 741 } |
OLD | NEW |