| 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 | 10 import '../common/names.dart' show |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 // TODO(johnniwinther): Find another way to obtain mixin uses. | 275 // TODO(johnniwinther): Find another way to obtain mixin uses. |
| 276 Iterable<MixinApplicationElement> mixinUses = | 276 Iterable<MixinApplicationElement> mixinUses = |
| 277 compiler.world.allMixinUsesOf(enclosingClass); | 277 compiler.world.allMixinUsesOf(enclosingClass); |
| 278 ClassElement mixin = enclosingClass; | 278 ClassElement mixin = enclosingClass; |
| 279 for (MixinApplicationElement mixinApplication in mixinUses) { | 279 for (MixinApplicationElement mixinApplication in mixinUses) { |
| 280 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); | 280 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); |
| 281 } | 281 } |
| 282 } | 282 } |
| 283 | 283 |
| 284 // TODO(9631): support noSuchMethod on native classes. | 284 // TODO(9631): support noSuchMethod on native classes. |
| 285 if (Elements.isInstanceMethod(element) && | 285 if (element.isFunction && |
| 286 element.isInstanceMember && |
| 286 element.name == Identifiers.noSuchMethod_ && | 287 element.name == Identifiers.noSuchMethod_ && |
| 287 _isNativeClassOrExtendsNativeClass(enclosingClass)) { | 288 _isNativeClassOrExtendsNativeClass(enclosingClass)) { |
| 288 reporter.reportErrorMessage( | 289 reporter.reportErrorMessage( |
| 289 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); | 290 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); |
| 290 } | 291 } |
| 291 | 292 |
| 292 return registry.worldImpact; | 293 return registry.worldImpact; |
| 293 }); | 294 }); |
| 294 | 295 |
| 295 } | 296 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 return const DynamicType(); | 429 return const DynamicType(); |
| 429 } | 430 } |
| 430 return result; | 431 return result; |
| 431 } | 432 } |
| 432 | 433 |
| 433 void resolveRedirectionChain(ConstructorElementX constructor, | 434 void resolveRedirectionChain(ConstructorElementX constructor, |
| 434 Spannable node) { | 435 Spannable node) { |
| 435 ConstructorElementX target = constructor; | 436 ConstructorElementX target = constructor; |
| 436 InterfaceType targetType; | 437 InterfaceType targetType; |
| 437 List<Element> seen = new List<Element>(); | 438 List<Element> seen = new List<Element>(); |
| 439 bool isMalformed = false; |
| 438 // Follow the chain of redirections and check for cycles. | 440 // Follow the chain of redirections and check for cycles. |
| 439 while (target.isRedirectingFactory || target.isPatched) { | 441 while (target.isRedirectingFactory || target.isPatched) { |
| 440 if (target.internalEffectiveTarget != null) { | 442 if (target.effectiveTargetInternal != null) { |
| 441 // We found a constructor that already has been processed. | 443 // We found a constructor that already has been processed. |
| 442 targetType = target.effectiveTargetType; | 444 targetType = target.effectiveTargetType; |
| 443 assert(invariant(target, targetType != null, | 445 assert(invariant(target, targetType != null, |
| 444 message: 'Redirection target type has not been computed for ' | 446 message: 'Redirection target type has not been computed for ' |
| 445 '$target')); | 447 '$target')); |
| 446 target = target.internalEffectiveTarget; | 448 target = target.effectiveTargetInternal; |
| 447 break; | 449 break; |
| 448 } | 450 } |
| 449 | 451 |
| 450 Element nextTarget; | 452 Element nextTarget; |
| 451 if (target.isPatched) { | 453 if (target.isPatched) { |
| 452 nextTarget = target.patch; | 454 nextTarget = target.patch; |
| 453 } else { | 455 } else { |
| 454 nextTarget = target.immediateRedirectionTarget; | 456 nextTarget = target.immediateRedirectionTarget; |
| 455 } | 457 } |
| 456 | 458 |
| 457 if (seen.contains(nextTarget)) { | 459 if (seen.contains(nextTarget)) { |
| 458 reporter.reportErrorMessage( | 460 reporter.reportErrorMessage( |
| 459 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); | 461 node, MessageKind.CYCLIC_REDIRECTING_FACTORY); |
| 460 targetType = target.enclosingClass.thisType; | 462 targetType = target.enclosingClass.thisType; |
| 463 isMalformed = true; |
| 461 break; | 464 break; |
| 462 } | 465 } |
| 463 seen.add(target); | 466 seen.add(target); |
| 464 target = nextTarget; | 467 target = nextTarget; |
| 465 } | 468 } |
| 466 | 469 |
| 470 if (target.isGenerativeConstructor && target.enclosingClass.isAbstract) { |
| 471 isMalformed = true; |
| 472 } |
| 473 if (target.isMalformed) { |
| 474 isMalformed = true; |
| 475 } |
| 476 |
| 467 if (targetType == null) { | 477 if (targetType == null) { |
| 468 assert(!target.isRedirectingFactory); | 478 assert(!target.isRedirectingFactory); |
| 469 targetType = target.enclosingClass.thisType; | 479 targetType = target.enclosingClass.thisType; |
| 470 } | 480 } |
| 471 | 481 |
| 472 // [target] is now the actual target of the redirections. Run through | 482 // [target] is now the actual target of the redirections. Run through |
| 473 // the constructors again and set their [redirectionTarget], so that we | 483 // the constructors again and set their [redirectionTarget], so that we |
| 474 // do not have to run the loop for these constructors again. Furthermore, | 484 // do not have to run the loop for these constructors again. Furthermore, |
| 475 // compute [redirectionTargetType] for each factory by computing the | 485 // compute [redirectionTargetType] for each factory by computing the |
| 476 // substitution of the target type with respect to the factory type. | 486 // substitution of the target type with respect to the factory type. |
| 477 while (!seen.isEmpty) { | 487 while (!seen.isEmpty) { |
| 478 ConstructorElementX factory = seen.removeLast(); | 488 ConstructorElementX factory = seen.removeLast(); |
| 479 | |
| 480 // [factory] must already be analyzed but the [TreeElements] might not | |
| 481 // have been stored in the enqueuer cache yet. | |
| 482 // TODO(johnniwinther): Store [TreeElements] in the cache before | |
| 483 // resolution of the element. | |
| 484 TreeElements treeElements = factory.treeElements; | 489 TreeElements treeElements = factory.treeElements; |
| 485 assert(invariant(node, treeElements != null, | 490 assert(invariant(node, treeElements != null, |
| 486 message: 'No TreeElements cached for $factory.')); | 491 message: 'No TreeElements cached for $factory.')); |
| 487 if (!factory.isPatched) { | 492 if (!factory.isPatched) { |
| 488 FunctionExpression functionNode = factory.parseNode(parsing); | 493 FunctionExpression functionNode = factory.node; |
| 489 RedirectingFactoryBody redirectionNode = functionNode.body; | 494 RedirectingFactoryBody redirectionNode = functionNode.body; |
| 490 DartType factoryType = treeElements.getType(redirectionNode); | 495 DartType factoryType = treeElements.getType(redirectionNode); |
| 491 if (!factoryType.isDynamic) { | 496 if (!factoryType.isDynamic) { |
| 492 targetType = targetType.substByContext(factoryType); | 497 targetType = targetType.substByContext(factoryType); |
| 493 } | 498 } |
| 494 } | 499 } |
| 495 factory.effectiveTarget = target; | 500 factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); |
| 496 factory.effectiveTargetType = targetType; | |
| 497 } | 501 } |
| 498 } | 502 } |
| 499 | 503 |
| 500 /** | 504 /** |
| 501 * Load and resolve the supertypes of [cls]. | 505 * Load and resolve the supertypes of [cls]. |
| 502 * | 506 * |
| 503 * Warning: do not call this method directly. It should only be | 507 * Warning: do not call this method directly. It should only be |
| 504 * called by [resolveClass] and [ClassSupertypeResolver]. | 508 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 505 */ | 509 */ |
| 506 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 510 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
| (...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1097 TreeElements get treeElements { | 1101 TreeElements get treeElements { |
| 1098 assert(invariant(this, _treeElements !=null, | 1102 assert(invariant(this, _treeElements !=null, |
| 1099 message: "TreeElements have not been computed for $this.")); | 1103 message: "TreeElements have not been computed for $this.")); |
| 1100 return _treeElements; | 1104 return _treeElements; |
| 1101 } | 1105 } |
| 1102 | 1106 |
| 1103 void reuseElement() { | 1107 void reuseElement() { |
| 1104 _treeElements = null; | 1108 _treeElements = null; |
| 1105 } | 1109 } |
| 1106 } | 1110 } |
| OLD | NEW |