Chromium Code Reviews| 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 |