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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 abstract class TreeElements { | 7 abstract class TreeElements { |
| 8 Element get currentElement; | 8 Element get currentElement; |
| 9 Set<Node> get superUses; | 9 Set<Node> get superUses; |
| 10 | 10 |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 Element originParameter = originParameters.head; | 220 Element originParameter = originParameters.head; |
| 221 Element patchParameter = patchParameters.head; | 221 Element patchParameter = patchParameters.head; |
| 222 // Hack: Use unparser to test parameter equality. This only works because | 222 // Hack: Use unparser to test parameter equality. This only works because |
| 223 // we are restricting patch uses and the approach cannot be used | 223 // we are restricting patch uses and the approach cannot be used |
| 224 // elsewhere. | 224 // elsewhere. |
| 225 String originParameterText = | 225 String originParameterText = |
| 226 originParameter.parseNode(compiler).toString(); | 226 originParameter.parseNode(compiler).toString(); |
| 227 String patchParameterText = | 227 String patchParameterText = |
| 228 patchParameter.parseNode(compiler).toString(); | 228 patchParameter.parseNode(compiler).toString(); |
| 229 if (originParameterText != patchParameterText) { | 229 if (originParameterText != patchParameterText) { |
| 230 compiler.reportErrorCode( | 230 compiler.reportError( |
| 231 originParameter.parseNode(compiler), | 231 originParameter.parseNode(compiler), |
| 232 MessageKind.PATCH_PARAMETER_MISMATCH, | 232 MessageKind.PATCH_PARAMETER_MISMATCH, |
| 233 {'methodName': origin.name, | 233 {'methodName': origin.name, |
| 234 'originParameter': originParameterText, | 234 'originParameter': originParameterText, |
| 235 'patchParameter': patchParameterText}); | 235 'patchParameter': patchParameterText}); |
| 236 compiler.reportMessage( | 236 compiler.reportMessage( |
| 237 compiler.spanFromSpannable(patchParameter), | 237 compiler.spanFromSpannable(patchParameter), |
| 238 MessageKind.PATCH_POINT_TO_PARAMETER.error( | 238 MessageKind.PATCH_POINT_TO_PARAMETER.error( |
| 239 {'parameterName': patchParameter.name}), | 239 {'parameterName': patchParameter.name}), |
| 240 Diagnostic.INFO); | 240 Diagnostic.INFO); |
| 241 } | 241 } |
| 242 DartType originParameterType = originParameter.computeType(compiler); | 242 DartType originParameterType = originParameter.computeType(compiler); |
| 243 DartType patchParameterType = patchParameter.computeType(compiler); | 243 DartType patchParameterType = patchParameter.computeType(compiler); |
| 244 if (originParameterType != patchParameterType) { | 244 if (originParameterType != patchParameterType) { |
| 245 compiler.reportErrorCode( | 245 compiler.reportError( |
| 246 originParameter.parseNode(compiler), | 246 originParameter.parseNode(compiler), |
| 247 MessageKind.PATCH_PARAMETER_TYPE_MISMATCH, | 247 MessageKind.PATCH_PARAMETER_TYPE_MISMATCH, |
| 248 {'methodName': origin.name, | 248 {'methodName': origin.name, |
| 249 'parameterName': originParameter.name, | 249 'parameterName': originParameter.name, |
| 250 'originParameterType': originParameterType, | 250 'originParameterType': originParameterType, |
| 251 'patchParameterType': patchParameterType}); | 251 'patchParameterType': patchParameterType}); |
| 252 compiler.reportMessage( | 252 compiler.reportMessage( |
| 253 compiler.spanFromSpannable(patchParameter), | 253 compiler.spanFromSpannable(patchParameter), |
| 254 MessageKind.PATCH_POINT_TO_PARAMETER.error( | 254 MessageKind.PATCH_POINT_TO_PARAMETER.error( |
| 255 {'parameterName': patchParameter.name}), | 255 {'parameterName': patchParameter.name}), |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 475 /** | 475 /** |
| 476 * Load and resolve the supertypes of [cls]. | 476 * Load and resolve the supertypes of [cls]. |
| 477 * | 477 * |
| 478 * Warning: do not call this method directly. It should only be | 478 * Warning: do not call this method directly. It should only be |
| 479 * called by [resolveClass] and [ClassSupertypeResolver]. | 479 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 480 */ | 480 */ |
| 481 void loadSupertypes(ClassElement cls, Spannable from) { | 481 void loadSupertypes(ClassElement cls, Spannable from) { |
| 482 compiler.withCurrentElement(cls, () => measure(() { | 482 compiler.withCurrentElement(cls, () => measure(() { |
| 483 if (cls.supertypeLoadState == STATE_DONE) return; | 483 if (cls.supertypeLoadState == STATE_DONE) return; |
| 484 if (cls.supertypeLoadState == STATE_STARTED) { | 484 if (cls.supertypeLoadState == STATE_STARTED) { |
| 485 compiler.reportErrorCode(from, MessageKind.CYCLIC_CLASS_HIERARCHY, | 485 compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 486 {'className': cls.name}); | 486 {'className': cls.name}); |
| 487 cls.supertypeLoadState = STATE_DONE; | 487 cls.supertypeLoadState = STATE_DONE; |
| 488 cls.allSupertypes = const Link<DartType>().prepend( | 488 cls.allSupertypes = const Link<DartType>().prepend( |
| 489 compiler.objectClass.computeType(compiler)); | 489 compiler.objectClass.computeType(compiler)); |
| 490 cls.supertype = cls.allSupertypes.head; | 490 cls.supertype = cls.allSupertypes.head; |
| 491 return; | 491 return; |
| 492 } | 492 } |
| 493 cls.supertypeLoadState = STATE_STARTED; | 493 cls.supertypeLoadState = STATE_STARTED; |
| 494 compiler.withCurrentElement(cls, () { | 494 compiler.withCurrentElement(cls, () { |
| 495 // TODO(ahe): Cache the node in cls. | 495 // TODO(ahe): Cache the node in cls. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 586 } else { | 586 } else { |
| 587 checkClassMembers(element); | 587 checkClassMembers(element); |
| 588 } | 588 } |
| 589 } | 589 } |
| 590 | 590 |
| 591 void checkMixinApplication(MixinApplicationElement mixinApplication) { | 591 void checkMixinApplication(MixinApplicationElement mixinApplication) { |
| 592 Modifiers modifiers = mixinApplication.modifiers; | 592 Modifiers modifiers = mixinApplication.modifiers; |
| 593 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT; | 593 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT; |
| 594 if (illegalFlags != 0) { | 594 if (illegalFlags != 0) { |
| 595 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags); | 595 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags); |
| 596 compiler.reportErrorCode( | 596 compiler.reportError( |
| 597 modifiers, | 597 modifiers, |
| 598 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS, | 598 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS, |
| 599 {'modifiers': illegalModifiers}); | 599 {'modifiers': illegalModifiers}); |
| 600 } | 600 } |
| 601 | 601 |
| 602 // In case of cyclic mixin applications, the mixin chain will have | 602 // In case of cyclic mixin applications, the mixin chain will have |
| 603 // been cut. If so, we have already reported the error to the | 603 // been cut. If so, we have already reported the error to the |
| 604 // user so we just return from here. | 604 // user so we just return from here. |
| 605 ClassElement mixin = mixinApplication.mixin; | 605 ClassElement mixin = mixinApplication.mixin; |
| 606 if (mixin == null) return; | 606 if (mixin == null) return; |
| 607 | 607 |
| 608 // Check that we're not trying to use Object as a mixin. | 608 // Check that we're not trying to use Object as a mixin. |
| 609 if (mixin.superclass == null) { | 609 if (mixin.superclass == null) { |
| 610 compiler.reportErrorCode(mixinApplication, | 610 compiler.reportError(mixinApplication, |
| 611 MessageKind.ILLEGAL_MIXIN_OBJECT); | 611 MessageKind.ILLEGAL_MIXIN_OBJECT); |
| 612 // Avoid reporting additional errors for the Object class. | 612 // Avoid reporting additional errors for the Object class. |
| 613 return; | 613 return; |
| 614 } | 614 } |
| 615 | 615 |
| 616 // Check that the mixed in class has Object as its superclass. | 616 // Check that the mixed in class has Object as its superclass. |
| 617 if (!mixin.superclass.isObject(compiler)) { | 617 if (!mixin.superclass.isObject(compiler)) { |
| 618 compiler.reportErrorCode(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); | 618 compiler.reportError(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); |
| 619 } | 619 } |
| 620 | 620 |
| 621 // Check that the mixed in class doesn't have any constructors and | 621 // Check that the mixed in class doesn't have any constructors and |
| 622 // make sure we aren't mixing in methods that use 'super'. | 622 // make sure we aren't mixing in methods that use 'super'. |
| 623 mixin.forEachLocalMember((Element member) { | 623 mixin.forEachLocalMember((Element member) { |
| 624 if (member.isGenerativeConstructor() && !member.isSynthesized) { | 624 if (member.isGenerativeConstructor() && !member.isSynthesized) { |
| 625 compiler.reportErrorCode(member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); | 625 compiler.reportError(member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); |
| 626 } else { | 626 } else { |
| 627 // Get the resolution tree and check that the resolved member | 627 // Get the resolution tree and check that the resolved member |
| 628 // doesn't use 'super'. This is the part of the 'super' mixin | 628 // doesn't use 'super'. This is the part of the 'super' mixin |
| 629 // check that happens when a function is resolved before the | 629 // check that happens when a function is resolved before the |
| 630 // mixin application has been performed. | 630 // mixin application has been performed. |
| 631 checkMixinSuperUses( | 631 checkMixinSuperUses( |
| 632 compiler.enqueuer.resolution.resolvedElements[member], | 632 compiler.enqueuer.resolution.resolvedElements[member], |
| 633 mixinApplication, | 633 mixinApplication, |
| 634 mixin); | 634 mixin); |
| 635 } | 635 } |
| 636 }); | 636 }); |
| 637 } | 637 } |
| 638 | 638 |
| 639 void checkMixinSuperUses(TreeElements resolutionTree, | 639 void checkMixinSuperUses(TreeElements resolutionTree, |
| 640 MixinApplicationElement mixinApplication, | 640 MixinApplicationElement mixinApplication, |
| 641 ClassElement mixin) { | 641 ClassElement mixin) { |
| 642 if (resolutionTree == null) return; | 642 if (resolutionTree == null) return; |
| 643 Set<Node> superUses = resolutionTree.superUses; | 643 Set<Node> superUses = resolutionTree.superUses; |
| 644 if (superUses.isEmpty) return; | 644 if (superUses.isEmpty) return; |
| 645 compiler.reportErrorCode(mixinApplication, | 645 compiler.reportError(mixinApplication, |
| 646 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, | 646 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, |
| 647 {'className': mixin.name}); | 647 {'className': mixin.name}); |
|
kustermann
2013/07/27 09:50:29
Indentation.
ahe
2013/07/28 09:05:51
Done.
| |
| 648 // Show the user the problematic uses of 'super' in the mixin. | 648 // Show the user the problematic uses of 'super' in the mixin. |
| 649 for (Node use in superUses) { | 649 for (Node use in superUses) { |
| 650 CompilationError error = MessageKind.ILLEGAL_MIXIN_SUPER_USE.error(); | 650 compiler.reportInfo( |
| 651 compiler.reportMessage(compiler.spanFromNode(use), | 651 use, |
| 652 error, Diagnostic.INFO); | 652 MessageKind.ILLEGAL_MIXIN_SUPER_USE); |
| 653 } | 653 } |
| 654 } | 654 } |
| 655 | 655 |
| 656 void checkClassMembers(ClassElement cls) { | 656 void checkClassMembers(ClassElement cls) { |
| 657 assert(invariant(cls, cls.isDeclaration)); | 657 assert(invariant(cls, cls.isDeclaration)); |
| 658 if (cls.isObject(compiler)) return; | 658 if (cls.isObject(compiler)) return; |
| 659 // TODO(johnniwinther): Should this be done on the implementation element as | 659 // TODO(johnniwinther): Should this be done on the implementation element as |
| 660 // well? | 660 // well? |
| 661 cls.forEachMember((holder, member) { | 661 cls.forEachMember((holder, member) { |
| 662 compiler.withCurrentElement(member, () { | 662 compiler.withCurrentElement(member, () { |
| 663 // Perform various checks as side effect of "computing" the type. | 663 // Perform various checks as side effect of "computing" the type. |
| 664 member.computeType(compiler); | 664 member.computeType(compiler); |
| 665 | 665 |
| 666 // Check modifiers. | 666 // Check modifiers. |
| 667 if (member.isFunction() && member.modifiers.isFinal()) { | 667 if (member.isFunction() && member.modifiers.isFinal()) { |
| 668 compiler.reportErrorCode( | 668 compiler.reportError( |
| 669 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 669 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
| 670 } | 670 } |
| 671 if (member.isConstructor()) { | 671 if (member.isConstructor()) { |
| 672 final mismatchedFlagsBits = | 672 final mismatchedFlagsBits = |
| 673 member.modifiers.flags & | 673 member.modifiers.flags & |
| 674 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 674 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
| 675 if (mismatchedFlagsBits != 0) { | 675 if (mismatchedFlagsBits != 0) { |
| 676 final mismatchedFlags = | 676 final mismatchedFlags = |
| 677 new Modifiers.withFlags(null, mismatchedFlagsBits); | 677 new Modifiers.withFlags(null, mismatchedFlagsBits); |
| 678 compiler.reportErrorCode( | 678 compiler.reportError( |
| 679 member, | 679 member, |
| 680 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, | 680 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, |
| 681 {'modifiers': mismatchedFlags}); | 681 {'modifiers': mismatchedFlags}); |
| 682 } | 682 } |
| 683 } | 683 } |
| 684 checkAbstractField(member); | 684 checkAbstractField(member); |
| 685 checkValidOverride(member, cls.lookupSuperMember(member.name)); | 685 checkValidOverride(member, cls.lookupSuperMember(member.name)); |
| 686 checkUserDefinableOperator(member); | 686 checkUserDefinableOperator(member); |
| 687 }); | 687 }); |
| 688 }); | 688 }); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 706 } | 706 } |
| 707 AbstractFieldElement field = lookupElement; | 707 AbstractFieldElement field = lookupElement; |
| 708 | 708 |
| 709 if (field.getter == null) return; | 709 if (field.getter == null) return; |
| 710 if (field.setter == null) return; | 710 if (field.setter == null) return; |
| 711 int getterFlags = field.getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 711 int getterFlags = field.getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
| 712 int setterFlags = field.setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 712 int setterFlags = field.setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
| 713 if (!identical(getterFlags, setterFlags)) { | 713 if (!identical(getterFlags, setterFlags)) { |
| 714 final mismatchedFlags = | 714 final mismatchedFlags = |
| 715 new Modifiers.withFlags(null, getterFlags ^ setterFlags); | 715 new Modifiers.withFlags(null, getterFlags ^ setterFlags); |
| 716 compiler.reportErrorCode( | 716 compiler.reportError( |
| 717 field.getter, | 717 field.getter, |
| 718 MessageKind.GETTER_MISMATCH, | 718 MessageKind.GETTER_MISMATCH, |
| 719 {'modifiers': mismatchedFlags}); | 719 {'modifiers': mismatchedFlags}); |
| 720 compiler.reportErrorCode( | 720 compiler.reportError( |
| 721 field.setter, | 721 field.setter, |
| 722 MessageKind.SETTER_MISMATCH, | 722 MessageKind.SETTER_MISMATCH, |
| 723 {'modifiers': mismatchedFlags}); | 723 {'modifiers': mismatchedFlags}); |
| 724 } | 724 } |
| 725 } | 725 } |
| 726 | 726 |
| 727 void checkUserDefinableOperator(Element member) { | 727 void checkUserDefinableOperator(Element member) { |
| 728 FunctionElement function = member.asFunctionElement(); | 728 FunctionElement function = member.asFunctionElement(); |
| 729 if (function == null) return; | 729 if (function == null) return; |
| 730 String value = member.name.stringValue; | 730 String value = member.name.stringValue; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 800 // int operator -(a, b) {} | 800 // int operator -(a, b) {} |
| 801 // ^ | 801 // ^ |
| 802 // | 802 // |
| 803 // since the correction might not be to remove 'b' but instead to | 803 // since the correction might not be to remove 'b' but instead to |
| 804 // remove 'a, b'. | 804 // remove 'a, b'. |
| 805 errorNode = node.parameters; | 805 errorNode = node.parameters; |
| 806 } else { | 806 } else { |
| 807 errorNode = node.parameters.nodes.skip(requiredParameterCount).head; | 807 errorNode = node.parameters.nodes.skip(requiredParameterCount).head; |
| 808 } | 808 } |
| 809 } | 809 } |
| 810 compiler.reportErrorCode( | 810 compiler.reportError( |
| 811 errorNode, messageKind, {'operatorName': function.name}); | 811 errorNode, messageKind, {'operatorName': function.name}); |
| 812 } | 812 } |
| 813 if (signature.optionalParameterCount != 0) { | 813 if (signature.optionalParameterCount != 0) { |
| 814 Node errorNode = | 814 Node errorNode = |
| 815 node.parameters.nodes.skip(signature.requiredParameterCount).head; | 815 node.parameters.nodes.skip(signature.requiredParameterCount).head; |
| 816 if (signature.optionalParametersAreNamed) { | 816 if (signature.optionalParametersAreNamed) { |
| 817 compiler.reportErrorCode( | 817 compiler.reportError( |
| 818 errorNode, | 818 errorNode, |
| 819 MessageKind.OPERATOR_NAMED_PARAMETERS, | 819 MessageKind.OPERATOR_NAMED_PARAMETERS, |
| 820 {'operatorName': function.name}); | 820 {'operatorName': function.name}); |
| 821 } else { | 821 } else { |
| 822 compiler.reportErrorCode( | 822 compiler.reportError( |
| 823 errorNode, | 823 errorNode, |
| 824 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, | 824 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, |
| 825 {'operatorName': function.name}); | 825 {'operatorName': function.name}); |
| 826 } | 826 } |
| 827 } | 827 } |
| 828 } | 828 } |
| 829 | 829 |
| 830 reportErrorWithContext(Element errorneousElement, | 830 reportErrorWithContext(Element errorneousElement, |
| 831 MessageKind errorMessage, | 831 MessageKind errorMessage, |
| 832 Element contextElement, | 832 Element contextElement, |
| 833 MessageKind contextMessage) { | 833 MessageKind contextMessage) { |
| 834 compiler.reportErrorCode( | 834 compiler.reportError( |
| 835 errorneousElement, | 835 errorneousElement, |
| 836 errorMessage, | 836 errorMessage, |
| 837 {'memberName': contextElement.name, | 837 {'memberName': contextElement.name, |
| 838 'className': contextElement.getEnclosingClass().name}); | 838 'className': contextElement.getEnclosingClass().name}); |
| 839 compiler.reportMessage( | 839 compiler.reportMessage( |
| 840 compiler.spanFromElement(contextElement), | 840 compiler.spanFromElement(contextElement), |
| 841 contextMessage.error(), | 841 contextMessage.error(), |
| 842 Diagnostic.INFO); | 842 Diagnostic.INFO); |
| 843 } | 843 } |
| 844 | 844 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 ResolverVisitor visitor = visitorFor(context); | 962 ResolverVisitor visitor = visitorFor(context); |
| 963 node.accept(visitor); | 963 node.accept(visitor); |
| 964 annotation.value = compiler.metadataHandler.compileNodeWithDefinitions( | 964 annotation.value = compiler.metadataHandler.compileNodeWithDefinitions( |
| 965 node, visitor.mapping, isConst: true); | 965 node, visitor.mapping, isConst: true); |
| 966 | 966 |
| 967 annotation.resolutionState = STATE_DONE; | 967 annotation.resolutionState = STATE_DONE; |
| 968 })); | 968 })); |
| 969 } | 969 } |
| 970 | 970 |
| 971 error(Node node, MessageKind kind, [arguments = const {}]) { | 971 error(Node node, MessageKind kind, [arguments = const {}]) { |
| 972 ResolutionError message = new ResolutionError(kind, arguments); | 972 // TODO(ahe): Make non-fatal. |
| 973 compiler.reportError(node, message); | 973 compiler.reportFatalError(node, kind, arguments); |
| 974 } | 974 } |
| 975 } | 975 } |
| 976 | 976 |
| 977 class InitializerResolver { | 977 class InitializerResolver { |
| 978 final ResolverVisitor visitor; | 978 final ResolverVisitor visitor; |
| 979 final Map<Element, Node> initialized; | 979 final Map<Element, Node> initialized; |
| 980 Link<Node> initializers; | 980 Link<Node> initializers; |
| 981 bool hasSuper; | 981 bool hasSuper; |
| 982 | 982 |
| 983 InitializerResolver(this.visitor) | 983 InitializerResolver(this.visitor) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 994 bool isFieldInitializer(SendSet node) { | 994 bool isFieldInitializer(SendSet node) { |
| 995 if (node.selector.asIdentifier() == null) return false; | 995 if (node.selector.asIdentifier() == null) return false; |
| 996 if (node.receiver == null) return true; | 996 if (node.receiver == null) return true; |
| 997 if (node.receiver.asIdentifier() == null) return false; | 997 if (node.receiver.asIdentifier() == null) return false; |
| 998 return node.receiver.asIdentifier().isThis(); | 998 return node.receiver.asIdentifier().isThis(); |
| 999 } | 999 } |
| 1000 | 1000 |
| 1001 reportDuplicateInitializerError(Element field, Node init, Node existing) { | 1001 reportDuplicateInitializerError(Element field, Node init, Node existing) { |
| 1002 visitor.compiler.reportError( | 1002 visitor.compiler.reportError( |
| 1003 init, | 1003 init, |
| 1004 new ResolutionError(MessageKind.DUPLICATE_INITIALIZER, | 1004 MessageKind.DUPLICATE_INITIALIZER, {'fieldName': field.name}); |
| 1005 {'fieldName': field.name})); | 1005 visitor.compiler.reportInfo( |
| 1006 visitor.compiler.reportMessage( | 1006 existing, |
| 1007 visitor.compiler.spanFromNode(existing), | 1007 MessageKind.ALREADY_INITIALIZED, {'fieldName': field.name}); |
| 1008 new ResolutionError(MessageKind.ALREADY_INITIALIZED, | |
| 1009 {'fieldName': field.name}), | |
| 1010 Diagnostic.INFO); | |
| 1011 } | 1008 } |
| 1012 | 1009 |
| 1013 void checkForDuplicateInitializers(Element field, Node init) { | 1010 void checkForDuplicateInitializers(Element field, Node init) { |
| 1014 // [field] can be null if it could not be resolved. | 1011 // [field] can be null if it could not be resolved. |
| 1015 if (field == null) return; | 1012 if (field == null) return; |
| 1016 SourceString name = field.name; | 1013 SourceString name = field.name; |
| 1017 if (initialized.containsKey(field)) { | 1014 if (initialized.containsKey(field)) { |
| 1018 reportDuplicateInitializerError(field, init, initialized[field]); | 1015 reportDuplicateInitializerError(field, init, initialized[field]); |
| 1019 } else if (field.modifiers.isFinal()) { | 1016 } else if (field.modifiers.isFinal()) { |
| 1020 Node fieldNode = field.parseNode(visitor.compiler).asSendSet(); | 1017 Node fieldNode = field.parseNode(visitor.compiler).asSendSet(); |
| 1021 if (fieldNode != null) { | 1018 if (fieldNode != null) { |
| 1022 reportDuplicateInitializerError(field, init, fieldNode); | 1019 reportDuplicateInitializerError(field, init, fieldNode); |
| 1023 } | 1020 } |
| 1024 } | 1021 } |
| 1025 initialized[field] = init; | 1022 initialized[field] = init; |
| 1026 } | 1023 } |
| 1027 | 1024 |
| 1028 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { | 1025 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { |
| 1029 // init is of the form [this.]field = value. | 1026 // init is of the form [this.]field = value. |
| 1030 final Node selector = init.selector; | 1027 final Node selector = init.selector; |
| 1031 final SourceString name = selector.asIdentifier().source; | 1028 final SourceString name = selector.asIdentifier().source; |
| 1032 // Lookup target field. | 1029 // Lookup target field. |
| 1033 Element target; | 1030 Element target; |
| 1034 if (isFieldInitializer(init)) { | 1031 if (isFieldInitializer(init)) { |
| 1035 target = constructor.getEnclosingClass().lookupLocalMember(name); | 1032 target = constructor.getEnclosingClass().lookupLocalMember(name); |
| 1036 if (target == null) { | 1033 if (target == null) { |
| 1037 error(selector, MessageKind.CANNOT_RESOLVE, {'name': name}); | 1034 error(selector, MessageKind.CANNOT_RESOLVE.error, {'name': name}); |
| 1038 } else if (target.kind != ElementKind.FIELD) { | 1035 } else if (target.kind != ElementKind.FIELD) { |
| 1039 error(selector, MessageKind.NOT_A_FIELD, {'fieldName': name}); | 1036 error(selector, MessageKind.NOT_A_FIELD, {'fieldName': name}); |
| 1040 } else if (!target.isInstanceMember()) { | 1037 } else if (!target.isInstanceMember()) { |
| 1041 error(selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name}); | 1038 error(selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name}); |
| 1042 } | 1039 } |
| 1043 } else { | 1040 } else { |
| 1044 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); | 1041 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); |
| 1045 } | 1042 } |
| 1046 visitor.useElement(init, target); | 1043 visitor.useElement(init, target); |
| 1047 visitor.world.registerStaticUse(target); | 1044 visitor.world.registerStaticUse(target); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1147 Selector constructorSelector) { | 1144 Selector constructorSelector) { |
| 1148 if (lookedupConstructor == null | 1145 if (lookedupConstructor == null |
| 1149 || !lookedupConstructor.isGenerativeConstructor()) { | 1146 || !lookedupConstructor.isGenerativeConstructor()) { |
| 1150 var fullConstructorName = | 1147 var fullConstructorName = |
| 1151 visitor.compiler.resolver.constructorNameForDiagnostics( | 1148 visitor.compiler.resolver.constructorNameForDiagnostics( |
| 1152 className, | 1149 className, |
| 1153 constructorSelector.name); | 1150 constructorSelector.name); |
| 1154 MessageKind kind = isImplicitSuperCall | 1151 MessageKind kind = isImplicitSuperCall |
| 1155 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT | 1152 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT |
| 1156 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; | 1153 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; |
| 1157 visitor.compiler.reportErrorCode( | 1154 visitor.compiler.reportError( |
| 1158 diagnosticNode, kind, {'constructorName': fullConstructorName}); | 1155 diagnosticNode, kind, {'constructorName': fullConstructorName}); |
| 1159 } else { | 1156 } else { |
| 1160 if (!call.applies(lookedupConstructor, visitor.compiler)) { | 1157 if (!call.applies(lookedupConstructor, visitor.compiler)) { |
| 1161 MessageKind kind = isImplicitSuperCall | 1158 MessageKind kind = isImplicitSuperCall |
| 1162 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT | 1159 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT |
| 1163 : MessageKind.NO_MATCHING_CONSTRUCTOR; | 1160 : MessageKind.NO_MATCHING_CONSTRUCTOR; |
| 1164 visitor.compiler.reportErrorCode(diagnosticNode, kind); | 1161 visitor.compiler.reportError(diagnosticNode, kind); |
| 1165 } else if (caller.modifiers.isConst() | 1162 } else if (caller.modifiers.isConst() |
| 1166 && !lookedupConstructor.modifiers.isConst()) { | 1163 && !lookedupConstructor.modifiers.isConst()) { |
| 1167 visitor.compiler.reportErrorCode( | 1164 visitor.compiler.reportError( |
| 1168 diagnosticNode, MessageKind.CONST_CALLS_NON_CONST); | 1165 diagnosticNode, MessageKind.CONST_CALLS_NON_CONST); |
| 1169 } | 1166 } |
| 1170 } | 1167 } |
| 1171 } | 1168 } |
| 1172 | 1169 |
| 1173 FunctionElement resolveRedirection(FunctionElement constructor, | 1170 FunctionElement resolveRedirection(FunctionElement constructor, |
| 1174 FunctionExpression functionNode) { | 1171 FunctionExpression functionNode) { |
| 1175 if (functionNode.initializers == null) return null; | 1172 if (functionNode.initializers == null) return null; |
| 1176 Link<Node> link = functionNode.initializers.nodes; | 1173 Link<Node> link = functionNode.initializers.nodes; |
| 1177 if (!link.isEmpty && Initializers.isConstructorRedirect(link.head)) { | 1174 if (!link.isEmpty && Initializers.isConstructorRedirect(link.head)) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1262 cancel(node, | 1259 cancel(node, |
| 1263 'internal error: Unhandled node: ${node.getObjectDescription()}'); | 1260 'internal error: Unhandled node: ${node.getObjectDescription()}'); |
| 1264 } | 1261 } |
| 1265 | 1262 |
| 1266 R visitEmptyStatement(Node node) => null; | 1263 R visitEmptyStatement(Node node) => null; |
| 1267 | 1264 |
| 1268 /** Convenience method for visiting nodes that may be null. */ | 1265 /** Convenience method for visiting nodes that may be null. */ |
| 1269 R visit(Node node) => (node == null) ? null : node.accept(this); | 1266 R visit(Node node) => (node == null) ? null : node.accept(this); |
| 1270 | 1267 |
| 1271 void error(Node node, MessageKind kind, [Map arguments = const {}]) { | 1268 void error(Node node, MessageKind kind, [Map arguments = const {}]) { |
| 1272 ResolutionError message = new ResolutionError(kind, arguments); | 1269 compiler.reportFatalError(node, kind, arguments); |
| 1273 compiler.reportError(node, message); | 1270 } |
| 1271 | |
| 1272 void dualError(Node node, DualKind kind, [Map arguments = const {}]) { | |
| 1273 error(node, kind.error, arguments); | |
| 1274 } | 1274 } |
| 1275 | 1275 |
| 1276 void warning(Node node, MessageKind kind, [Map arguments = const {}]) { | 1276 void warning(Node node, MessageKind kind, [Map arguments = const {}]) { |
| 1277 ResolutionWarning message = new ResolutionWarning(kind, arguments); | 1277 ResolutionWarning message = new ResolutionWarning(kind, arguments); |
| 1278 compiler.reportWarning(node, message); | 1278 compiler.reportWarning(node, message); |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 void dualWarning(Node node, DualKind kind, [Map arguments = const {}]) { | |
| 1282 warning(node, kind.warning, arguments); | |
| 1283 } | |
| 1284 | |
| 1281 void cancel(Node node, String message) { | 1285 void cancel(Node node, String message) { |
| 1282 compiler.cancel(message, node: node); | 1286 compiler.cancel(message, node: node); |
| 1283 } | 1287 } |
| 1284 | 1288 |
| 1285 void internalError(Node node, String message) { | 1289 void internalError(Node node, String message) { |
| 1286 compiler.internalError(message, node: node); | 1290 compiler.internalError(message, node: node); |
| 1287 } | 1291 } |
| 1288 | 1292 |
| 1289 void unimplemented(Node node, String message) { | 1293 void unimplemented(Node node, String message) { |
| 1290 compiler.unimplemented(message, node: node); | 1294 compiler.unimplemented(message, node: node); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1421 return scope.lookup(typeName.source); | 1425 return scope.lookup(typeName.source); |
| 1422 } | 1426 } |
| 1423 } | 1427 } |
| 1424 } | 1428 } |
| 1425 | 1429 |
| 1426 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean | 1430 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean |
| 1427 // flags instead of closures. | 1431 // flags instead of closures. |
| 1428 DartType resolveTypeAnnotation( | 1432 DartType resolveTypeAnnotation( |
| 1429 MappingVisitor visitor, | 1433 MappingVisitor visitor, |
| 1430 TypeAnnotation node, | 1434 TypeAnnotation node, |
| 1431 {onFailure(Node node, MessageKind kind, [Map arguments])}) { | 1435 {onFailure(Node node, DualKind kind, [Map arguments])}) { |
| 1432 if (onFailure == null) { | 1436 if (onFailure == null) { |
| 1433 onFailure = (n, k, [arguments]) {}; | 1437 onFailure = (n, k, [arguments]) {}; |
| 1434 } | 1438 } |
| 1435 return resolveTypeAnnotationInContext(visitor, node, onFailure); | 1439 return resolveTypeAnnotationInContext(visitor, node, onFailure); |
| 1436 } | 1440 } |
| 1437 | 1441 |
| 1438 DartType resolveTypeAnnotationInContext(MappingVisitor visitor, | 1442 DartType resolveTypeAnnotationInContext( |
| 1439 TypeAnnotation node, | 1443 MappingVisitor visitor, |
| 1440 onFailure) { | 1444 TypeAnnotation node, |
| 1445 onFailure(Node node, DualKind kind, [Map arguments])) { | |
| 1441 Identifier typeName; | 1446 Identifier typeName; |
| 1442 SourceString prefixName; | 1447 SourceString prefixName; |
| 1443 Send send = node.typeName.asSend(); | 1448 Send send = node.typeName.asSend(); |
| 1444 if (send != null) { | 1449 if (send != null) { |
| 1445 // The type name is of the form [: prefix . identifier :]. | 1450 // The type name is of the form [: prefix . identifier :]. |
| 1446 prefixName = send.receiver.asIdentifier().source; | 1451 prefixName = send.receiver.asIdentifier().source; |
| 1447 typeName = send.selector.asIdentifier(); | 1452 typeName = send.selector.asIdentifier(); |
| 1448 } else { | 1453 } else { |
| 1449 typeName = node.typeName.asIdentifier(); | 1454 typeName = node.typeName.asIdentifier(); |
| 1450 } | 1455 } |
| 1451 | 1456 |
| 1452 Element element = resolveTypeName(visitor.scope, prefixName, typeName); | 1457 Element element = resolveTypeName(visitor.scope, prefixName, typeName); |
| 1453 DartType type; | 1458 DartType type; |
| 1454 | 1459 |
| 1455 DartType reportFailureAndCreateType(MessageKind messageKind, | 1460 DartType reportFailureAndCreateType(DualKind messageKind, |
| 1456 Map messageArguments) { | 1461 Map messageArguments) { |
| 1457 onFailure(node, messageKind, messageArguments); | 1462 onFailure(node, messageKind, messageArguments); |
| 1458 var erroneousElement = new ErroneousElementX( | 1463 var erroneousElement = new ErroneousElementX( |
| 1459 messageKind, messageArguments, typeName.source, | 1464 messageKind.error, messageArguments, typeName.source, |
| 1460 visitor.enclosingElement); | 1465 visitor.enclosingElement); |
| 1461 var arguments = new LinkBuilder<DartType>(); | 1466 var arguments = new LinkBuilder<DartType>(); |
| 1462 resolveTypeArguments( | 1467 resolveTypeArguments( |
| 1463 visitor, node, null, | 1468 visitor, node, null, |
| 1464 onFailure, arguments); | 1469 onFailure, arguments); |
| 1465 return new MalformedType(erroneousElement, null, arguments.toLink()); | 1470 return new MalformedType(erroneousElement, null, arguments.toLink()); |
| 1466 } | 1471 } |
| 1467 | 1472 |
| 1468 DartType checkNoTypeArguments(DartType type) { | 1473 DartType checkNoTypeArguments(DartType type) { |
| 1469 var arguments = new LinkBuilder<DartType>(); | 1474 var arguments = new LinkBuilder<DartType>(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1538 } else if (element.isTypeVariable()) { | 1543 } else if (element.isTypeVariable()) { |
| 1539 Element outer = | 1544 Element outer = |
| 1540 visitor.enclosingElement.getOutermostEnclosingMemberOrTopLevel(); | 1545 visitor.enclosingElement.getOutermostEnclosingMemberOrTopLevel(); |
| 1541 bool isInFactoryConstructor = | 1546 bool isInFactoryConstructor = |
| 1542 outer != null && outer.isFactoryConstructor(); | 1547 outer != null && outer.isFactoryConstructor(); |
| 1543 if (!outer.isClass() && | 1548 if (!outer.isClass() && |
| 1544 !outer.isTypedef() && | 1549 !outer.isTypedef() && |
| 1545 !isInFactoryConstructor && | 1550 !isInFactoryConstructor && |
| 1546 Elements.isInStaticContext(visitor.enclosingElement)) { | 1551 Elements.isInStaticContext(visitor.enclosingElement)) { |
| 1547 compiler.backend.registerThrowRuntimeError(visitor.mapping); | 1552 compiler.backend.registerThrowRuntimeError(visitor.mapping); |
| 1548 compiler.reportWarning(node, | 1553 compiler.reportWarningCode( |
| 1549 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( | 1554 node, |
| 1550 {'typeVariableName': node})); | 1555 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.warning, |
| 1556 {'typeVariableName': node}); | |
| 1551 type = new MalformedType( | 1557 type = new MalformedType( |
| 1552 new ErroneousElementX( | 1558 new ErroneousElementX( |
| 1553 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | 1559 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.error, |
| 1554 {'typeVariableName': node}, | 1560 {'typeVariableName': node}, |
| 1555 typeName.source, visitor.enclosingElement), | 1561 typeName.source, visitor.enclosingElement), |
| 1556 element.computeType(compiler)); | 1562 element.computeType(compiler)); |
| 1557 } else { | 1563 } else { |
| 1558 type = element.computeType(compiler); | 1564 type = element.computeType(compiler); |
| 1559 } | 1565 } |
| 1560 type = checkNoTypeArguments(type); | 1566 type = checkNoTypeArguments(type); |
| 1561 } else { | 1567 } else { |
| 1562 compiler.cancel("unexpected element kind ${element.kind}", | 1568 compiler.cancel("unexpected element kind ${element.kind}", |
| 1563 node: node); | 1569 node: node); |
| 1564 } | 1570 } |
| 1565 } | 1571 } |
| 1566 visitor.useType(node, type); | 1572 visitor.useType(node, type); |
| 1567 return type; | 1573 return type; |
| 1568 } | 1574 } |
| 1569 | 1575 |
| 1570 /** | 1576 /** |
| 1571 * Resolves the type arguments of [node] and adds these to [arguments]. | 1577 * Resolves the type arguments of [node] and adds these to [arguments]. |
| 1572 * | 1578 * |
| 1573 * Returns [: true :] if the number of type arguments did not match the | 1579 * Returns [: true :] if the number of type arguments did not match the |
| 1574 * number of type variables. | 1580 * number of type variables. |
| 1575 */ | 1581 */ |
| 1576 bool resolveTypeArguments( | 1582 bool resolveTypeArguments( |
| 1577 MappingVisitor visitor, | 1583 MappingVisitor visitor, |
| 1578 TypeAnnotation node, | 1584 TypeAnnotation node, |
| 1579 Link<DartType> typeVariables, | 1585 Link<DartType> typeVariables, |
| 1580 onFailure, | 1586 onFailure(Node node, DualKind kind, [Map arguments]), |
| 1581 LinkBuilder<DartType> arguments) { | 1587 LinkBuilder<DartType> arguments) { |
| 1582 if (node.typeArguments == null) { | 1588 if (node.typeArguments == null) { |
| 1583 return false; | 1589 return false; |
| 1584 } | 1590 } |
| 1585 bool typeArgumentCountMismatch = false; | 1591 bool typeArgumentCountMismatch = false; |
| 1586 for (Link<Node> typeArguments = node.typeArguments.nodes; | 1592 for (Link<Node> typeArguments = node.typeArguments.nodes; |
| 1587 !typeArguments.isEmpty; | 1593 !typeArguments.isEmpty; |
| 1588 typeArguments = typeArguments.tail) { | 1594 typeArguments = typeArguments.tail) { |
| 1589 if (typeVariables != null && typeVariables.isEmpty) { | 1595 if (typeVariables != null && typeVariables.isEmpty) { |
| 1590 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 1596 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1707 !element.enclosingElement.isTypedef()), | 1713 !element.enclosingElement.isTypedef()), |
| 1708 inCatchBlock = false, | 1714 inCatchBlock = false, |
| 1709 super(compiler, mapping); | 1715 super(compiler, mapping); |
| 1710 | 1716 |
| 1711 ResolutionEnqueuer get world => compiler.enqueuer.resolution; | 1717 ResolutionEnqueuer get world => compiler.enqueuer.resolution; |
| 1712 | 1718 |
| 1713 Element lookup(Node node, SourceString name) { | 1719 Element lookup(Node node, SourceString name) { |
| 1714 Element result = scope.lookup(name); | 1720 Element result = scope.lookup(name); |
| 1715 if (!Elements.isUnresolved(result)) { | 1721 if (!Elements.isUnresolved(result)) { |
| 1716 if (!inInstanceContext && result.isInstanceMember()) { | 1722 if (!inInstanceContext && result.isInstanceMember()) { |
| 1717 compiler.reportErrorCode( | 1723 compiler.reportError( |
| 1718 node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name}); | 1724 node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name}); |
| 1719 return new ErroneousElementX(MessageKind.NO_INSTANCE_AVAILABLE, | 1725 return new ErroneousElementX(MessageKind.NO_INSTANCE_AVAILABLE, |
| 1720 {'name': name}, | 1726 {'name': name}, |
| 1721 name, enclosingElement); | 1727 name, enclosingElement); |
| 1722 } else if (result.isAmbiguous()) { | 1728 } else if (result.isAmbiguous()) { |
| 1723 AmbiguousElement ambiguous = result; | 1729 AmbiguousElement ambiguous = result; |
| 1724 compiler.reportErrorCode( | 1730 compiler.reportError( |
| 1725 node, ambiguous.messageKind, ambiguous.messageArguments); | 1731 node, ambiguous.messageKind.error, ambiguous.messageArguments); |
| 1726 ambiguous.diagnose(enclosingElement, compiler); | 1732 ambiguous.diagnose(enclosingElement, compiler); |
| 1727 return new ErroneousElementX(ambiguous.messageKind, | 1733 return new ErroneousElementX(ambiguous.messageKind.error, |
| 1728 ambiguous.messageArguments, | 1734 ambiguous.messageArguments, |
| 1729 name, enclosingElement); | 1735 name, enclosingElement); |
| 1730 } | 1736 } |
| 1731 } | 1737 } |
| 1732 return result; | 1738 return result; |
| 1733 } | 1739 } |
| 1734 | 1740 |
| 1735 // Create, or reuse an already created, statement element for a statement. | 1741 // Create, or reuse an already created, statement element for a statement. |
| 1736 TargetElement getOrCreateTargetElement(Node statement) { | 1742 TargetElement getOrCreateTargetElement(Node statement) { |
| 1737 TargetElement element = mapping[statement]; | 1743 TargetElement element = mapping[statement]; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1759 inInstanceContext = wasInstanceContext; | 1765 inInstanceContext = wasInstanceContext; |
| 1760 return result; | 1766 return result; |
| 1761 } | 1767 } |
| 1762 | 1768 |
| 1763 visitInStaticContext(Node node) { | 1769 visitInStaticContext(Node node) { |
| 1764 inStaticContext(() => visit(node)); | 1770 inStaticContext(() => visit(node)); |
| 1765 } | 1771 } |
| 1766 | 1772 |
| 1767 ErroneousElement warnAndCreateErroneousElement(Node node, | 1773 ErroneousElement warnAndCreateErroneousElement(Node node, |
| 1768 SourceString name, | 1774 SourceString name, |
| 1769 MessageKind kind, | 1775 DualKind kind, |
| 1770 [Map arguments = const {}]) { | 1776 [Map arguments = const {}]) { |
| 1771 ResolutionWarning warning = new ResolutionWarning(kind, arguments); | 1777 ResolutionWarning warning = new ResolutionWarning(kind.warning, arguments); |
| 1772 compiler.reportWarning(node, warning); | 1778 compiler.reportWarning(node, warning); |
| 1773 return new ErroneousElementX(kind, arguments, name, enclosingElement); | 1779 return new ErroneousElementX(kind.error, arguments, name, enclosingElement); |
| 1774 } | 1780 } |
| 1775 | 1781 |
| 1776 Element visitIdentifier(Identifier node) { | 1782 Element visitIdentifier(Identifier node) { |
| 1777 if (node.isThis()) { | 1783 if (node.isThis()) { |
| 1778 if (!inInstanceContext) { | 1784 if (!inInstanceContext) { |
| 1779 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); | 1785 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); |
| 1780 } | 1786 } |
| 1781 return null; | 1787 return null; |
| 1782 } else if (node.isSuper()) { | 1788 } else if (node.isSuper()) { |
| 1783 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); | 1789 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC); |
| 1784 if ((ElementCategory.SUPER & allowedCategory) == 0) { | 1790 if ((ElementCategory.SUPER & allowedCategory) == 0) { |
| 1785 error(node, MessageKind.INVALID_USE_OF_SUPER); | 1791 error(node, MessageKind.INVALID_USE_OF_SUPER); |
| 1786 } | 1792 } |
| 1787 return null; | 1793 return null; |
| 1788 } else { | 1794 } else { |
| 1789 Element element = lookup(node, node.source); | 1795 Element element = lookup(node, node.source); |
| 1790 if (element == null) { | 1796 if (element == null) { |
| 1791 if (!inInstanceContext) { | 1797 if (!inInstanceContext) { |
| 1792 element = warnAndCreateErroneousElement(node, node.source, | 1798 element = warnAndCreateErroneousElement( |
| 1793 MessageKind.CANNOT_RESOLVE, | 1799 node, node.source, MessageKind.CANNOT_RESOLVE, |
| 1794 {'name': node}); | 1800 {'name': node}); |
| 1795 compiler.backend.registerThrowNoSuchMethod(mapping); | 1801 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 1796 } | 1802 } |
| 1797 } else if (element.isErroneous()) { | 1803 } else if (element.isErroneous()) { |
| 1798 // Use the erroneous element. | 1804 // Use the erroneous element. |
| 1799 } else { | 1805 } else { |
| 1800 if ((element.kind.category & allowedCategory) == 0) { | 1806 if ((element.kind.category & allowedCategory) == 0) { |
| 1801 // TODO(ahe): Improve error message. Need UX input. | 1807 // TODO(ahe): Improve error message. Need UX input. |
| 1802 error(node, MessageKind.GENERIC, | 1808 error(node, MessageKind.GENERIC, |
| 1803 {'text': "is not an expression $element"}); | 1809 {'text': "is not an expression $element"}); |
| 1804 } | 1810 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1822 return null; | 1828 return null; |
| 1823 } | 1829 } |
| 1824 | 1830 |
| 1825 Element defineElement(Node node, Element element, | 1831 Element defineElement(Node node, Element element, |
| 1826 {bool doAddToScope: true}) { | 1832 {bool doAddToScope: true}) { |
| 1827 compiler.ensure(element != null); | 1833 compiler.ensure(element != null); |
| 1828 mapping[node] = element; | 1834 mapping[node] = element; |
| 1829 if (doAddToScope) { | 1835 if (doAddToScope) { |
| 1830 Element existing = scope.add(element); | 1836 Element existing = scope.add(element); |
| 1831 if (existing != element) { | 1837 if (existing != element) { |
| 1832 compiler.reportErrorCode( | 1838 compiler.reportError( |
| 1833 node, MessageKind.DUPLICATE_DEFINITION, {'name': node}); | 1839 node, MessageKind.DUPLICATE_DEFINITION, {'name': node}); |
| 1834 compiler.reportMessage( | 1840 compiler.reportMessage( |
| 1835 compiler.spanFromSpannable(existing), | 1841 compiler.spanFromSpannable(existing), |
| 1836 MessageKind.EXISTING_DEFINITION.error({'name': node}), | 1842 MessageKind.EXISTING_DEFINITION.error({'name': node}), |
| 1837 Diagnostic.INFO); | 1843 Diagnostic.INFO); |
| 1838 } | 1844 } |
| 1839 } | 1845 } |
| 1840 return element; | 1846 return element; |
| 1841 } | 1847 } |
| 1842 | 1848 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1868 final ClassElement classElement = constructor.getEnclosingClass(); | 1874 final ClassElement classElement = constructor.getEnclosingClass(); |
| 1869 return classElement.lookupConstructor(selector); | 1875 return classElement.lookupConstructor(selector); |
| 1870 } | 1876 } |
| 1871 return null; | 1877 return null; |
| 1872 } | 1878 } |
| 1873 | 1879 |
| 1874 void setupFunction(FunctionExpression node, FunctionElement function) { | 1880 void setupFunction(FunctionExpression node, FunctionElement function) { |
| 1875 Element enclosingElement = function.enclosingElement; | 1881 Element enclosingElement = function.enclosingElement; |
| 1876 if (node.modifiers.isStatic() && | 1882 if (node.modifiers.isStatic() && |
| 1877 enclosingElement.kind != ElementKind.CLASS) { | 1883 enclosingElement.kind != ElementKind.CLASS) { |
| 1878 compiler.reportErrorCode(node, MessageKind.ILLEGAL_STATIC); | 1884 compiler.reportError(node, MessageKind.ILLEGAL_STATIC); |
| 1879 } | 1885 } |
| 1880 | 1886 |
| 1881 scope = new MethodScope(scope, function); | 1887 scope = new MethodScope(scope, function); |
| 1882 // Put the parameters in scope. | 1888 // Put the parameters in scope. |
| 1883 FunctionSignature functionParameters = | 1889 FunctionSignature functionParameters = |
| 1884 function.computeSignature(compiler); | 1890 function.computeSignature(compiler); |
| 1885 Link<Node> parameterNodes = (node.parameters == null) | 1891 Link<Node> parameterNodes = (node.parameters == null) |
| 1886 ? const Link<Node>() : node.parameters.nodes; | 1892 ? const Link<Node>() : node.parameters.nodes; |
| 1887 functionParameters.forEachParameter((Element element) { | 1893 functionParameters.forEachParameter((Element element) { |
| 1888 if (element == functionParameters.optionalParameters.head) { | 1894 if (element == functionParameters.optionalParameters.head) { |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2103 target = receiverClass.lookupLocalMember(name); | 2109 target = receiverClass.lookupLocalMember(name); |
| 2104 if (target == null || target.isInstanceMember()) { | 2110 if (target == null || target.isInstanceMember()) { |
| 2105 compiler.backend.registerThrowNoSuchMethod(mapping); | 2111 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2106 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | 2112 // TODO(johnniwinther): With the simplified [TreeElements] invariant, |
| 2107 // try to resolve injected elements if [currentClass] is in the patch | 2113 // try to resolve injected elements if [currentClass] is in the patch |
| 2108 // library of [receiverClass]. | 2114 // library of [receiverClass]. |
| 2109 | 2115 |
| 2110 // TODO(karlklose): this should be reported by the caller of | 2116 // TODO(karlklose): this should be reported by the caller of |
| 2111 // [resolveSend] to select better warning messages for getters and | 2117 // [resolveSend] to select better warning messages for getters and |
| 2112 // setters. | 2118 // setters. |
| 2113 MessageKind kind = (target == null) | 2119 DualKind kind = (target == null) |
| 2114 ? MessageKind.MEMBER_NOT_FOUND | 2120 ? MessageKind.MEMBER_NOT_FOUND |
| 2115 : MessageKind.MEMBER_NOT_STATIC; | 2121 : MessageKind.MEMBER_NOT_STATIC; |
| 2116 return warnAndCreateErroneousElement(node, name, kind, | 2122 return warnAndCreateErroneousElement(node, name, kind, |
| 2117 {'className': receiverClass.name, | 2123 {'className': receiverClass.name, |
| 2118 'memberName': name}); | 2124 'memberName': name}); |
| 2119 } | 2125 } |
| 2120 } else if (identical(resolvedReceiver.kind, ElementKind.PREFIX)) { | 2126 } else if (identical(resolvedReceiver.kind, ElementKind.PREFIX)) { |
| 2121 PrefixElement prefix = resolvedReceiver; | 2127 PrefixElement prefix = resolvedReceiver; |
| 2122 target = prefix.lookupLocalMember(name); | 2128 target = prefix.lookupLocalMember(name); |
| 2123 if (Elements.isUnresolved(target)) { | 2129 if (Elements.isUnresolved(target)) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2205 void resolveArguments(NodeList list) { | 2211 void resolveArguments(NodeList list) { |
| 2206 if (list == null) return; | 2212 if (list == null) return; |
| 2207 Map<SourceString, Node> seenNamedArguments = new Map<SourceString, Node>(); | 2213 Map<SourceString, Node> seenNamedArguments = new Map<SourceString, Node>(); |
| 2208 for (Link<Node> link = list.nodes; !link.isEmpty; link = link.tail) { | 2214 for (Link<Node> link = list.nodes; !link.isEmpty; link = link.tail) { |
| 2209 Expression argument = link.head; | 2215 Expression argument = link.head; |
| 2210 visit(argument); | 2216 visit(argument); |
| 2211 NamedArgument namedArgument = argument.asNamedArgument(); | 2217 NamedArgument namedArgument = argument.asNamedArgument(); |
| 2212 if (namedArgument != null) { | 2218 if (namedArgument != null) { |
| 2213 SourceString source = namedArgument.name.source; | 2219 SourceString source = namedArgument.name.source; |
| 2214 if (seenNamedArguments.containsKey(source)) { | 2220 if (seenNamedArguments.containsKey(source)) { |
| 2215 compiler.reportErrorCode( | 2221 compiler.reportError( |
| 2216 argument, | 2222 argument, |
| 2217 MessageKind.DUPLICATE_DEFINITION, | 2223 MessageKind.DUPLICATE_DEFINITION, |
| 2218 {'name': source}); | 2224 {'name': source}); |
| 2219 compiler.reportMessage( | 2225 compiler.reportMessage( |
| 2220 compiler.spanFromSpannable(seenNamedArguments[source]), | 2226 compiler.spanFromSpannable(seenNamedArguments[source]), |
| 2221 MessageKind.EXISTING_DEFINITION.error({'name': source}), | 2227 MessageKind.EXISTING_DEFINITION.error({'name': source}), |
| 2222 Diagnostic.INFO); | 2228 Diagnostic.INFO); |
| 2223 } else { | 2229 } else { |
| 2224 seenNamedArguments[source] = namedArgument; | 2230 seenNamedArguments[source] = namedArgument; |
| 2225 } | 2231 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2332 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { | 2338 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { |
| 2333 world.registerGetOfStaticFunction(target.declaration); | 2339 world.registerGetOfStaticFunction(target.declaration); |
| 2334 } | 2340 } |
| 2335 return node.isPropertyAccess ? target : null; | 2341 return node.isPropertyAccess ? target : null; |
| 2336 } | 2342 } |
| 2337 | 2343 |
| 2338 void warnArgumentMismatch(Send node, Element target) { | 2344 void warnArgumentMismatch(Send node, Element target) { |
| 2339 compiler.backend.registerThrowNoSuchMethod(mapping); | 2345 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2340 // TODO(karlklose): we can be more precise about the reason of the | 2346 // TODO(karlklose): we can be more precise about the reason of the |
| 2341 // mismatch. | 2347 // mismatch. |
| 2342 warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS, | 2348 warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS.warning, |
| 2343 {'methodName': target.name}); | 2349 {'methodName': target.name}); |
| 2344 } | 2350 } |
| 2345 | 2351 |
| 2346 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. | 2352 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. |
| 2347 DartType resolveTypeFromString(String typeName) { | 2353 DartType resolveTypeFromString(String typeName) { |
| 2348 Element element = scope.lookup(new SourceString(typeName)); | 2354 Element element = scope.lookup(new SourceString(typeName)); |
| 2349 if (element == null) return null; | 2355 if (element == null) return null; |
| 2350 if (element is! ClassElement) return null; | 2356 if (element is! ClassElement) return null; |
| 2351 ClassElement cls = element; | 2357 ClassElement cls = element; |
| 2352 cls.ensureResolved(compiler); | 2358 cls.ensureResolved(compiler); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2500 if (node.isRedirectingFactoryBody) { | 2506 if (node.isRedirectingFactoryBody) { |
| 2501 handleRedirectingFactoryBody(node); | 2507 handleRedirectingFactoryBody(node); |
| 2502 } else { | 2508 } else { |
| 2503 visit(node.expression); | 2509 visit(node.expression); |
| 2504 } | 2510 } |
| 2505 } | 2511 } |
| 2506 | 2512 |
| 2507 void handleRedirectingFactoryBody(Return node) { | 2513 void handleRedirectingFactoryBody(Return node) { |
| 2508 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor; | 2514 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor; |
| 2509 if (!enclosingElement.isFactoryConstructor()) { | 2515 if (!enclosingElement.isFactoryConstructor()) { |
| 2510 compiler.reportErrorCode( | 2516 compiler.reportError( |
| 2511 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); | 2517 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); |
| 2512 compiler.reportErrorCode( | 2518 compiler.reportHint( |
| 2513 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD); | 2519 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD); |
| 2514 } | 2520 } |
| 2515 FunctionElement redirectionTarget = resolveRedirectingFactory(node); | 2521 FunctionElement redirectionTarget = resolveRedirectingFactory(node); |
| 2516 useElement(node.expression, redirectionTarget); | 2522 useElement(node.expression, redirectionTarget); |
| 2517 FunctionElement constructor = enclosingElement; | 2523 FunctionElement constructor = enclosingElement; |
| 2518 if (constructor.modifiers.isConst() && | 2524 if (constructor.modifiers.isConst() && |
| 2519 !redirectionTarget.modifiers.isConst()) { | 2525 !redirectionTarget.modifiers.isConst()) { |
| 2520 error(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST); | 2526 error(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST); |
| 2521 } | 2527 } |
| 2522 constructor.defaultImplementation = redirectionTarget; | 2528 constructor.defaultImplementation = redirectionTarget; |
| 2523 if (Elements.isUnresolved(redirectionTarget)) { | 2529 if (Elements.isUnresolved(redirectionTarget)) { |
| 2524 compiler.backend.registerThrowNoSuchMethod(mapping); | 2530 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2525 return; | 2531 return; |
| 2526 } | 2532 } |
| 2527 | 2533 |
| 2528 // Check that the target constructor is type compatible with the | 2534 // Check that the target constructor is type compatible with the |
| 2529 // redirecting constructor. | 2535 // redirecting constructor. |
| 2530 ClassElement targetClass = redirectionTarget.getEnclosingClass(); | 2536 ClassElement targetClass = redirectionTarget.getEnclosingClass(); |
| 2531 InterfaceType type = mapping.getType(node.expression); | 2537 InterfaceType type = mapping.getType(node.expression); |
| 2532 FunctionType targetType = redirectionTarget.computeType(compiler) | 2538 FunctionType targetType = redirectionTarget.computeType(compiler) |
| 2533 .subst(type.typeArguments, targetClass.typeVariables); | 2539 .subst(type.typeArguments, targetClass.typeVariables); |
| 2534 FunctionType constructorType = constructor.computeType(compiler); | 2540 FunctionType constructorType = constructor.computeType(compiler); |
| 2535 if (!compiler.types.isSubtype(targetType, constructorType)) { | 2541 if (!compiler.types.isSubtype(targetType, constructorType)) { |
| 2536 warning(node, MessageKind.NOT_ASSIGNABLE, | 2542 warning(node, MessageKind.NOT_ASSIGNABLE.warning, |
| 2537 {'fromType': targetType, 'toType': constructorType}); | 2543 {'fromType': targetType, 'toType': constructorType}); |
| 2538 } | 2544 } |
| 2539 | 2545 |
| 2540 FunctionSignature targetSignature = | 2546 FunctionSignature targetSignature = |
| 2541 redirectionTarget.computeSignature(compiler); | 2547 redirectionTarget.computeSignature(compiler); |
| 2542 FunctionSignature constructorSignature = | 2548 FunctionSignature constructorSignature = |
| 2543 constructor.computeSignature(compiler); | 2549 constructor.computeSignature(compiler); |
| 2544 if (!targetSignature.isCompatibleWith(constructorSignature)) { | 2550 if (!targetSignature.isCompatibleWith(constructorSignature)) { |
| 2545 compiler.backend.registerThrowNoSuchMethod(mapping); | 2551 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2546 } | 2552 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2618 warnArgumentMismatch(node.send, constructor); | 2624 warnArgumentMismatch(node.send, constructor); |
| 2619 compiler.backend.registerThrowNoSuchMethod(mapping); | 2625 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2620 } | 2626 } |
| 2621 | 2627 |
| 2622 // [constructor] might be the implementation element | 2628 // [constructor] might be the implementation element |
| 2623 // and only declaration elements may be registered. | 2629 // and only declaration elements may be registered. |
| 2624 world.registerStaticUse(constructor.declaration); | 2630 world.registerStaticUse(constructor.declaration); |
| 2625 ClassElement cls = constructor.getEnclosingClass(); | 2631 ClassElement cls = constructor.getEnclosingClass(); |
| 2626 InterfaceType type = mapping.getType(node); | 2632 InterfaceType type = mapping.getType(node); |
| 2627 if (node.isConst() && type.containsTypeVariables) { | 2633 if (node.isConst() && type.containsTypeVariables) { |
| 2628 compiler.reportErrorCode(node.send.selector, | 2634 compiler.reportError(node.send.selector, |
| 2629 MessageKind.TYPE_VARIABLE_IN_CONSTANT); | 2635 MessageKind.TYPE_VARIABLE_IN_CONSTANT); |
| 2630 } | 2636 } |
| 2631 world.registerInstantiatedType(type, mapping); | 2637 world.registerInstantiatedType(type, mapping); |
| 2632 if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) { | 2638 if (constructor.isFactoryConstructor() && !type.typeArguments.isEmpty) { |
| 2633 world.registerFactoryWithTypeArguments(mapping); | 2639 world.registerFactoryWithTypeArguments(mapping); |
| 2634 } | 2640 } |
| 2635 if (cls.isAbstract(compiler)) { | 2641 if (cls.isAbstract(compiler)) { |
| 2636 compiler.backend.registerAbstractClassInstantiation(mapping); | 2642 compiler.backend.registerAbstractClassInstantiation(mapping); |
| 2637 } | 2643 } |
| 2638 | 2644 |
| 2639 if (isSymbolConstructor) { | 2645 if (isSymbolConstructor) { |
| 2640 if (node.isConst()) { | 2646 if (node.isConst()) { |
| 2641 Node argumentNode = node.send.arguments.head; | 2647 Node argumentNode = node.send.arguments.head; |
| 2642 Constant name = compiler.metadataHandler.compileNodeWithDefinitions( | 2648 Constant name = compiler.metadataHandler.compileNodeWithDefinitions( |
| 2643 argumentNode, mapping, isConst: true); | 2649 argumentNode, mapping, isConst: true); |
| 2644 if (!name.isString()) { | 2650 if (!name.isString()) { |
| 2645 DartType type = name.computeType(compiler); | 2651 DartType type = name.computeType(compiler); |
| 2646 compiler.reportErrorCode(argumentNode, MessageKind.STRING_EXPECTED, | 2652 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, |
| 2647 {'type': type}); | 2653 {'type': type}); |
| 2648 } else { | 2654 } else { |
| 2649 StringConstant stringConstant = name; | 2655 StringConstant stringConstant = name; |
| 2650 String nameString = stringConstant.toDartString().slowToString(); | 2656 String nameString = stringConstant.toDartString().slowToString(); |
| 2651 if (validateSymbol(argumentNode, nameString)) { | 2657 if (validateSymbol(argumentNode, nameString)) { |
| 2652 world.registerConstSymbol(nameString, mapping); | 2658 world.registerConstSymbol(nameString, mapping); |
| 2653 } | 2659 } |
| 2654 } | 2660 } |
| 2655 } else { | 2661 } else { |
| 2656 compiler.reportHint( | 2662 compiler.reportHint( |
| 2657 node.newToken, MessageKind.NON_CONST_BLOAT, | 2663 node.newToken, MessageKind.NON_CONST_BLOAT, |
| 2658 {'name': compiler.symbolClass.name}); | 2664 {'name': compiler.symbolClass.name}); |
| 2659 world.registerNewSymbol(mapping); | 2665 world.registerNewSymbol(mapping); |
| 2660 } | 2666 } |
| 2661 } | 2667 } |
| 2662 | 2668 |
| 2663 return null; | 2669 return null; |
| 2664 } | 2670 } |
| 2665 | 2671 |
| 2666 bool validateSymbol(Node node, String name) { | 2672 bool validateSymbol(Node node, String name) { |
| 2667 if (name.isEmpty) return true; | 2673 if (name.isEmpty) return true; |
| 2668 if (name.startsWith('_')) { | 2674 if (name.startsWith('_')) { |
| 2669 compiler.reportErrorCode(node, MessageKind.PRIVATE_IDENTIFIER, | 2675 compiler.reportError(node, MessageKind.PRIVATE_IDENTIFIER, |
| 2670 {'value': name}); | 2676 {'value': name}); |
| 2671 return false; | 2677 return false; |
| 2672 } | 2678 } |
| 2673 if (!symbolValidationPattern.hasMatch(name)) { | 2679 if (!symbolValidationPattern.hasMatch(name)) { |
| 2674 compiler.reportErrorCode(node, MessageKind.INVALID_SYMBOL, | 2680 compiler.reportError(node, MessageKind.INVALID_SYMBOL, |
| 2675 {'value': name}); | 2681 {'value': name}); |
| 2676 return false; | 2682 return false; |
| 2677 } | 2683 } |
| 2678 return true; | 2684 return true; |
| 2679 } | 2685 } |
| 2680 | 2686 |
| 2681 | 2687 |
| 2682 /** | 2688 /** |
| 2683 * Try to resolve the constructor that is referred to by [node]. | 2689 * Try to resolve the constructor that is referred to by [node]. |
| 2684 * Note: this function may return an ErroneousFunctionElement instead of | 2690 * Note: this function may return an ErroneousFunctionElement instead of |
| 2685 * [null], if there is no corresponding constructor, class or library. | 2691 * [null], if there is no corresponding constructor, class or library. |
| 2686 */ | 2692 */ |
| 2687 FunctionElement resolveConstructor(NewExpression node) { | 2693 FunctionElement resolveConstructor(NewExpression node) { |
| 2688 return node.accept(new ConstructorResolver(compiler, this)); | 2694 return node.accept(new ConstructorResolver(compiler, this)); |
| 2689 } | 2695 } |
| 2690 | 2696 |
| 2691 FunctionElement resolveRedirectingFactory(Return node) { | 2697 FunctionElement resolveRedirectingFactory(Return node) { |
| 2692 return node.accept(new ConstructorResolver(compiler, this)); | 2698 return node.accept(new ConstructorResolver(compiler, this)); |
| 2693 } | 2699 } |
| 2694 | 2700 |
| 2695 DartType resolveTypeRequired(TypeAnnotation node) { | 2701 DartType resolveTypeRequired(TypeAnnotation node) { |
| 2696 bool old = typeRequired; | 2702 bool old = typeRequired; |
| 2697 typeRequired = true; | 2703 typeRequired = true; |
| 2698 DartType result = resolveTypeAnnotation(node); | 2704 DartType result = resolveTypeAnnotation(node); |
| 2699 typeRequired = old; | 2705 typeRequired = old; |
| 2700 return result; | 2706 return result; |
| 2701 } | 2707 } |
| 2702 | 2708 |
| 2703 DartType resolveTypeAnnotation(TypeAnnotation node) { | 2709 DartType resolveTypeAnnotation(TypeAnnotation node) { |
| 2704 Function report = typeRequired ? error : warning; | 2710 Function report = typeRequired ? dualError : dualWarning; |
| 2705 DartType type = typeResolver.resolveTypeAnnotation( | 2711 DartType type = typeResolver.resolveTypeAnnotation( |
| 2706 this, node, onFailure: report); | 2712 this, node, onFailure: report); |
| 2707 if (type == null) return null; | 2713 if (type == null) return null; |
| 2708 if (inCheckContext) { | 2714 if (inCheckContext) { |
| 2709 compiler.enqueuer.resolution.registerIsCheck(type, mapping); | 2715 compiler.enqueuer.resolution.registerIsCheck(type, mapping); |
| 2710 } | 2716 } |
| 2711 if (typeRequired || inCheckContext) { | 2717 if (typeRequired || inCheckContext) { |
| 2712 compiler.backend.registerRequiredType(type, enclosingElement); | 2718 compiler.backend.registerRequiredType(type, enclosingElement); |
| 2713 } | 2719 } |
| 2714 return type; | 2720 return type; |
| 2715 } | 2721 } |
| 2716 | 2722 |
| 2717 visitModifiers(Modifiers node) { | 2723 visitModifiers(Modifiers node) { |
| 2718 // TODO(ngeoffray): Implement this. | 2724 // TODO(ngeoffray): Implement this. |
| 2719 unimplemented(node, 'modifiers'); | 2725 unimplemented(node, 'modifiers'); |
| 2720 } | 2726 } |
| 2721 | 2727 |
| 2722 visitLiteralList(LiteralList node) { | 2728 visitLiteralList(LiteralList node) { |
| 2723 NodeList arguments = node.typeArguments; | 2729 NodeList arguments = node.typeArguments; |
| 2724 DartType typeArgument; | 2730 DartType typeArgument; |
| 2725 if (arguments != null) { | 2731 if (arguments != null) { |
| 2726 Link<Node> nodes = arguments.nodes; | 2732 Link<Node> nodes = arguments.nodes; |
| 2727 if (nodes.isEmpty) { | 2733 if (nodes.isEmpty) { |
| 2728 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); | 2734 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error); |
| 2729 } else { | 2735 } else { |
| 2730 typeArgument = resolveTypeRequired(nodes.head); | 2736 typeArgument = resolveTypeRequired(nodes.head); |
| 2731 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { | 2737 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { |
| 2732 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 2738 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.error); |
| 2733 resolveTypeRequired(nodes.head); | 2739 resolveTypeRequired(nodes.head); |
| 2734 } | 2740 } |
| 2735 } | 2741 } |
| 2736 } | 2742 } |
| 2737 DartType listType; | 2743 DartType listType; |
| 2738 if (typeArgument != null) { | 2744 if (typeArgument != null) { |
| 2739 if (node.isConst() && typeArgument.containsTypeVariables) { | 2745 if (node.isConst() && typeArgument.containsTypeVariables) { |
| 2740 compiler.reportErrorCode(arguments.nodes.head, | 2746 compiler.reportError(arguments.nodes.head, |
| 2741 MessageKind.TYPE_VARIABLE_IN_CONSTANT); | 2747 MessageKind.TYPE_VARIABLE_IN_CONSTANT); |
| 2742 } | 2748 } |
| 2743 listType = new InterfaceType(compiler.listClass, | 2749 listType = new InterfaceType(compiler.listClass, |
| 2744 new Link<DartType>.fromList([typeArgument])); | 2750 new Link<DartType>.fromList([typeArgument])); |
| 2745 } else { | 2751 } else { |
| 2746 compiler.listClass.computeType(compiler); | 2752 compiler.listClass.computeType(compiler); |
| 2747 listType = compiler.listClass.rawType; | 2753 listType = compiler.listClass.rawType; |
| 2748 } | 2754 } |
| 2749 mapping.setType(node, listType); | 2755 mapping.setType(node, listType); |
| 2750 world.registerInstantiatedType(listType, mapping); | 2756 world.registerInstantiatedType(listType, mapping); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2846 | 2852 |
| 2847 Send send = declaration.asSend(); | 2853 Send send = declaration.asSend(); |
| 2848 VariableDefinitions variableDefinitions = | 2854 VariableDefinitions variableDefinitions = |
| 2849 declaration.asVariableDefinitions(); | 2855 declaration.asVariableDefinitions(); |
| 2850 Element loopVariable; | 2856 Element loopVariable; |
| 2851 Selector loopVariableSelector; | 2857 Selector loopVariableSelector; |
| 2852 if (send != null) { | 2858 if (send != null) { |
| 2853 loopVariable = mapping[send]; | 2859 loopVariable = mapping[send]; |
| 2854 Identifier identifier = send.selector.asIdentifier(); | 2860 Identifier identifier = send.selector.asIdentifier(); |
| 2855 if (identifier == null) { | 2861 if (identifier == null) { |
| 2856 compiler.reportErrorCode(send.selector, MessageKind.INVALID_FOR_IN); | 2862 compiler.reportError(send.selector, MessageKind.INVALID_FOR_IN); |
| 2857 } else { | 2863 } else { |
| 2858 loopVariableSelector = new Selector.setter(identifier.source, library); | 2864 loopVariableSelector = new Selector.setter(identifier.source, library); |
| 2859 } | 2865 } |
| 2860 if (send.receiver != null) { | 2866 if (send.receiver != null) { |
| 2861 compiler.reportErrorCode(send.receiver, MessageKind.INVALID_FOR_IN); | 2867 compiler.reportError(send.receiver, MessageKind.INVALID_FOR_IN); |
| 2862 } | 2868 } |
| 2863 } else if (variableDefinitions != null) { | 2869 } else if (variableDefinitions != null) { |
| 2864 Link<Node> nodes = variableDefinitions.definitions.nodes; | 2870 Link<Node> nodes = variableDefinitions.definitions.nodes; |
| 2865 if (!nodes.tail.isEmpty) { | 2871 if (!nodes.tail.isEmpty) { |
| 2866 compiler.reportErrorCode(nodes.tail.head, MessageKind.INVALID_FOR_IN); | 2872 compiler.reportError(nodes.tail.head, MessageKind.INVALID_FOR_IN); |
| 2867 } | 2873 } |
| 2868 Node first = nodes.head; | 2874 Node first = nodes.head; |
| 2869 Identifier identifier = first.asIdentifier(); | 2875 Identifier identifier = first.asIdentifier(); |
| 2870 if (identifier == null) { | 2876 if (identifier == null) { |
| 2871 compiler.reportErrorCode(first, MessageKind.INVALID_FOR_IN); | 2877 compiler.reportError(first, MessageKind.INVALID_FOR_IN); |
| 2872 } else { | 2878 } else { |
| 2873 loopVariableSelector = new Selector.setter(identifier.source, library); | 2879 loopVariableSelector = new Selector.setter(identifier.source, library); |
| 2874 loopVariable = mapping[identifier]; | 2880 loopVariable = mapping[identifier]; |
| 2875 } | 2881 } |
| 2876 } else { | 2882 } else { |
| 2877 compiler.reportErrorCode(declaration, MessageKind.INVALID_FOR_IN); | 2883 compiler.reportError(declaration, MessageKind.INVALID_FOR_IN); |
| 2878 } | 2884 } |
| 2879 if (loopVariableSelector != null) { | 2885 if (loopVariableSelector != null) { |
| 2880 mapping.setSelector(declaration, loopVariableSelector); | 2886 mapping.setSelector(declaration, loopVariableSelector); |
| 2881 registerSend(loopVariableSelector, loopVariable); | 2887 registerSend(loopVariableSelector, loopVariable); |
| 2882 } else { | 2888 } else { |
| 2883 // The selector may only be null if we reported an error. | 2889 // The selector may only be null if we reported an error. |
| 2884 assert(invariant(declaration, compiler.compilationFailed)); | 2890 assert(invariant(declaration, compiler.compilationFailed)); |
| 2885 } | 2891 } |
| 2886 if (loopVariable != null) { | 2892 if (loopVariable != null) { |
| 2887 // loopVariable may be null if it could not be resolved. | 2893 // loopVariable may be null if it could not be resolved. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2922 } | 2928 } |
| 2923 } | 2929 } |
| 2924 | 2930 |
| 2925 visitLiteralMap(LiteralMap node) { | 2931 visitLiteralMap(LiteralMap node) { |
| 2926 NodeList arguments = node.typeArguments; | 2932 NodeList arguments = node.typeArguments; |
| 2927 DartType keyTypeArgument; | 2933 DartType keyTypeArgument; |
| 2928 DartType valueTypeArgument; | 2934 DartType valueTypeArgument; |
| 2929 if (arguments != null) { | 2935 if (arguments != null) { |
| 2930 Link<Node> nodes = arguments.nodes; | 2936 Link<Node> nodes = arguments.nodes; |
| 2931 if (nodes.isEmpty) { | 2937 if (nodes.isEmpty) { |
| 2932 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); | 2938 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error); |
| 2933 } else { | 2939 } else { |
| 2934 keyTypeArgument = resolveTypeRequired(nodes.head); | 2940 keyTypeArgument = resolveTypeRequired(nodes.head); |
| 2935 nodes = nodes.tail; | 2941 nodes = nodes.tail; |
| 2936 if (nodes.isEmpty) { | 2942 if (nodes.isEmpty) { |
| 2937 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT); | 2943 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT.error); |
| 2938 } else { | 2944 } else { |
| 2939 valueTypeArgument = resolveTypeRequired(nodes.head); | 2945 valueTypeArgument = resolveTypeRequired(nodes.head); |
| 2940 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { | 2946 for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) { |
| 2941 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 2947 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.error); |
| 2942 resolveTypeRequired(nodes.head); | 2948 resolveTypeRequired(nodes.head); |
| 2943 } | 2949 } |
| 2944 } | 2950 } |
| 2945 } | 2951 } |
| 2946 } | 2952 } |
| 2947 DartType mapType; | 2953 DartType mapType; |
| 2948 if (valueTypeArgument != null) { | 2954 if (valueTypeArgument != null) { |
| 2949 mapType = new InterfaceType(compiler.mapClass, | 2955 mapType = new InterfaceType(compiler.mapClass, |
| 2950 new Link<DartType>.fromList([keyTypeArgument, valueTypeArgument])); | 2956 new Link<DartType>.fromList([keyTypeArgument, valueTypeArgument])); |
| 2951 } else { | 2957 } else { |
| 2952 compiler.mapClass.computeType(compiler); | 2958 compiler.mapClass.computeType(compiler); |
| 2953 mapType = compiler.mapClass.rawType; | 2959 mapType = compiler.mapClass.rawType; |
| 2954 } | 2960 } |
| 2955 if (node.isConst() && mapType.containsTypeVariables) { | 2961 if (node.isConst() && mapType.containsTypeVariables) { |
| 2956 compiler.reportErrorCode(arguments, | 2962 compiler.reportError(arguments, |
| 2957 MessageKind.TYPE_VARIABLE_IN_CONSTANT); | 2963 MessageKind.TYPE_VARIABLE_IN_CONSTANT); |
| 2958 } | 2964 } |
| 2959 mapping.setType(node, mapType); | 2965 mapping.setType(node, mapType); |
| 2960 world.registerInstantiatedClass(compiler.mapClass, mapping); | 2966 world.registerInstantiatedClass(compiler.mapClass, mapping); |
| 2961 if (node.isConst()) { | 2967 if (node.isConst()) { |
| 2962 compiler.backend.registerConstantMap(mapping); | 2968 compiler.backend.registerConstantMap(mapping); |
| 2963 } | 2969 } |
| 2964 node.visitChildren(this); | 2970 node.visitChildren(this); |
| 2965 } | 2971 } |
| 2966 | 2972 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2981 while (!cases.isEmpty) { | 2987 while (!cases.isEmpty) { |
| 2982 SwitchCase switchCase = cases.head; | 2988 SwitchCase switchCase = cases.head; |
| 2983 for (Node labelOrCase in switchCase.labelsAndCases) { | 2989 for (Node labelOrCase in switchCase.labelsAndCases) { |
| 2984 if (labelOrCase is! Label) continue; | 2990 if (labelOrCase is! Label) continue; |
| 2985 Label label = labelOrCase; | 2991 Label label = labelOrCase; |
| 2986 String labelName = label.slowToString(); | 2992 String labelName = label.slowToString(); |
| 2987 | 2993 |
| 2988 LabelElement existingElement = continueLabels[labelName]; | 2994 LabelElement existingElement = continueLabels[labelName]; |
| 2989 if (existingElement != null) { | 2995 if (existingElement != null) { |
| 2990 // It's an error if the same label occurs twice in the same switch. | 2996 // It's an error if the same label occurs twice in the same switch. |
| 2991 warning(label, MessageKind.DUPLICATE_LABEL, {'labelName': labelName}); | 2997 compiler.reportError( |
| 2992 error(existingElement.label, MessageKind.EXISTING_LABEL, | 2998 label, |
| 2993 {'labelName': labelName}); | 2999 MessageKind.DUPLICATE_LABEL.error, {'labelName': labelName}); |
| 3000 compiler.reportInfo( | |
| 3001 existingElement.label, | |
| 3002 MessageKind.EXISTING_LABEL, {'labelName': labelName}); | |
| 2994 } else { | 3003 } else { |
| 2995 // It's only a warning if it shadows another label. | 3004 // It's only a warning if it shadows another label. |
| 2996 existingElement = statementScope.lookupLabel(labelName); | 3005 existingElement = statementScope.lookupLabel(labelName); |
| 2997 if (existingElement != null) { | 3006 if (existingElement != null) { |
| 2998 warning(label, MessageKind.DUPLICATE_LABEL, | 3007 compiler.reportWarningCode( |
| 2999 {'labelName': labelName}); | 3008 label, |
| 3000 warning(existingElement.label, | 3009 MessageKind.DUPLICATE_LABEL.warning, {'labelName': labelName}); |
| 3001 MessageKind.EXISTING_LABEL, {'labelName': labelName}); | 3010 compiler.reportInfo( |
| 3011 existingElement.label, | |
| 3012 MessageKind.EXISTING_LABEL, {'labelName': labelName}); | |
| 3002 } | 3013 } |
| 3003 } | 3014 } |
| 3004 | 3015 |
| 3005 TargetElement targetElement = getOrCreateTargetElement(switchCase); | 3016 TargetElement targetElement = getOrCreateTargetElement(switchCase); |
| 3006 LabelElement labelElement = targetElement.addLabel(label, labelName); | 3017 LabelElement labelElement = targetElement.addLabel(label, labelName); |
| 3007 mapping[label] = labelElement; | 3018 mapping[label] = labelElement; |
| 3008 continueLabels[labelName] = labelElement; | 3019 continueLabels[labelName] = labelElement; |
| 3009 } | 3020 } |
| 3010 cases = cases.tail; | 3021 cases = cases.tail; |
| 3011 // Test that only the last case, if any, is a default case. | 3022 // Test that only the last case, if any, is a default case. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3155 TypeVariable typeNode = nodeLink.head; | 3166 TypeVariable typeNode = nodeLink.head; |
| 3156 if (nameSet.contains(typeName)) { | 3167 if (nameSet.contains(typeName)) { |
| 3157 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, | 3168 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, |
| 3158 {'typeVariableName': typeName}); | 3169 {'typeVariableName': typeName}); |
| 3159 } | 3170 } |
| 3160 nameSet.add(typeName); | 3171 nameSet.add(typeName); |
| 3161 | 3172 |
| 3162 TypeVariableElement variableElement = typeVariable.element; | 3173 TypeVariableElement variableElement = typeVariable.element; |
| 3163 if (typeNode.bound != null) { | 3174 if (typeNode.bound != null) { |
| 3164 DartType boundType = typeResolver.resolveTypeAnnotation( | 3175 DartType boundType = typeResolver.resolveTypeAnnotation( |
| 3165 this, typeNode.bound, onFailure: warning); | 3176 this, typeNode.bound, onFailure: dualWarning); |
| 3166 variableElement.bound = boundType; | 3177 variableElement.bound = boundType; |
| 3167 | 3178 |
| 3168 void checkTypeVariableBound() { | 3179 void checkTypeVariableBound() { |
| 3169 Link<TypeVariableElement> seenTypeVariables = | 3180 Link<TypeVariableElement> seenTypeVariables = |
| 3170 const Link<TypeVariableElement>(); | 3181 const Link<TypeVariableElement>(); |
| 3171 seenTypeVariables = seenTypeVariables.prepend(variableElement); | 3182 seenTypeVariables = seenTypeVariables.prepend(variableElement); |
| 3172 DartType bound = boundType; | 3183 DartType bound = boundType; |
| 3173 while (bound.element.isTypeVariable()) { | 3184 while (bound.element.isTypeVariable()) { |
| 3174 TypeVariableElement element = bound.element; | 3185 TypeVariableElement element = bound.element; |
| 3175 if (seenTypeVariables.contains(element)) { | 3186 if (seenTypeVariables.contains(element)) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3287 } | 3298 } |
| 3288 | 3299 |
| 3289 assert(element.interfaces == null); | 3300 assert(element.interfaces == null); |
| 3290 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); | 3301 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); |
| 3291 calculateAllSupertypes(element); | 3302 calculateAllSupertypes(element); |
| 3292 | 3303 |
| 3293 if (!element.hasConstructor) { | 3304 if (!element.hasConstructor) { |
| 3294 Element superMember = | 3305 Element superMember = |
| 3295 element.superclass.localLookup(const SourceString('')); | 3306 element.superclass.localLookup(const SourceString('')); |
| 3296 if (superMember == null || !superMember.isGenerativeConstructor()) { | 3307 if (superMember == null || !superMember.isGenerativeConstructor()) { |
| 3297 MessageKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR; | 3308 DualKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR; |
| 3298 Map arguments = {'constructorName': const SourceString('')}; | 3309 Map arguments = {'constructorName': const SourceString('')}; |
| 3299 compiler.reportErrorCode(node, kind, arguments); | 3310 // TODO(ahe): Why is this a compile-time error? Or if it is an error, |
| 3311 // why do we bother to registerThrowNoSuchMethod below? | |
| 3312 compiler.reportError(node, kind.error, arguments); | |
| 3300 superMember = new ErroneousElementX( | 3313 superMember = new ErroneousElementX( |
| 3301 kind, arguments, const SourceString(''), element); | 3314 kind.error, arguments, const SourceString(''), element); |
| 3302 compiler.backend.registerThrowNoSuchMethod(mapping); | 3315 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 3303 } | 3316 } |
| 3304 FunctionElement constructor = | 3317 FunctionElement constructor = |
| 3305 new SynthesizedConstructorElementX.forDefault(superMember, element); | 3318 new SynthesizedConstructorElementX.forDefault(superMember, element); |
| 3306 element.setDefaultConstructor(constructor, compiler); | 3319 element.setDefaultConstructor(constructor, compiler); |
| 3307 } | 3320 } |
| 3308 return element.computeType(compiler); | 3321 return element.computeType(compiler); |
| 3309 } | 3322 } |
| 3310 | 3323 |
| 3311 DartType visitNamedMixinApplication(NamedMixinApplication node) { | 3324 DartType visitNamedMixinApplication(NamedMixinApplication node) { |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3403 DartType mixinType) { | 3416 DartType mixinType) { |
| 3404 ClassElement mixin = mixinType.element; | 3417 ClassElement mixin = mixinType.element; |
| 3405 mixin.ensureResolved(compiler); | 3418 mixin.ensureResolved(compiler); |
| 3406 | 3419 |
| 3407 // Check for cycles in the mixin chain. | 3420 // Check for cycles in the mixin chain. |
| 3408 ClassElement previous = mixinApplication; // For better error messages. | 3421 ClassElement previous = mixinApplication; // For better error messages. |
| 3409 ClassElement current = mixin; | 3422 ClassElement current = mixin; |
| 3410 while (current != null && current.isMixinApplication) { | 3423 while (current != null && current.isMixinApplication) { |
| 3411 MixinApplicationElement currentMixinApplication = current; | 3424 MixinApplicationElement currentMixinApplication = current; |
| 3412 if (currentMixinApplication == mixinApplication) { | 3425 if (currentMixinApplication == mixinApplication) { |
| 3413 compiler.reportErrorCode( | 3426 compiler.reportError( |
| 3414 mixinApplication, MessageKind.ILLEGAL_MIXIN_CYCLE, | 3427 mixinApplication, MessageKind.ILLEGAL_MIXIN_CYCLE, |
| 3415 {'mixinName1': current.name, 'mixinName2': previous.name}); | 3428 {'mixinName1': current.name, 'mixinName2': previous.name}); |
| 3416 // We have found a cycle in the mixin chain. Return null as | 3429 // We have found a cycle in the mixin chain. Return null as |
| 3417 // the mixin for this application to avoid getting into | 3430 // the mixin for this application to avoid getting into |
| 3418 // infinite recursion when traversing members. | 3431 // infinite recursion when traversing members. |
| 3419 return null; | 3432 return null; |
| 3420 } | 3433 } |
| 3421 previous = current; | 3434 previous = current; |
| 3422 current = currentMixinApplication.mixin; | 3435 current = currentMixinApplication.mixin; |
| 3423 } | 3436 } |
| 3424 compiler.world.registerMixinUse(mixinApplication, mixin); | 3437 compiler.world.registerMixinUse(mixinApplication, mixin); |
| 3425 return mixin; | 3438 return mixin; |
| 3426 } | 3439 } |
| 3427 | 3440 |
| 3428 DartType resolveType(TypeAnnotation node) { | 3441 DartType resolveType(TypeAnnotation node) { |
| 3429 // TODO(johnniwinther): Report errors/warnings on resolution failures. | 3442 // TODO(johnniwinther): Report errors/warnings on resolution failures. |
| 3430 return typeResolver.resolveTypeAnnotation(this, node); | 3443 return typeResolver.resolveTypeAnnotation(this, node); |
| 3431 } | 3444 } |
| 3432 | 3445 |
| 3433 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { | 3446 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) { |
| 3434 DartType supertype = typeResolver.resolveTypeAnnotation( | 3447 DartType supertype = typeResolver.resolveTypeAnnotation( |
| 3435 this, superclass, onFailure: error); | 3448 this, superclass, onFailure: dualError); |
| 3436 if (supertype != null) { | 3449 if (supertype != null) { |
| 3437 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { | 3450 if (identical(supertype.kind, TypeKind.MALFORMED_TYPE)) { |
| 3438 // Error has already been reported. | 3451 // Error has already been reported. |
| 3439 return null; | 3452 return null; |
| 3440 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { | 3453 } else if (!identical(supertype.kind, TypeKind.INTERFACE)) { |
| 3441 // TODO(johnniwinther): Handle dynamic. | 3454 // TODO(johnniwinther): Handle dynamic. |
| 3442 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); | 3455 error(superclass.typeName, MessageKind.CLASS_NAME_EXPECTED); |
| 3443 return null; | 3456 return null; |
| 3444 } else if (isBlackListed(supertype)) { | 3457 } else if (isBlackListed(supertype)) { |
| 3445 error(superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); | 3458 error(superclass, MessageKind.CANNOT_EXTEND, {'type': supertype}); |
| 3446 return null; | 3459 return null; |
| 3447 } | 3460 } |
| 3448 } | 3461 } |
| 3449 return supertype; | 3462 return supertype; |
| 3450 } | 3463 } |
| 3451 | 3464 |
| 3452 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { | 3465 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) { |
| 3453 Link<DartType> result = const Link<DartType>(); | 3466 Link<DartType> result = const Link<DartType>(); |
| 3454 if (interfaces == null) return result; | 3467 if (interfaces == null) return result; |
| 3455 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { | 3468 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) { |
| 3456 DartType interfaceType = typeResolver.resolveTypeAnnotation( | 3469 DartType interfaceType = typeResolver.resolveTypeAnnotation( |
| 3457 this, link.head, onFailure: error); | 3470 this, link.head, onFailure: dualError); |
| 3458 if (interfaceType != null) { | 3471 if (interfaceType != null) { |
| 3459 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { | 3472 if (identical(interfaceType.kind, TypeKind.MALFORMED_TYPE)) { |
| 3460 // Error has already been reported. | 3473 // Error has already been reported. |
| 3461 } else if (!identical(interfaceType.kind, TypeKind.INTERFACE)) { | 3474 } else if (!identical(interfaceType.kind, TypeKind.INTERFACE)) { |
| 3462 // TODO(johnniwinther): Handle dynamic. | 3475 // TODO(johnniwinther): Handle dynamic. |
| 3463 TypeAnnotation typeAnnotation = link.head; | 3476 TypeAnnotation typeAnnotation = link.head; |
| 3464 error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED); | 3477 error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED); |
| 3465 } else { | 3478 } else { |
| 3466 if (interfaceType == element.supertype) { | 3479 if (interfaceType == element.supertype) { |
| 3467 compiler.reportErrorCode( | 3480 compiler.reportError( |
| 3468 superclass, | 3481 superclass, |
| 3469 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 3482 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
| 3470 {'type': interfaceType}); | 3483 {'type': interfaceType}); |
| 3471 compiler.reportErrorCode( | 3484 compiler.reportError( |
| 3472 link.head, | 3485 link.head, |
| 3473 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, | 3486 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS, |
| 3474 {'type': interfaceType}); | 3487 {'type': interfaceType}); |
| 3475 } | 3488 } |
| 3476 if (result.contains(interfaceType)) { | 3489 if (result.contains(interfaceType)) { |
| 3477 compiler.reportErrorCode( | 3490 compiler.reportError( |
| 3478 link.head, | 3491 link.head, |
| 3479 MessageKind.DUPLICATE_IMPLEMENTS, | 3492 MessageKind.DUPLICATE_IMPLEMENTS, |
| 3480 {'type': interfaceType}); | 3493 {'type': interfaceType}); |
| 3481 } | 3494 } |
| 3482 result = result.prepend(interfaceType); | 3495 result = result.prepend(interfaceType); |
| 3483 if (isBlackListed(interfaceType)) { | 3496 if (isBlackListed(interfaceType)) { |
| 3484 error(link.head, MessageKind.CANNOT_IMPLEMENT, | 3497 error(link.head, MessageKind.CANNOT_IMPLEMENT, |
| 3485 {'type': interfaceType}); | 3498 {'type': interfaceType}); |
| 3486 } | 3499 } |
| 3487 } | 3500 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3625 visitNodeList(node.interfaces); | 3638 visitNodeList(node.interfaces); |
| 3626 } | 3639 } |
| 3627 | 3640 |
| 3628 void visitTypeAnnotation(TypeAnnotation node) { | 3641 void visitTypeAnnotation(TypeAnnotation node) { |
| 3629 node.typeName.accept(this); | 3642 node.typeName.accept(this); |
| 3630 } | 3643 } |
| 3631 | 3644 |
| 3632 void visitIdentifier(Identifier node) { | 3645 void visitIdentifier(Identifier node) { |
| 3633 Element element = context.lookup(node.source); | 3646 Element element = context.lookup(node.source); |
| 3634 if (element == null) { | 3647 if (element == null) { |
| 3635 error(node, MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node}); | 3648 error(node, MessageKind.CANNOT_RESOLVE_TYPE.error, {'typeName': node}); |
| 3636 } else if (!element.impliesType()) { | 3649 } else if (!element.impliesType()) { |
| 3637 error(node, MessageKind.NOT_A_TYPE, {'node': node}); | 3650 error(node, MessageKind.NOT_A_TYPE.error, {'node': node}); |
| 3638 } else { | 3651 } else { |
| 3639 if (element.isClass()) { | 3652 if (element.isClass()) { |
| 3640 loadSupertype(element, node); | 3653 loadSupertype(element, node); |
| 3641 } else { | 3654 } else { |
| 3642 compiler.reportErrorCode(node, MessageKind.CLASS_NAME_EXPECTED); | 3655 compiler.reportError(node, MessageKind.CLASS_NAME_EXPECTED); |
| 3643 } | 3656 } |
| 3644 } | 3657 } |
| 3645 } | 3658 } |
| 3646 | 3659 |
| 3647 void visitSend(Send node) { | 3660 void visitSend(Send node) { |
| 3648 Identifier prefix = node.receiver.asIdentifier(); | 3661 Identifier prefix = node.receiver.asIdentifier(); |
| 3649 if (prefix == null) { | 3662 if (prefix == null) { |
| 3650 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); | 3663 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); |
| 3651 return; | 3664 return; |
| 3652 } | 3665 } |
| 3653 Element element = context.lookup(prefix.source); | 3666 Element element = context.lookup(prefix.source); |
| 3654 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { | 3667 if (element == null || !identical(element.kind, ElementKind.PREFIX)) { |
| 3655 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); | 3668 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver}); |
| 3656 return; | 3669 return; |
| 3657 } | 3670 } |
| 3658 PrefixElement prefixElement = element; | 3671 PrefixElement prefixElement = element; |
| 3659 Identifier selector = node.selector.asIdentifier(); | 3672 Identifier selector = node.selector.asIdentifier(); |
| 3660 var e = prefixElement.lookupLocalMember(selector.source); | 3673 var e = prefixElement.lookupLocalMember(selector.source); |
| 3661 if (e == null || !e.impliesType()) { | 3674 if (e == null || !e.impliesType()) { |
| 3662 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, | 3675 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE.error, |
| 3663 {'typeName': node.selector}); | 3676 {'typeName': node.selector}); |
| 3664 return; | 3677 return; |
| 3665 } | 3678 } |
| 3666 loadSupertype(e, node); | 3679 loadSupertype(e, node); |
| 3667 } | 3680 } |
| 3668 } | 3681 } |
| 3669 | 3682 |
| 3670 class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> { | 3683 class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> { |
| 3671 VariableDefinitions definitions; | 3684 VariableDefinitions definitions; |
| 3672 ResolverVisitor resolver; | 3685 ResolverVisitor resolver; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3853 */ | 3866 */ |
| 3854 static FunctionSignature analyze(Compiler compiler, | 3867 static FunctionSignature analyze(Compiler compiler, |
| 3855 NodeList formalParameters, | 3868 NodeList formalParameters, |
| 3856 Node returnNode, | 3869 Node returnNode, |
| 3857 Element element) { | 3870 Element element) { |
| 3858 SignatureResolver visitor = new SignatureResolver(compiler, element); | 3871 SignatureResolver visitor = new SignatureResolver(compiler, element); |
| 3859 Link<Element> parameters = const Link<Element>(); | 3872 Link<Element> parameters = const Link<Element>(); |
| 3860 int requiredParameterCount = 0; | 3873 int requiredParameterCount = 0; |
| 3861 if (formalParameters == null) { | 3874 if (formalParameters == null) { |
| 3862 if (!element.isGetter()) { | 3875 if (!element.isGetter()) { |
| 3863 compiler.reportErrorCode(element, MessageKind.MISSING_FORMALS); | 3876 compiler.reportError(element, MessageKind.MISSING_FORMALS); |
| 3864 } | 3877 } |
| 3865 } else { | 3878 } else { |
| 3866 if (element.isGetter()) { | 3879 if (element.isGetter()) { |
| 3867 if (!identical(formalParameters.getEndToken().next.stringValue, | 3880 if (!identical(formalParameters.getEndToken().next.stringValue, |
| 3868 // TODO(ahe): Remove the check for native keyword. | 3881 // TODO(ahe): Remove the check for native keyword. |
| 3869 'native')) { | 3882 'native')) { |
| 3870 if (compiler.rejectDeprecatedFeatures && | 3883 if (compiler.rejectDeprecatedFeatures && |
| 3871 // TODO(ahe): Remove isPlatformLibrary check. | 3884 // TODO(ahe): Remove isPlatformLibrary check. |
| 3872 !element.getLibrary().isPlatformLibrary) { | 3885 !element.getLibrary().isPlatformLibrary) { |
| 3873 compiler.reportErrorCode(formalParameters, | 3886 compiler.reportError(formalParameters, |
| 3874 MessageKind.EXTRA_FORMALS); | 3887 MessageKind.EXTRA_FORMALS); |
| 3875 } else { | 3888 } else { |
| 3876 compiler.onDeprecatedFeature(formalParameters, 'getter parameters'); | 3889 compiler.onDeprecatedFeature(formalParameters, 'getter parameters'); |
| 3877 } | 3890 } |
| 3878 } | 3891 } |
| 3879 } | 3892 } |
| 3880 LinkBuilder<Element> parametersBuilder = | 3893 LinkBuilder<Element> parametersBuilder = |
| 3881 visitor.analyzeNodes(formalParameters.nodes); | 3894 visitor.analyzeNodes(formalParameters.nodes); |
| 3882 requiredParameterCount = parametersBuilder.length; | 3895 requiredParameterCount = parametersBuilder.length; |
| 3883 parameters = parametersBuilder.toLink(); | 3896 parameters = parametersBuilder.toLink(); |
| 3884 } | 3897 } |
| 3885 DartType returnType; | 3898 DartType returnType; |
| 3886 if (element.isFactoryConstructor()) { | 3899 if (element.isFactoryConstructor()) { |
| 3887 returnType = element.getEnclosingClass().computeType(compiler); | 3900 returnType = element.getEnclosingClass().computeType(compiler); |
| 3888 // Because there is no type annotation for the return type of | 3901 // Because there is no type annotation for the return type of |
| 3889 // this element, we explicitly add one. | 3902 // this element, we explicitly add one. |
| 3890 if (compiler.enableTypeAssertions) { | 3903 if (compiler.enableTypeAssertions) { |
| 3891 compiler.enqueuer.resolution.registerIsCheck( | 3904 compiler.enqueuer.resolution.registerIsCheck( |
| 3892 returnType, new TreeElementMapping(element)); | 3905 returnType, new TreeElementMapping(element)); |
| 3893 } | 3906 } |
| 3894 } else { | 3907 } else { |
| 3895 returnType = compiler.resolveReturnType(element, returnNode); | 3908 returnType = compiler.resolveReturnType(element, returnNode); |
| 3896 } | 3909 } |
| 3897 | 3910 |
| 3898 if (element.isSetter() && (requiredParameterCount != 1 || | 3911 if (element.isSetter() && (requiredParameterCount != 1 || |
| 3899 visitor.optionalParameterCount != 0)) { | 3912 visitor.optionalParameterCount != 0)) { |
| 3900 // If there are no formal parameters, we already reported an error above. | 3913 // If there are no formal parameters, we already reported an error above. |
| 3901 if (formalParameters != null) { | 3914 if (formalParameters != null) { |
| 3902 compiler.reportErrorCode(formalParameters, | 3915 compiler.reportError(formalParameters, |
| 3903 MessageKind.ILLEGAL_SETTER_FORMALS); | 3916 MessageKind.ILLEGAL_SETTER_FORMALS); |
| 3904 } | 3917 } |
| 3905 } | 3918 } |
| 3906 if (element.isGetter() && (requiredParameterCount != 0 | 3919 if (element.isGetter() && (requiredParameterCount != 0 |
| 3907 || visitor.optionalParameterCount != 0)) { | 3920 || visitor.optionalParameterCount != 0)) { |
| 3908 compiler.reportErrorCode(formalParameters, MessageKind.EXTRA_FORMALS); | 3921 compiler.reportError(formalParameters, MessageKind.EXTRA_FORMALS); |
| 3909 } | 3922 } |
| 3910 return new FunctionSignatureX(parameters, | 3923 return new FunctionSignatureX(parameters, |
| 3911 visitor.optionalParameters, | 3924 visitor.optionalParameters, |
| 3912 requiredParameterCount, | 3925 requiredParameterCount, |
| 3913 visitor.optionalParameterCount, | 3926 visitor.optionalParameterCount, |
| 3914 visitor.optionalParametersAreNamed, | 3927 visitor.optionalParametersAreNamed, |
| 3915 returnType); | 3928 returnType); |
| 3916 } | 3929 } |
| 3917 | 3930 |
| 3918 // TODO(ahe): This is temporary. | 3931 // TODO(ahe): This is temporary. |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 3934 bool inConstContext = false; | 3947 bool inConstContext = false; |
| 3935 DartType type; | 3948 DartType type; |
| 3936 | 3949 |
| 3937 ConstructorResolver(Compiler compiler, this.resolver) : super(compiler); | 3950 ConstructorResolver(Compiler compiler, this.resolver) : super(compiler); |
| 3938 | 3951 |
| 3939 visitNode(Node node) { | 3952 visitNode(Node node) { |
| 3940 throw 'not supported'; | 3953 throw 'not supported'; |
| 3941 } | 3954 } |
| 3942 | 3955 |
| 3943 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode, | 3956 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode, |
| 3944 SourceString targetName, MessageKind kind, | 3957 SourceString targetName, DualKind kind, |
| 3945 Map arguments) { | 3958 Map arguments) { |
| 3946 if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { | 3959 if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { |
| 3947 compiler.backend.registerThrowNoSuchMethod(resolver.mapping); | 3960 compiler.backend.registerThrowNoSuchMethod(resolver.mapping); |
| 3948 } else { | 3961 } else { |
| 3949 compiler.backend.registerThrowRuntimeError(resolver.mapping); | 3962 compiler.backend.registerThrowRuntimeError(resolver.mapping); |
| 3950 } | 3963 } |
| 3951 if (inConstContext) { | 3964 if (inConstContext) { |
| 3952 error(diagnosticNode, kind, arguments); | 3965 error(diagnosticNode, kind.error, arguments); |
| 3953 } else { | 3966 } else { |
| 3954 ResolutionWarning warning = new ResolutionWarning(kind, arguments); | 3967 ResolutionWarning warning = |
| 3968 new ResolutionWarning(kind.warning, arguments); | |
| 3955 compiler.reportWarning(diagnosticNode, warning); | 3969 compiler.reportWarning(diagnosticNode, warning); |
| 3956 return new ErroneousElementX(kind, arguments, targetName, enclosing); | 3970 return new ErroneousElementX( |
| 3971 kind.error, arguments, targetName, enclosing); | |
| 3957 } | 3972 } |
| 3958 } | 3973 } |
| 3959 | 3974 |
| 3960 Selector createConstructorSelector(SourceString constructorName) { | 3975 Selector createConstructorSelector(SourceString constructorName) { |
| 3961 return constructorName == const SourceString('') | 3976 return constructorName == const SourceString('') |
| 3962 ? new Selector.callDefaultConstructor( | 3977 ? new Selector.callDefaultConstructor( |
| 3963 resolver.enclosingElement.getLibrary()) | 3978 resolver.enclosingElement.getLibrary()) |
| 3964 : new Selector.callConstructor( | 3979 : new Selector.callConstructor( |
| 3965 constructorName, | 3980 constructorName, |
| 3966 resolver.enclosingElement.getLibrary()); | 3981 resolver.enclosingElement.getLibrary()); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4034 if (name == null) internalError(node.selector, 'unexpected node'); | 4049 if (name == null) internalError(node.selector, 'unexpected node'); |
| 4035 | 4050 |
| 4036 if (identical(e.kind, ElementKind.CLASS)) { | 4051 if (identical(e.kind, ElementKind.CLASS)) { |
| 4037 ClassElement cls = e; | 4052 ClassElement cls = e; |
| 4038 cls.ensureResolved(compiler); | 4053 cls.ensureResolved(compiler); |
| 4039 return lookupConstructor(cls, name, name.source); | 4054 return lookupConstructor(cls, name, name.source); |
| 4040 } else if (identical(e.kind, ElementKind.PREFIX)) { | 4055 } else if (identical(e.kind, ElementKind.PREFIX)) { |
| 4041 PrefixElement prefix = e; | 4056 PrefixElement prefix = e; |
| 4042 e = prefix.lookupLocalMember(name.source); | 4057 e = prefix.lookupLocalMember(name.source); |
| 4043 if (e == null) { | 4058 if (e == null) { |
| 4044 return failOrReturnErroneousElement(resolver.enclosingElement, name, | 4059 return failOrReturnErroneousElement( |
| 4045 name.source, | 4060 resolver.enclosingElement, name, |
| 4046 MessageKind.CANNOT_RESOLVE, | 4061 name.source, |
| 4047 {'name': name}); | 4062 MessageKind.CANNOT_RESOLVE, |
| 4063 {'name': name}); | |
| 4048 } else if (!identical(e.kind, ElementKind.CLASS)) { | 4064 } else if (!identical(e.kind, ElementKind.CLASS)) { |
| 4049 error(node, MessageKind.NOT_A_TYPE, {'node': name}); | 4065 error(node, MessageKind.NOT_A_TYPE.error, {'node': name}); |
| 4050 } | 4066 } |
| 4051 } else { | 4067 } else { |
| 4052 internalError(node.receiver, 'unexpected element $e'); | 4068 internalError(node.receiver, 'unexpected element $e'); |
| 4053 } | 4069 } |
| 4054 return e; | 4070 return e; |
| 4055 } | 4071 } |
| 4056 | 4072 |
| 4057 Element visitIdentifier(Identifier node) { | 4073 Element visitIdentifier(Identifier node) { |
| 4058 SourceString name = node.source; | 4074 SourceString name = node.source; |
| 4059 Element e = resolver.lookup(node, name); | 4075 Element e = resolver.lookup(node, name); |
| 4060 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. | 4076 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. |
| 4061 if (e == null) { | 4077 if (e == null) { |
| 4062 return failOrReturnErroneousElement(resolver.enclosingElement, node, name, | 4078 return failOrReturnErroneousElement(resolver.enclosingElement, node, name, |
| 4063 MessageKind.CANNOT_RESOLVE, | 4079 MessageKind.CANNOT_RESOLVE, |
| 4064 {'name': name}); | 4080 {'name': name}); |
| 4065 } else if (e.isErroneous()) { | 4081 } else if (e.isErroneous()) { |
| 4066 return e; | 4082 return e; |
| 4067 } else if (identical(e.kind, ElementKind.TYPEDEF)) { | 4083 } else if (identical(e.kind, ElementKind.TYPEDEF)) { |
| 4068 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, | 4084 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, |
| 4069 {'typedefName': name}); | 4085 {'typedefName': name}); |
| 4070 } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) { | 4086 } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) { |
| 4071 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, | 4087 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, |
| 4072 {'typeVariableName': name}); | 4088 {'typeVariableName': name}); |
| 4073 } else if (!identical(e.kind, ElementKind.CLASS) | 4089 } else if (!identical(e.kind, ElementKind.CLASS) |
| 4074 && !identical(e.kind, ElementKind.PREFIX)) { | 4090 && !identical(e.kind, ElementKind.PREFIX)) { |
| 4075 error(node, MessageKind.NOT_A_TYPE, {'node': name}); | 4091 error(node, MessageKind.NOT_A_TYPE.error, {'node': name}); |
| 4076 } | 4092 } |
| 4077 return e; | 4093 return e; |
| 4078 } | 4094 } |
| 4079 | 4095 |
| 4080 /// Assumed to be called by [resolveRedirectingFactory]. | 4096 /// Assumed to be called by [resolveRedirectingFactory]. |
| 4081 Element visitReturn(Return node) { | 4097 Element visitReturn(Return node) { |
| 4082 Node expression = node.expression; | 4098 Node expression = node.expression; |
| 4083 return finishConstructorReference(visit(expression), | 4099 return finishConstructorReference(visit(expression), |
| 4084 expression, expression); | 4100 expression, expression); |
| 4085 } | 4101 } |
| 4086 } | 4102 } |
| OLD | NEW |