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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/resolution/members.dart

Issue 23533040: Check for non-final field in the face of const constructors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of resolution; 5 part of resolution;
6 6
7 abstract class TreeElements { 7 abstract class TreeElements {
8 Element get currentElement; 8 Element get currentElement;
9 Set<Node> get superUses; 9 Set<Node> get superUses;
10 10
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 } 329 }
330 330
331 TreeElements resolveMethodElement(FunctionElement element) { 331 TreeElements resolveMethodElement(FunctionElement element) {
332 assert(invariant(element, element.isDeclaration)); 332 assert(invariant(element, element.isDeclaration));
333 return compiler.withCurrentElement(element, () { 333 return compiler.withCurrentElement(element, () {
334 bool isConstructor = 334 bool isConstructor =
335 identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR); 335 identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR);
336 TreeElements elements = 336 TreeElements elements =
337 compiler.enqueuer.resolution.getCachedElements(element); 337 compiler.enqueuer.resolution.getCachedElements(element);
338 if (elements != null) { 338 if (elements != null) {
339 assert(isConstructor); 339 assert(isConstructor || element.isFactoryConstructor());
karlklose 2013/09/05 12:43:42 Remember to remove this when rebasing with my chan
Johnni Winther 2013/09/06 06:22:41 Done.
340 return elements; 340 return elements;
341 } 341 }
342 if (element.isSynthesized) { 342 if (element.isSynthesized) {
343 Element target = element.targetConstructor; 343 Element target = element.targetConstructor;
344 // Ensure the signature of the synthesized element is 344 // Ensure the signature of the synthesized element is
345 // resolved. This is the only place where the resolver is 345 // resolved. This is the only place where the resolver is
346 // seeing this element. 346 // seeing this element.
347 element.computeSignature(compiler); 347 element.computeSignature(compiler);
348 if (!target.isErroneous()) { 348 if (!target.isErroneous()) {
349 compiler.enqueuer.resolution.registerStaticUse( 349 compiler.enqueuer.resolution.registerStaticUse(
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 use, 655 use,
656 MessageKind.ILLEGAL_MIXIN_SUPER_USE); 656 MessageKind.ILLEGAL_MIXIN_SUPER_USE);
657 } 657 }
658 } 658 }
659 659
660 void checkClassMembers(ClassElement cls) { 660 void checkClassMembers(ClassElement cls) {
661 assert(invariant(cls, cls.isDeclaration)); 661 assert(invariant(cls, cls.isDeclaration));
662 if (cls.isObject(compiler)) return; 662 if (cls.isObject(compiler)) return;
663 // TODO(johnniwinther): Should this be done on the implementation element as 663 // TODO(johnniwinther): Should this be done on the implementation element as
664 // well? 664 // well?
665 List<Element> constConstructors = <Element>[];
666 List<Element> nonFinalInstanceFields = <Element>[];
665 cls.forEachMember((holder, member) { 667 cls.forEachMember((holder, member) {
666 compiler.withCurrentElement(member, () { 668 compiler.withCurrentElement(member, () {
667 // Perform various checks as side effect of "computing" the type. 669 // Perform various checks as side effect of "computing" the type.
668 member.computeType(compiler); 670 member.computeType(compiler);
669 671
670 // Check modifiers. 672 // Check modifiers.
671 if (member.isFunction() && member.modifiers.isFinal()) { 673 if (member.isFunction() && member.modifiers.isFinal()) {
672 compiler.reportError( 674 compiler.reportError(
673 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); 675 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER);
674 } 676 }
675 if (member.isConstructor()) { 677 if (member.isConstructor()) {
676 final mismatchedFlagsBits = 678 final mismatchedFlagsBits =
677 member.modifiers.flags & 679 member.modifiers.flags &
678 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); 680 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT);
679 if (mismatchedFlagsBits != 0) { 681 if (mismatchedFlagsBits != 0) {
680 final mismatchedFlags = 682 final mismatchedFlags =
681 new Modifiers.withFlags(null, mismatchedFlagsBits); 683 new Modifiers.withFlags(null, mismatchedFlagsBits);
682 compiler.reportError( 684 compiler.reportError(
683 member, 685 member,
684 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, 686 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS,
685 {'modifiers': mismatchedFlags}); 687 {'modifiers': mismatchedFlags});
686 } 688 }
689 if (member.modifiers.isConst()) {
690 constConstructors.add(member);
691 }
692 }
693 if (member.isField()) {
694 if (!member.modifiers.isStatic() &&
695 !member.modifiers.isFinal()) {
696 nonFinalInstanceFields.add(member);
697 }
687 } 698 }
688 checkAbstractField(member); 699 checkAbstractField(member);
689 checkValidOverride(member, cls.lookupSuperMember(member.name)); 700 checkValidOverride(member, cls.lookupSuperMember(member.name));
690 checkUserDefinableOperator(member); 701 checkUserDefinableOperator(member);
691 }); 702 });
692 }); 703 });
704 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) {
705 if (constConstructors.length == 1) {
706 compiler.reportError(constConstructors[0],
707 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
708 {'className': cls.name});
709 } else {
710 compiler.reportError(cls,
karlklose 2013/09/05 12:43:42 Move the call out of the if and compute the Spanna
Johnni Winther 2013/09/06 06:22:41 Done.
711 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
712 {'className': cls.name});
713 for (Element constructor in constConstructors) {
714 compiler.reportInfo(constructor,
715 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR);
716 }
717 }
718 for (Element field in nonFinalInstanceFields) {
719 compiler.reportInfo(field,
720 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD);
721 }
722 }
693 } 723 }
694 724
695 void checkAbstractField(Element member) { 725 void checkAbstractField(Element member) {
696 // Only check for getters. The test can only fail if there is both a setter 726 // Only check for getters. The test can only fail if there is both a setter
697 // and a getter with the same name, and we only need to check each abstract 727 // and a getter with the same name, and we only need to check each abstract
698 // field once, so we just ignore setters. 728 // field once, so we just ignore setters.
699 if (!member.isGetter()) return; 729 if (!member.isGetter()) return;
700 730
701 // Find the associated abstract field. 731 // Find the associated abstract field.
702 ClassElement classElement = member.getEnclosingClass(); 732 ClassElement classElement = member.getEnclosingClass();
(...skipping 2005 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 if (!symbolValidationPattern.hasMatch(name)) { 2738 if (!symbolValidationPattern.hasMatch(name)) {
2709 if (reportError) { 2739 if (reportError) {
2710 compiler.reportError(node, MessageKind.INVALID_SYMBOL, 2740 compiler.reportError(node, MessageKind.INVALID_SYMBOL,
2711 {'value': name}); 2741 {'value': name});
2712 } 2742 }
2713 return false; 2743 return false;
2714 } 2744 }
2715 return true; 2745 return true;
2716 } 2746 }
2717 2747
2718
2719 /** 2748 /**
2720 * Try to resolve the constructor that is referred to by [node]. 2749 * Try to resolve the constructor that is referred to by [node].
2721 * Note: this function may return an ErroneousFunctionElement instead of 2750 * Note: this function may return an ErroneousFunctionElement instead of
2722 * [null], if there is no corresponding constructor, class or library. 2751 * [null], if there is no corresponding constructor, class or library.
2723 */ 2752 */
2724 FunctionElement resolveConstructor(NewExpression node) { 2753 FunctionElement resolveConstructor(NewExpression node) {
2725 return node.accept(new ConstructorResolver(compiler, this)); 2754 return node.accept(new ConstructorResolver(compiler, this));
2726 } 2755 }
2727 2756
2728 FunctionElement resolveRedirectingFactory(Return node) { 2757 FunctionElement resolveRedirectingFactory(Return node) {
(...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after
4114 return e; 4143 return e;
4115 } 4144 }
4116 4145
4117 /// Assumed to be called by [resolveRedirectingFactory]. 4146 /// Assumed to be called by [resolveRedirectingFactory].
4118 Element visitReturn(Return node) { 4147 Element visitReturn(Return node) {
4119 Node expression = node.expression; 4148 Node expression = node.expression;
4120 return finishConstructorReference(visit(expression), 4149 return finishConstructorReference(visit(expression),
4121 expression, expression); 4150 expression, expression);
4122 } 4151 }
4123 } 4152 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698