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

Side by Side Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 746993002: Avoid patching in dart2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « pkg/compiler/lib/src/js_backend/patch_resolver.dart ('k') | pkg/compiler/lib/src/warnings.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 part of resolution; 5 part of resolution;
6 6
7 abstract class TreeElements { 7 abstract class TreeElements {
8 AnalyzableElement get analyzedElement; 8 AnalyzableElement get analyzedElement;
9 Iterable<Node> get superUses; 9 Iterable<Node> get superUses;
10 10
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 112
113 /// Map from labeled goto statements to the labels they target. 113 /// Map from labeled goto statements to the labels they target.
114 Map<GotoStatement, LabelDefinition> _targetLabels; 114 Map<GotoStatement, LabelDefinition> _targetLabels;
115 115
116 final int hashCode = ++_hashCodeCounter; 116 final int hashCode = ++_hashCodeCounter;
117 static int _hashCodeCounter = 0; 117 static int _hashCodeCounter = 0;
118 118
119 TreeElementMapping(this.analyzedElement); 119 TreeElementMapping(this.analyzedElement);
120 120
121 operator []=(Node node, Element element) { 121 operator []=(Node node, Element element) {
122 assert(invariant(node, () {
123 FunctionExpression functionExpression = node.asFunctionExpression();
124 if (functionExpression != null) {
125 return !functionExpression.modifiers.isExternal;
126 }
127 return true;
128 }));
129 // TODO(johnniwinther): Simplify this invariant to use only declarations in 122 // TODO(johnniwinther): Simplify this invariant to use only declarations in
130 // [TreeElements]. 123 // [TreeElements].
131 assert(invariant(node, () { 124 assert(invariant(node, () {
132 if (!element.isErroneous && analyzedElement != null && element.isPatch) { 125 if (!element.isErroneous && analyzedElement != null && element.isPatch) {
133 return analyzedElement.implementationLibrary.isPatch; 126 return analyzedElement.implementationLibrary.isPatch;
134 } 127 }
135 return true; 128 return true;
136 })); 129 }));
137 // TODO(ahe): Investigate why the invariant below doesn't hold. 130 // TODO(ahe): Investigate why the invariant below doesn't hold.
138 // assert(invariant(node, 131 // assert(invariant(node,
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 redirection = redirection.implementation; 484 redirection = redirection.implementation;
492 if (seen.contains(redirection)) { 485 if (seen.contains(redirection)) {
493 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); 486 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
494 return; 487 return;
495 } 488 }
496 seen.add(redirection); 489 seen.add(redirection);
497 redirection = resolver.visitor.resolveConstructorRedirection(redirection); 490 redirection = resolver.visitor.resolveConstructorRedirection(redirection);
498 } 491 }
499 } 492 }
500 493
501 void checkMatchingPatchParameters(FunctionElement origin,
502 Link<Element> originParameters,
503 Link<Element> patchParameters) {
504 while (!originParameters.isEmpty) {
505 ParameterElementX originParameter = originParameters.head;
506 ParameterElementX patchParameter = patchParameters.head;
507 // TODO(johnniwinther): Remove the conditional patching when we never
508 // resolve the same method twice.
509 if (!originParameter.isPatched) {
510 originParameter.applyPatch(patchParameter);
511 } else {
512 assert(invariant(origin, originParameter.patch == patchParameter,
513 message: "Inconsistent repatch of $originParameter."));
514 }
515 DartType originParameterType = originParameter.computeType(compiler);
516 DartType patchParameterType = patchParameter.computeType(compiler);
517 if (originParameterType != patchParameterType) {
518 compiler.reportError(
519 originParameter.parseNode(compiler),
520 MessageKind.PATCH_PARAMETER_TYPE_MISMATCH,
521 {'methodName': origin.name,
522 'parameterName': originParameter.name,
523 'originParameterType': originParameterType,
524 'patchParameterType': patchParameterType});
525 compiler.reportInfo(patchParameter,
526 MessageKind.PATCH_POINT_TO_PARAMETER,
527 {'parameterName': patchParameter.name});
528 } else {
529 // Hack: Use unparser to test parameter equality. This only works
530 // because we are restricting patch uses and the approach cannot be used
531 // elsewhere.
532
533 // The node contains the type, so there is a potential overlap.
534 // Therefore we only check the text if the types are identical.
535 String originParameterText =
536 originParameter.parseNode(compiler).toString();
537 String patchParameterText =
538 patchParameter.parseNode(compiler).toString();
539 if (originParameterText != patchParameterText
540 // We special case the list constructor because of the
541 // optional parameter.
542 && origin != compiler.unnamedListConstructor) {
543 compiler.reportError(
544 originParameter.parseNode(compiler),
545 MessageKind.PATCH_PARAMETER_MISMATCH,
546 {'methodName': origin.name,
547 'originParameter': originParameterText,
548 'patchParameter': patchParameterText});
549 compiler.reportInfo(patchParameter,
550 MessageKind.PATCH_POINT_TO_PARAMETER,
551 {'parameterName': patchParameter.name});
552 }
553 }
554
555 originParameters = originParameters.tail;
556 patchParameters = patchParameters.tail;
557 }
558 }
559
560 void checkMatchingPatchSignatures(FunctionElement origin,
561 FunctionElement patch) {
562 // TODO(johnniwinther): Show both origin and patch locations on errors.
563 FunctionExpression originTree = origin.node;
564 FunctionSignature originSignature = origin.functionSignature;
565 FunctionExpression patchTree = patch.node;
566 FunctionSignature patchSignature = patch.functionSignature;
567
568 if (originSignature.type.returnType != patchSignature.type.returnType) {
569 compiler.withCurrentElement(patch, () {
570 Node errorNode =
571 patchTree.returnType != null ? patchTree.returnType : patchTree;
572 error(errorNode, MessageKind.PATCH_RETURN_TYPE_MISMATCH,
573 {'methodName': origin.name,
574 'originReturnType': originSignature.type.returnType,
575 'patchReturnType': patchSignature.type.returnType});
576 });
577 }
578 if (originSignature.requiredParameterCount !=
579 patchSignature.requiredParameterCount) {
580 compiler.withCurrentElement(patch, () {
581 error(patchTree,
582 MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH,
583 {'methodName': origin.name,
584 'originParameterCount': originSignature.requiredParameterCount,
585 'patchParameterCount': patchSignature.requiredParameterCount});
586 });
587 } else {
588 checkMatchingPatchParameters(origin,
589 originSignature.requiredParameters,
590 patchSignature.requiredParameters);
591 }
592 if (originSignature.optionalParameterCount != 0 &&
593 patchSignature.optionalParameterCount != 0) {
594 if (originSignature.optionalParametersAreNamed !=
595 patchSignature.optionalParametersAreNamed) {
596 compiler.withCurrentElement(patch, () {
597 error(patchTree,
598 MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH,
599 {'methodName': origin.name});
600 });
601 }
602 }
603 if (originSignature.optionalParameterCount !=
604 patchSignature.optionalParameterCount) {
605 compiler.withCurrentElement(patch, () {
606 error(patchTree,
607 MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH,
608 {'methodName': origin.name,
609 'originParameterCount': originSignature.optionalParameterCount,
610 'patchParameterCount': patchSignature.optionalParameterCount});
611 });
612 } else {
613 checkMatchingPatchParameters(origin,
614 originSignature.optionalParameters,
615 patchSignature.optionalParameters);
616 }
617 }
618
619 static void processAsyncMarker(Compiler compiler, 494 static void processAsyncMarker(Compiler compiler,
620 BaseFunctionElementX element) { 495 BaseFunctionElementX element) {
621 FunctionExpression functionExpression = element.node; 496 FunctionExpression functionExpression = element.node;
622 AsyncModifier asyncModifier = functionExpression.asyncModifier; 497 AsyncModifier asyncModifier = functionExpression.asyncModifier;
623 if (asyncModifier != null) { 498 if (asyncModifier != null) {
624 if (!compiler.enableAsyncAwait) { 499 if (!compiler.enableAsyncAwait) {
625 compiler.reportError(asyncModifier, 500 compiler.reportError(asyncModifier,
626 MessageKind.EXPERIMENTAL_ASYNC_AWAIT, 501 MessageKind.EXPERIMENTAL_ASYNC_AWAIT,
627 {'modifier': element.asyncMarker}); 502 {'modifier': element.asyncMarker});
628 } else if (!compiler.analyzeOnly) { 503 } else if (!compiler.analyzeOnly) {
(...skipping 18 matching lines...) Expand all
647 {'modifier': element.asyncMarker}); 522 {'modifier': element.asyncMarker});
648 } else if (functionExpression.body.asReturn() != null && 523 } else if (functionExpression.body.asReturn() != null &&
649 element.asyncMarker.isYielding) { 524 element.asyncMarker.isYielding) {
650 compiler.reportError(asyncModifier, 525 compiler.reportError(asyncModifier,
651 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, 526 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
652 {'modifier': element.asyncMarker}); 527 {'modifier': element.asyncMarker});
653 } 528 }
654 } 529 }
655 } 530 }
656 531
532 TreeElements resolveMethodElementImplementation(
533 FunctionElement element, FunctionExpression tree) {
534 return compiler.withCurrentElement(element, () {
535 if (element.isExternal && tree.hasBody()) {
536 compiler.reportError(element,
537 MessageKind.EXTERNAL_WITH_BODY,
538 {'functionName': element.name});
539 }
540 if (element.isConstructor) {
541 if (tree.returnType != null) {
542 compiler.reportError(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE);
543 }
544 if (element.isConst &&
545 tree.hasBody() &&
546 !tree.isRedirectingFactory) {
547 compiler.reportError(tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY);
548 }
549 }
550
551 ResolverVisitor visitor = visitorFor(element);
552 ResolutionRegistry registry = visitor.registry;
553 registry.defineFunction(tree, element);
554 visitor.setupFunction(tree, element);
555
556 if (element.isGenerativeConstructor) {
557 // Even if there is no initializer list we still have to do the
558 // resolution in case there is an implicit super constructor call.
559 InitializerResolver resolver = new InitializerResolver(visitor);
560 FunctionElement redirection =
561 resolver.resolveInitializers(element, tree);
562 if (redirection != null) {
563 resolveRedirectingConstructor(resolver, tree, element, redirection);
564 }
565 } else if (tree.initializers != null) {
566 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER);
567 }
568
569 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) {
570 // We need to analyze the redirecting factory bodies to ensure that
571 // we can analyze compile-time constants.
572 visitor.visit(tree.body);
573 }
574
575 // Get the resolution tree and check that the resolved
576 // function doesn't use 'super' if it is mixed into another
577 // class. This is the part of the 'super' mixin check that
578 // happens when a function is resolved after the mixin
579 // application has been performed.
580 TreeElements resolutionTree = registry.mapping;
581 ClassElement enclosingClass = element.enclosingClass;
582 if (enclosingClass != null) {
583 // TODO(johnniwinther): Find another way to obtain mixin uses.
584 Iterable<MixinApplicationElement> mixinUses =
585 compiler.world.allMixinUsesOf(enclosingClass);
586 ClassElement mixin = enclosingClass;
587 for (MixinApplicationElement mixinApplication in mixinUses) {
588 checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
589 }
590 }
591 return resolutionTree;
592 });
593
594 }
595
657 TreeElements resolveMethodElement(FunctionElementX element) { 596 TreeElements resolveMethodElement(FunctionElementX element) {
658 assert(invariant(element, element.isDeclaration)); 597 assert(invariant(element, element.isDeclaration));
659 return compiler.withCurrentElement(element, () { 598 return compiler.withCurrentElement(element, () {
660 bool isConstructor =
661 identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR);
662 if (compiler.enqueuer.resolution.hasBeenResolved(element)) { 599 if (compiler.enqueuer.resolution.hasBeenResolved(element)) {
663 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] 600 // TODO(karlklose): Remove the check for [isConstructor]. [elememts]
664 // should never be non-null, not even for constructors. 601 // should never be non-null, not even for constructors.
665 assert(invariant(element, element.isConstructor, 602 assert(invariant(element, element.isConstructor,
666 message: 'Non-constructor element $element ' 603 message: 'Non-constructor element $element '
667 'has already been analyzed.')); 604 'has already been analyzed.'));
668 return element.resolvedAst.elements; 605 return element.resolvedAst.elements;
669 } 606 }
670 if (element.isSynthesized) { 607 if (element.isSynthesized) {
671 if (isConstructor) { 608 if (element.isGenerativeConstructor) {
672 ResolutionRegistry registry = 609 ResolutionRegistry registry =
673 new ResolutionRegistry(compiler, element); 610 new ResolutionRegistry(compiler, element);
674 ConstructorElement constructor = element.asFunctionElement(); 611 ConstructorElement constructor = element.asFunctionElement();
675 ConstructorElement target = constructor.definingConstructor; 612 ConstructorElement target = constructor.definingConstructor;
676 // Ensure the signature of the synthesized element is 613 // Ensure the signature of the synthesized element is
677 // resolved. This is the only place where the resolver is 614 // resolved. This is the only place where the resolver is
678 // seeing this element. 615 // seeing this element.
679 element.computeSignature(compiler); 616 element.computeSignature(compiler);
680 if (!target.isErroneous) { 617 if (!target.isErroneous) {
681 registry.registerStaticUse(target); 618 registry.registerStaticUse(target);
682 registry.registerImplicitSuperCall(target); 619 registry.registerImplicitSuperCall(target);
683 } 620 }
684 return registry.mapping; 621 return registry.mapping;
685 } else { 622 } else {
686 assert(element.isDeferredLoaderGetter); 623 assert(element.isDeferredLoaderGetter);
687 return _ensureTreeElements(element); 624 return _ensureTreeElements(element);
688 } 625 }
626 } else {
627 element.parseNode(compiler);
628 element.computeType(compiler);
629 processAsyncMarker(compiler, element);
630 FunctionElementX implementation = element;
631 if (element.isExternal) {
632 implementation = compiler.backend.resolveExternalFunction(element);
633 }
634 return resolveMethodElementImplementation(
635 implementation, implementation.node);
689 } 636 }
690 element.parseNode(compiler);
691 element.computeType(compiler);
692 processAsyncMarker(compiler, element);
693 if (element.isPatched) {
694 FunctionElementX patch = element.patch;
695 compiler.withCurrentElement(patch, () {
696 patch.parseNode(compiler);
697 patch.computeType(compiler);
698 });
699 checkMatchingPatchSignatures(element, patch);
700 element = patch;
701 processAsyncMarker(compiler, element);
702 }
703 return compiler.withCurrentElement(element, () {
704 FunctionExpression tree = element.node;
705 if (tree.modifiers.isExternal) {
706 error(tree, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION);
707 return null;
708 }
709 if (isConstructor || element.isFactoryConstructor) {
710 if (tree.returnType != null) {
711 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE);
712 }
713 if (element.modifiers.isConst &&
714 tree.hasBody() &&
715 !tree.isRedirectingFactory) {
716 compiler.reportError(tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY);
717 }
718 }
719
720 ResolverVisitor visitor = visitorFor(element);
721 ResolutionRegistry registry = visitor.registry;
722 registry.defineFunction(tree, element);
723 visitor.setupFunction(tree, element);
724
725 if (isConstructor && !element.isForwardingConstructor) {
726 // Even if there is no initializer list we still have to do the
727 // resolution in case there is an implicit super constructor call.
728 InitializerResolver resolver = new InitializerResolver(visitor);
729 FunctionElement redirection =
730 resolver.resolveInitializers(element, tree);
731 if (redirection != null) {
732 resolveRedirectingConstructor(resolver, tree, element, redirection);
733 }
734 } else if (element.isForwardingConstructor) {
735 // Initializers will be checked on the original constructor.
736 } else if (tree.initializers != null) {
737 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER);
738 }
739
740 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) {
741 // We need to analyze the redirecting factory bodies to ensure that
742 // we can analyze compile-time constants.
743 visitor.visit(tree.body);
744 }
745
746 // Get the resolution tree and check that the resolved
747 // function doesn't use 'super' if it is mixed into another
748 // class. This is the part of the 'super' mixin check that
749 // happens when a function is resolved after the mixin
750 // application has been performed.
751 TreeElements resolutionTree = registry.mapping;
752 ClassElement enclosingClass = element.enclosingClass;
753 if (enclosingClass != null) {
754 // TODO(johnniwinther): Find another way to obtain mixin uses.
755 Iterable<MixinApplicationElement> mixinUses =
756 compiler.world.allMixinUsesOf(enclosingClass);
757 ClassElement mixin = enclosingClass;
758 for (MixinApplicationElement mixinApplication in mixinUses) {
759 checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
760 }
761 }
762 return resolutionTree;
763 });
764 }); 637 });
765 } 638 }
766 639
767 /// Creates a [ResolverVisitor] for resolving an AST in context of [element]. 640 /// Creates a [ResolverVisitor] for resolving an AST in context of [element].
768 /// If [useEnclosingScope] is `true` then the initial scope of the visitor 641 /// If [useEnclosingScope] is `true` then the initial scope of the visitor
769 /// does not include inner scope of [element]. 642 /// does not include inner scope of [element].
770 /// 643 ///
771 /// This method should only be used by this library (or tests of 644 /// This method should only be used by this library (or tests of
772 /// this library). 645 /// this library).
773 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { 646 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) {
(...skipping 4327 matching lines...) Expand 10 before | Expand all | Expand 10 after
5101 } 4974 }
5102 4975
5103 /// The result for the resolution of the `assert` method. 4976 /// The result for the resolution of the `assert` method.
5104 class AssertResult implements ResolutionResult { 4977 class AssertResult implements ResolutionResult {
5105 const AssertResult(); 4978 const AssertResult();
5106 4979
5107 Element get element => null; 4980 Element get element => null;
5108 4981
5109 String toString() => 'AssertResult()'; 4982 String toString() => 'AssertResult()';
5110 } 4983 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/patch_resolver.dart ('k') | pkg/compiler/lib/src/warnings.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698