| 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 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 use, | 661 use, |
| 662 MessageKind.ILLEGAL_MIXIN_SUPER_USE); | 662 MessageKind.ILLEGAL_MIXIN_SUPER_USE); |
| 663 } | 663 } |
| 664 } | 664 } |
| 665 | 665 |
| 666 void checkClassMembers(ClassElement cls) { | 666 void checkClassMembers(ClassElement cls) { |
| 667 assert(invariant(cls, cls.isDeclaration)); | 667 assert(invariant(cls, cls.isDeclaration)); |
| 668 if (cls.isObject(compiler)) return; | 668 if (cls.isObject(compiler)) return; |
| 669 // TODO(johnniwinther): Should this be done on the implementation element as | 669 // TODO(johnniwinther): Should this be done on the implementation element as |
| 670 // well? | 670 // well? |
| 671 List<Element> constConstructors = <Element>[]; |
| 672 List<Element> nonFinalInstanceFields = <Element>[]; |
| 671 cls.forEachMember((holder, member) { | 673 cls.forEachMember((holder, member) { |
| 672 compiler.withCurrentElement(member, () { | 674 compiler.withCurrentElement(member, () { |
| 673 // Perform various checks as side effect of "computing" the type. | 675 // Perform various checks as side effect of "computing" the type. |
| 674 member.computeType(compiler); | 676 member.computeType(compiler); |
| 675 | 677 |
| 676 // Check modifiers. | 678 // Check modifiers. |
| 677 if (member.isFunction() && member.modifiers.isFinal()) { | 679 if (member.isFunction() && member.modifiers.isFinal()) { |
| 678 compiler.reportError( | 680 compiler.reportError( |
| 679 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 681 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
| 680 } | 682 } |
| 681 if (member.isConstructor()) { | 683 if (member.isConstructor()) { |
| 682 final mismatchedFlagsBits = | 684 final mismatchedFlagsBits = |
| 683 member.modifiers.flags & | 685 member.modifiers.flags & |
| 684 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 686 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
| 685 if (mismatchedFlagsBits != 0) { | 687 if (mismatchedFlagsBits != 0) { |
| 686 final mismatchedFlags = | 688 final mismatchedFlags = |
| 687 new Modifiers.withFlags(null, mismatchedFlagsBits); | 689 new Modifiers.withFlags(null, mismatchedFlagsBits); |
| 688 compiler.reportError( | 690 compiler.reportError( |
| 689 member, | 691 member, |
| 690 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, | 692 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, |
| 691 {'modifiers': mismatchedFlags}); | 693 {'modifiers': mismatchedFlags}); |
| 692 } | 694 } |
| 695 if (member.modifiers.isConst()) { |
| 696 constConstructors.add(member); |
| 697 } |
| 698 } |
| 699 if (member.isField()) { |
| 700 if (!member.modifiers.isStatic() && |
| 701 !member.modifiers.isFinal()) { |
| 702 nonFinalInstanceFields.add(member); |
| 703 } |
| 693 } | 704 } |
| 694 checkAbstractField(member); | 705 checkAbstractField(member); |
| 695 checkValidOverride(member, cls.lookupSuperMember(member.name)); | 706 checkValidOverride(member, cls.lookupSuperMember(member.name)); |
| 696 checkUserDefinableOperator(member); | 707 checkUserDefinableOperator(member); |
| 697 }); | 708 }); |
| 698 }); | 709 }); |
| 710 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { |
| 711 Spannable span = constConstructors.length > 1 |
| 712 ? cls : constConstructors[0]; |
| 713 compiler.reportError(span, |
| 714 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, |
| 715 {'className': cls.name}); |
| 716 if (constConstructors.length > 1) { |
| 717 for (Element constructor in constConstructors) { |
| 718 compiler.reportInfo(constructor, |
| 719 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR); |
| 720 } |
| 721 } |
| 722 for (Element field in nonFinalInstanceFields) { |
| 723 compiler.reportInfo(field, |
| 724 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD); |
| 725 } |
| 726 } |
| 699 } | 727 } |
| 700 | 728 |
| 701 void checkAbstractField(Element member) { | 729 void checkAbstractField(Element member) { |
| 702 // Only check for getters. The test can only fail if there is both a setter | 730 // Only check for getters. The test can only fail if there is both a setter |
| 703 // and a getter with the same name, and we only need to check each abstract | 731 // and a getter with the same name, and we only need to check each abstract |
| 704 // field once, so we just ignore setters. | 732 // field once, so we just ignore setters. |
| 705 if (!member.isGetter()) return; | 733 if (!member.isGetter()) return; |
| 706 | 734 |
| 707 // Find the associated abstract field. | 735 // Find the associated abstract field. |
| 708 ClassElement classElement = member.getEnclosingClass(); | 736 ClassElement classElement = member.getEnclosingClass(); |
| (...skipping 2007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2716 if (!symbolValidationPattern.hasMatch(name)) { | 2744 if (!symbolValidationPattern.hasMatch(name)) { |
| 2717 if (reportError) { | 2745 if (reportError) { |
| 2718 compiler.reportError(node, MessageKind.INVALID_SYMBOL, | 2746 compiler.reportError(node, MessageKind.INVALID_SYMBOL, |
| 2719 {'value': name}); | 2747 {'value': name}); |
| 2720 } | 2748 } |
| 2721 return false; | 2749 return false; |
| 2722 } | 2750 } |
| 2723 return true; | 2751 return true; |
| 2724 } | 2752 } |
| 2725 | 2753 |
| 2726 | |
| 2727 /** | 2754 /** |
| 2728 * Try to resolve the constructor that is referred to by [node]. | 2755 * Try to resolve the constructor that is referred to by [node]. |
| 2729 * Note: this function may return an ErroneousFunctionElement instead of | 2756 * Note: this function may return an ErroneousFunctionElement instead of |
| 2730 * [null], if there is no corresponding constructor, class or library. | 2757 * [null], if there is no corresponding constructor, class or library. |
| 2731 */ | 2758 */ |
| 2732 FunctionElement resolveConstructor(NewExpression node) { | 2759 FunctionElement resolveConstructor(NewExpression node) { |
| 2733 return node.accept(new ConstructorResolver(compiler, this)); | 2760 return node.accept(new ConstructorResolver(compiler, this)); |
| 2734 } | 2761 } |
| 2735 | 2762 |
| 2736 FunctionElement resolveRedirectingFactory(Return node) { | 2763 FunctionElement resolveRedirectingFactory(Return node) { |
| (...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4122 return e; | 4149 return e; |
| 4123 } | 4150 } |
| 4124 | 4151 |
| 4125 /// Assumed to be called by [resolveRedirectingFactory]. | 4152 /// Assumed to be called by [resolveRedirectingFactory]. |
| 4126 Element visitReturn(Return node) { | 4153 Element visitReturn(Return node) { |
| 4127 Node expression = node.expression; | 4154 Node expression = node.expression; |
| 4128 return finishConstructorReference(visit(expression), | 4155 return finishConstructorReference(visit(expression), |
| 4129 expression, expression); | 4156 expression, expression); |
| 4130 } | 4157 } |
| 4131 } | 4158 } |
| OLD | NEW |