OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.resolution; | 5 library dart2js.resolution; |
6 | 6 |
7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; |
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); | 441 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); |
442 if (result == null) { | 442 if (result == null) { |
443 // TODO(karklose): warning. | 443 // TODO(karklose): warning. |
444 return const DynamicType(); | 444 return const DynamicType(); |
445 } | 445 } |
446 return result; | 446 return result; |
447 } | 447 } |
448 | 448 |
449 void resolveRedirectionChain(ConstructorElement constructor, Spannable node) { | 449 void resolveRedirectionChain(ConstructorElement constructor, Spannable node) { |
450 ConstructorElement target = constructor; | 450 ConstructorElement target = constructor; |
451 InterfaceType targetType; | 451 DartType targetType; |
452 List<Element> seen = new List<Element>(); | 452 List<ConstructorElement> seen = new List<ConstructorElement>(); |
453 bool isMalformed = false; | 453 bool isMalformed = false; |
454 // Follow the chain of redirections and check for cycles. | 454 // Follow the chain of redirections and check for cycles. |
455 while (target.isRedirectingFactory || target.isPatched) { | 455 while (target.isRedirectingFactory) { |
456 if (target.hasEffectiveTarget) { | 456 if (target.hasEffectiveTarget) { |
457 // We found a constructor that already has been processed. | 457 // We found a constructor that already has been processed. |
458 // TODO(johnniwinther): Should `effectiveTargetType` be part of the | 458 // TODO(johnniwinther): Should `effectiveTargetType` be part of the |
459 // interface? | 459 // interface? |
460 targetType = | 460 targetType = |
461 target.computeEffectiveTargetType(target.enclosingClass.thisType); | 461 target.computeEffectiveTargetType(target.enclosingClass.thisType); |
462 assert(invariant(target, targetType != null, | 462 assert(invariant(target, targetType != null, |
463 message: 'Redirection target type has not been computed for ' | 463 message: 'Redirection target type has not been computed for ' |
464 '$target')); | 464 '$target')); |
465 target = target.effectiveTarget; | 465 target = target.effectiveTarget; |
466 break; | 466 break; |
467 } | 467 } |
468 | 468 |
469 Element nextTarget; | 469 Element nextTarget = target.immediateRedirectionTarget; |
Harry Terkelsen
2016/07/06 16:40:07
much cleaner!
| |
470 if (target.isPatched) { | |
471 nextTarget = target.patch; | |
472 } else { | |
473 nextTarget = target.immediateRedirectionTarget; | |
474 } | |
475 | 470 |
476 if (seen.contains(nextTarget)) { | 471 if (seen.contains(nextTarget)) { |
477 reporter.reportErrorMessage( | 472 reporter.reportErrorMessage( |
478 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); | 473 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); |
479 targetType = target.enclosingClass.thisType; | 474 targetType = target.enclosingClass.thisType; |
480 isMalformed = true; | 475 isMalformed = true; |
481 break; | 476 break; |
482 } | 477 } |
483 seen.add(target); | 478 seen.add(target); |
484 target = nextTarget; | 479 target = nextTarget; |
(...skipping 11 matching lines...) Expand all Loading... | |
496 targetType = target.enclosingClass.thisType; | 491 targetType = target.enclosingClass.thisType; |
497 } | 492 } |
498 | 493 |
499 // [target] is now the actual target of the redirections. Run through | 494 // [target] is now the actual target of the redirections. Run through |
500 // the constructors again and set their [redirectionTarget], so that we | 495 // the constructors again and set their [redirectionTarget], so that we |
501 // do not have to run the loop for these constructors again. Furthermore, | 496 // do not have to run the loop for these constructors again. Furthermore, |
502 // compute [redirectionTargetType] for each factory by computing the | 497 // compute [redirectionTargetType] for each factory by computing the |
503 // substitution of the target type with respect to the factory type. | 498 // substitution of the target type with respect to the factory type. |
504 while (!seen.isEmpty) { | 499 while (!seen.isEmpty) { |
505 ConstructorElementX factory = seen.removeLast(); | 500 ConstructorElementX factory = seen.removeLast(); |
506 TreeElements treeElements = factory.treeElements; | 501 ResolvedAst resolvedAst = factory.resolvedAst; |
507 assert(invariant(node, treeElements != null, | 502 assert(invariant(node, resolvedAst != null, |
508 message: 'No TreeElements cached for $factory.')); | 503 message: 'No ResolvedAst for $factory.')); |
509 if (!factory.isPatched) { | 504 FunctionExpression functionNode = resolvedAst.node; |
510 FunctionExpression functionNode = factory.node; | 505 RedirectingFactoryBody redirectionNode = resolvedAst.body; |
511 RedirectingFactoryBody redirectionNode = functionNode.body; | 506 DartType factoryType = resolvedAst.elements.getType(redirectionNode); |
512 DartType factoryType = treeElements.getType(redirectionNode); | 507 if (!factoryType.isDynamic) { |
513 if (!factoryType.isDynamic) { | 508 targetType = targetType.substByContext(factoryType); |
514 targetType = targetType.substByContext(factoryType); | |
515 } | |
516 } | 509 } |
517 factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); | 510 factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); |
518 } | 511 } |
519 } | 512 } |
520 | 513 |
521 /** | 514 /** |
522 * Load and resolve the supertypes of [cls]. | 515 * Load and resolve the supertypes of [cls]. |
523 * | 516 * |
524 * Warning: do not call this method directly. It should only be | 517 * Warning: do not call this method directly. It should only be |
525 * called by [resolveClass] and [ClassSupertypeResolver]. | 518 * called by [resolveClass] and [ClassSupertypeResolver]. |
(...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1127 TreeElements get treeElements { | 1120 TreeElements get treeElements { |
1128 assert(invariant(this, _treeElements != null, | 1121 assert(invariant(this, _treeElements != null, |
1129 message: "TreeElements have not been computed for $this.")); | 1122 message: "TreeElements have not been computed for $this.")); |
1130 return _treeElements; | 1123 return _treeElements; |
1131 } | 1124 } |
1132 | 1125 |
1133 void reuseElement() { | 1126 void reuseElement() { |
1134 _treeElements = null; | 1127 _treeElements = null; |
1135 } | 1128 } |
1136 } | 1129 } |
OLD | NEW |