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

Side by Side Diff: compiler/java/com/google/dart/compiler/resolver/Resolver.java

Issue 9081001: Issue 991: Missing compiler errors for uninitialized final fields (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Nits for Eric Created 8 years, 11 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
« no previous file with comments | « no previous file | compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 package com.google.dart.compiler.resolver; 5 package com.google.dart.compiler.resolver;
6 6
7 import com.google.common.annotations.VisibleForTesting; 7 import com.google.common.annotations.VisibleForTesting;
8 import com.google.common.collect.Sets; 8 import com.google.common.collect.Sets;
9 import com.google.dart.compiler.DartCompilationPhase; 9 import com.google.dart.compiler.DartCompilationPhase;
10 import com.google.dart.compiler.DartCompilerContext; 10 import com.google.dart.compiler.DartCompilerContext;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 @VisibleForTesting 170 @VisibleForTesting
171 public class ResolveElementsVisitor extends ResolveVisitor { 171 public class ResolveElementsVisitor extends ResolveVisitor {
172 private EnclosingElement currentHolder; 172 private EnclosingElement currentHolder;
173 private MethodElement currentMethod; 173 private MethodElement currentMethod;
174 private boolean inInitializer; 174 private boolean inInitializer;
175 private MethodElement innermostFunction; 175 private MethodElement innermostFunction;
176 private ResolutionContext context; 176 private ResolutionContext context;
177 private LabelElement currentLabel; 177 private LabelElement currentLabel;
178 private Set<LabelElement> referencedLabels = Sets.newHashSet(); 178 private Set<LabelElement> referencedLabels = Sets.newHashSet();
179 private Set<LabelElement> labelsInScopes = Sets.newHashSet(); 179 private Set<LabelElement> labelsInScopes = Sets.newHashSet();
180 private Set<String> finalsNeedingInitializing = Sets.newHashSet();
180 181
181 @VisibleForTesting 182 @VisibleForTesting
182 public ResolveElementsVisitor(ResolutionContext context, 183 public ResolveElementsVisitor(ResolutionContext context,
183 EnclosingElement currentHolder, 184 EnclosingElement currentHolder,
184 MethodElement currentMethod) { 185 MethodElement currentMethod) {
185 super(typeProvider); 186 super(typeProvider);
186 this.context = context; 187 this.context = context;
187 this.currentMethod = currentMethod; 188 this.currentMethod = currentMethod;
188 this.innermostFunction = currentMethod; 189 this.innermostFunction = currentMethod;
189 this.currentHolder = currentHolder; 190 this.currentHolder = currentHolder;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 } 234 }
234 235
235 checkClassTypeVariables(classElement); 236 checkClassTypeVariables(classElement);
236 237
237 // Push new resolution context. 238 // Push new resolution context.
238 ResolutionContext previousContext = context; 239 ResolutionContext previousContext = context;
239 EnclosingElement previousHolder = currentHolder; 240 EnclosingElement previousHolder = currentHolder;
240 currentHolder = classElement; 241 currentHolder = classElement;
241 context = topLevelContext.extend(classElement); 242 context = topLevelContext.extend(classElement);
242 243
244 this.finalsNeedingInitializing.clear();
243 for (Element element : classElement.getMembers()) { 245 for (Element element : classElement.getMembers()) {
244 element.getNode().accept(this); 246 element.getNode().accept(this);
245 } 247 }
246 248
247 for (Element element : classElement.getConstructors()) { 249 for (Element element : classElement.getConstructors()) {
248 element.getNode().accept(this); 250 element.getNode().accept(this);
249 } 251 }
250 252
251 checkRedirectConstructorCycle(classElement.getConstructors(), context); 253 checkRedirectConstructorCycle(classElement.getConstructors(), context);
252 if (Elements.needsImplicitDefaultConstructor(classElement)) { 254 if (Elements.needsImplicitDefaultConstructor(classElement)) {
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 @Override 519 @Override
518 public MethodElement visitMethodDefinition(DartMethodDefinition node) { 520 public MethodElement visitMethodDefinition(DartMethodDefinition node) {
519 MethodElement member = node.getSymbol(); 521 MethodElement member = node.getSymbol();
520 ResolutionContext previousContext = context; 522 ResolutionContext previousContext = context;
521 context = context.extend(member.getName()); 523 context = context.extend(member.getName());
522 assert currentMethod == null : "Nested methods?"; 524 assert currentMethod == null : "Nested methods?";
523 innermostFunction = currentMethod = member; 525 innermostFunction = currentMethod = member;
524 526
525 DartFunction functionNode = node.getFunction(); 527 DartFunction functionNode = node.getFunction();
526 List<DartParameter> parameters = functionNode.getParams(); 528 List<DartParameter> parameters = functionNode.getParams();
529 Set<String> initalizedFinals = Sets.newHashSet();
527 530
528 // First declare all normal parameters in the scope, putting them in the 531 // First declare all normal parameters in the scope, putting them in the
529 // scope of the default expressions so we can report better errors. 532 // scope of the default expressions so we can report better errors.
530 for (DartParameter parameter : parameters) { 533 for (DartParameter parameter : parameters) {
531 assert parameter.getSymbol() != null; 534 assert parameter.getSymbol() != null;
532 if (parameter.getQualifier() instanceof DartThisExpression) { 535 if (parameter.getQualifier() instanceof DartThisExpression) {
533 checkParameterInitializer(node, parameter); 536 checkParameterInitializer(node, parameter);
537 if (!initalizedFinals.add(parameter.getParameterName())) {
538 onError(parameter, ResolverErrorCode.DUPLICATE_PARAMETER, parameter. getName());
539 }
534 } else { 540 } else {
535 getContext().declare( 541 getContext().declare(
536 parameter.getSymbol(), 542 parameter.getSymbol(),
537 ResolverErrorCode.DUPLICATE_PARAMETER, 543 ResolverErrorCode.DUPLICATE_PARAMETER,
538 ResolverErrorCode.DUPLICATE_PARAMETER_WARNING); 544 ResolverErrorCode.DUPLICATE_PARAMETER_WARNING);
539 } 545 }
540 } 546 }
541 for (DartParameter parameter : parameters) { 547 for (DartParameter parameter : parameters) {
542 // Then resolve the default values. 548 // Then resolve the default values.
543 resolve(parameter.getDefaultExpr()); 549 resolve(parameter.getDefaultExpr());
544 } 550 }
545 551
546 if ((functionNode.getBody() == null) 552 if ((functionNode.getBody() == null)
547 && !Elements.isNonFactoryConstructor(member) 553 && !Elements.isNonFactoryConstructor(member)
548 && !member.getModifiers().isAbstract() 554 && !member.getModifiers().isAbstract()
549 && !member.getEnclosingElement().isInterface()) { 555 && !member.getEnclosingElement().isInterface()) {
550 onError(functionNode, ResolverErrorCode.METHOD_MUST_HAVE_BODY); 556 onError(functionNode, ResolverErrorCode.METHOD_MUST_HAVE_BODY);
551 } 557 }
552 resolve(functionNode.getBody()); 558 resolve(functionNode.getBody());
553 559
554 if (Elements.isNonFactoryConstructor(member)) { 560 if (Elements.isNonFactoryConstructor(member)) {
555 resolveInitializers(node); 561 resolveInitializers(node, initalizedFinals);
562 // Test for missing final initialized fields
563 if (!this.currentHolder.isInterface() && !member.getModifiers().isRedire ctedConstructor()
564 && !finalsNeedingInitializing.equals(initalizedFinals)) {
565 for (String field : this.finalsNeedingInitializing) {
566 if (!initalizedFinals.contains(field)) {
567 onError(node.getName(), ResolverErrorCode.FINAL_FIELD_MUST_BE_INIT IALIZED, field);
568 }
569 }
570 }
556 } 571 }
557 572
558 // If this method is an override, make sure its signature roughly matches any superclass 573 // If this method is an override, make sure its signature roughly matches any superclass
559 // declaration. 574 // declaration.
560 if (ElementKind.of(currentHolder).equals(ElementKind.CLASS)) { 575 if (ElementKind.of(currentHolder).equals(ElementKind.CLASS)) {
561 // Look for this method in super implementations. 576 // Look for this method in super implementations.
562 ClassElement classElement = (ClassElement) currentHolder; 577 ClassElement classElement = (ClassElement) currentHolder;
563 try { 578 try {
564 for (InterfaceType supertype : classElement.getAllSupertypes()) { 579 for (InterfaceType supertype : classElement.getAllSupertypes()) {
565 Member superMember = supertype.lookupMember(member.getName()); 580 Member superMember = supertype.lookupMember(member.getName());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 modifiers.makeStatic(); 651 modifiers.makeStatic();
637 } 652 }
638 653
639 if (expression != null) { 654 if (expression != null) {
640 resolve(expression); 655 resolve(expression);
641 // Now, this constant has a type. Save it for future reference. 656 // Now, this constant has a type. Save it for future reference.
642 Element element = node.getSymbol(); 657 Element element = node.getSymbol();
643 if (expression.getType() != null) { 658 if (expression.getType() != null) {
644 Elements.setType(element, expression.getType()); 659 Elements.setType(element, expression.getType());
645 } 660 }
646 } else if (isStatic && isFinal) { 661 } else if (isFinal) {
647 onError(node, ResolverErrorCode.STATIC_FINAL_REQUIRES_VALUE); 662 if (isStatic) {
663 onError(node, ResolverErrorCode.STATIC_FINAL_REQUIRES_VALUE);
664 } else {
665 // If a final instance field wasn't initialized at declaration, we mus t check
666 // at construction time.
667 this.finalsNeedingInitializing.add(node.getName().getTargetName());
668 }
648 } 669 }
649 670
650 // If field is an accessor, both getter and setter need to be visited (if present). 671 // If field is an accessor, both getter and setter need to be visited (if present).
651 FieldElement field = node.getSymbol(); 672 FieldElement field = node.getSymbol();
652 if (field.getGetter() != null) { 673 if (field.getGetter() != null) {
653 resolve(field.getGetter().getNode()); 674 resolve(field.getGetter().getNode());
654 } 675 }
655 if (field.getSetter() != null) { 676 if (field.getSetter() != null) {
656 resolve(field.getSetter().getNode()); 677 resolve(field.getSetter().getNode());
657 } 678 }
(...skipping 1014 matching lines...) Expand 10 before | Expand all | Expand 10 after
1672 // If no type specified, use type of field. 1693 // If no type specified, use type of field.
1673 if (parameter.getTypeNode() == null && element != null) { 1694 if (parameter.getTypeNode() == null && element != null) {
1674 Elements.setType(parameter.getSymbol(), element.getType()); 1695 Elements.setType(parameter.getSymbol(), element.getType());
1675 } 1696 }
1676 } else { 1697 } else {
1677 onError(parameter.getName(), 1698 onError(parameter.getName(),
1678 ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR); 1699 ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR);
1679 } 1700 }
1680 } 1701 }
1681 1702
1682 private void resolveInitializers(DartMethodDefinition node) { 1703 private void resolveInitializers(DartMethodDefinition node, Set<String> inti alizedFields) {
1683 Iterator<DartInitializer> initializers = node.getInitializers().iterator() ; 1704 Iterator<DartInitializer> initializers = node.getInitializers().iterator() ;
1684 ConstructorElement constructorElement = null; 1705 ConstructorElement constructorElement = null;
1685 while (initializers.hasNext()) { 1706 while (initializers.hasNext()) {
1686 DartInitializer initializer = initializers.next(); 1707 DartInitializer initializer = initializers.next();
1687 Element element = resolve(initializer); 1708 Element element = resolve(initializer);
1688 if ((ElementKind.of(element) == ElementKind.CONSTRUCTOR) && initializer. isInvocation()) { 1709 if ((ElementKind.of(element) == ElementKind.CONSTRUCTOR) && initializer. isInvocation()) {
1689 constructorElement = (ConstructorElement) element; 1710 constructorElement = (ConstructorElement) element;
1711 } else if (initializer.getName() != null && initializer.getName().getSym bol() != null
1712 && initializer.getName().getSymbol().getModifiers() != null
1713 && initializer.getName().getSymbol().getModifiers().isFinal()
1714 && !intializedFields.add(initializer.getName().getTargetName())) {
1715 onError(initializer, ResolverErrorCode.DUPLICATE_PARAMETER, initialize r.getName());
1690 } 1716 }
1691 } 1717 }
1692 1718
1693 checkConstructor(node, constructorElement); 1719 checkConstructor(node, constructorElement);
1694 } 1720 }
1695 1721
1696 private void onError(DartNode node, ErrorCode errorCode, Object... arguments ) { 1722 private void onError(DartNode node, ErrorCode errorCode, Object... arguments ) {
1697 context.onError(node, errorCode, arguments); 1723 context.onError(node, errorCode, arguments);
1698 } 1724 }
1699 1725
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1771 ClassElement nextClass = (ClassElement) nextConstructorElement.getEnclos ingElement(); 1797 ClassElement nextClass = (ClassElement) nextConstructorElement.getEnclos ingElement();
1772 ClassElement currentClass = (ClassElement) constructor.getEnclosingEleme nt(); 1798 ClassElement currentClass = (ClassElement) constructor.getEnclosingEleme nt();
1773 if (nextClass.getName().equals(currentClass.getName())) { 1799 if (nextClass.getName().equals(currentClass.getName())) {
1774 return nextConstructorElement; 1800 return nextConstructorElement;
1775 } 1801 }
1776 } 1802 }
1777 } 1803 }
1778 return null; 1804 return null;
1779 } 1805 }
1780 } 1806 }
OLDNEW
« no previous file with comments | « no previous file | compiler/java/com/google/dart/compiler/resolver/ResolverErrorCode.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698