| OLD | NEW |
| 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 Loading... |
| 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 private Set<FieldElement> finalsNeedingInitializing = Sets.newHashSet(); |
| 181 | 181 |
| 182 @VisibleForTesting | 182 @VisibleForTesting |
| 183 public ResolveElementsVisitor(ResolutionContext context, | 183 public ResolveElementsVisitor(ResolutionContext context, |
| 184 EnclosingElement currentHolder, | 184 EnclosingElement currentHolder, |
| 185 MethodElement currentMethod) { | 185 MethodElement currentMethod) { |
| 186 super(typeProvider); | 186 super(typeProvider); |
| 187 this.context = context; | 187 this.context = context; |
| 188 this.currentMethod = currentMethod; | 188 this.currentMethod = currentMethod; |
| 189 this.innermostFunction = currentMethod; | 189 this.innermostFunction = currentMethod; |
| 190 this.currentHolder = currentHolder; | 190 this.currentHolder = currentHolder; |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 @Override | 552 @Override |
| 553 public MethodElement visitMethodDefinition(DartMethodDefinition node) { | 553 public MethodElement visitMethodDefinition(DartMethodDefinition node) { |
| 554 MethodElement member = node.getSymbol(); | 554 MethodElement member = node.getSymbol(); |
| 555 ResolutionContext previousContext = context; | 555 ResolutionContext previousContext = context; |
| 556 context = context.extend(member.getName()); | 556 context = context.extend(member.getName()); |
| 557 assert currentMethod == null : "Nested methods?"; | 557 assert currentMethod == null : "Nested methods?"; |
| 558 innermostFunction = currentMethod = member; | 558 innermostFunction = currentMethod = member; |
| 559 | 559 |
| 560 DartFunction functionNode = node.getFunction(); | 560 DartFunction functionNode = node.getFunction(); |
| 561 List<DartParameter> parameters = functionNode.getParams(); | 561 List<DartParameter> parameters = functionNode.getParams(); |
| 562 Set<String> initalizedFinals = Sets.newHashSet(); | 562 Set<FieldElement> initializedFields = Sets.newHashSet(); |
| 563 | 563 |
| 564 // First declare all normal parameters in the scope, putting them in the | 564 // First declare all normal parameters in the scope, putting them in the |
| 565 // scope of the default expressions so we can report better errors. | 565 // scope of the default expressions so we can report better errors. |
| 566 for (DartParameter parameter : parameters) { | 566 for (DartParameter parameter : parameters) { |
| 567 assert parameter.getSymbol() != null; | 567 assert parameter.getSymbol() != null; |
| 568 if (parameter.getQualifier() instanceof DartThisExpression) { | 568 if (parameter.getQualifier() instanceof DartThisExpression) { |
| 569 checkParameterInitializer(node, parameter); | 569 checkParameterInitializer(node, parameter); |
| 570 if (!initalizedFinals.add(parameter.getParameterName())) { | |
| 571 onError(parameter, ResolverErrorCode.DUPLICATE_PARAMETER, parameter.
getName()); | |
| 572 } | |
| 573 } else { | 570 } else { |
| 574 getContext().declare( | 571 getContext().declare( |
| 575 parameter.getSymbol(), | 572 parameter.getSymbol(), |
| 576 ResolverErrorCode.DUPLICATE_PARAMETER, | 573 ResolverErrorCode.DUPLICATE_PARAMETER, |
| 577 ResolverErrorCode.DUPLICATE_PARAMETER_WARNING); | 574 ResolverErrorCode.DUPLICATE_PARAMETER_WARNING); |
| 578 } | 575 } |
| 579 } | 576 } |
| 580 for (DartParameter parameter : parameters) { | 577 for (DartParameter parameter : parameters) { |
| 581 // Then resolve the default values. | 578 // Then resolve the default values. |
| 582 resolve(parameter.getDefaultExpr()); | 579 resolve(parameter.getDefaultExpr()); |
| 580 if (parameter.getQualifier() instanceof DartThisExpression && parameter.
getSymbol() != null |
| 581 && !initializedFields.add(parameter.getSymbol().getParameterInitiali
zerElement())) { |
| 582 onError(parameter, ResolverErrorCode.DUPLICATE_INITIALIZATION, paramet
er.getName()); |
| 583 } |
| 583 } | 584 } |
| 584 | 585 |
| 585 if ((functionNode.getBody() == null) | 586 if ((functionNode.getBody() == null) |
| 586 && !Elements.isNonFactoryConstructor(member) | 587 && !Elements.isNonFactoryConstructor(member) |
| 587 && !member.getModifiers().isAbstract() | 588 && !member.getModifiers().isAbstract() |
| 588 && !member.getEnclosingElement().isInterface()) { | 589 && !member.getEnclosingElement().isInterface()) { |
| 589 onError(functionNode, ResolverErrorCode.METHOD_MUST_HAVE_BODY); | 590 onError(functionNode, ResolverErrorCode.METHOD_MUST_HAVE_BODY); |
| 590 } | 591 } |
| 591 resolve(functionNode.getBody()); | 592 resolve(functionNode.getBody()); |
| 592 | 593 |
| 593 if (Elements.isNonFactoryConstructor(member)) { | 594 if (Elements.isNonFactoryConstructor(member)) { |
| 594 resolveInitializers(node, initalizedFinals); | 595 resolveInitializers(node, initializedFields); |
| 595 // Test for missing final initialized fields | 596 // Test for missing final initialized fields |
| 596 if (!this.currentHolder.isInterface() && !member.getModifiers().isRedire
ctedConstructor() | 597 if (!this.currentHolder.isInterface() && !member.getModifiers().isRedire
ctedConstructor()) { |
| 597 && !finalsNeedingInitializing.equals(initalizedFinals)) { | 598 for (FieldElement finalField : this.finalsNeedingInitializing) { |
| 598 for (String field : this.finalsNeedingInitializing) { | 599 if (!initializedFields.contains(finalField)) { |
| 599 if (!initalizedFinals.contains(field)) { | 600 onError(node.getName(), ResolverErrorCode.FINAL_FIELD_MUST_BE_INIT
IALIZED, |
| 600 onError(node.getName(), ResolverErrorCode.FINAL_FIELD_MUST_BE_INIT
IALIZED, field); | 601 finalField.getName()); |
| 601 } | 602 } |
| 602 } | 603 } |
| 603 } | 604 } |
| 604 } | 605 } |
| 605 | 606 |
| 606 // If this method is an override, make sure its signature roughly matches
any superclass | 607 // If this method is an override, make sure its signature roughly matches
any superclass |
| 607 // declaration. | 608 // declaration. |
| 608 if (ElementKind.of(currentHolder).equals(ElementKind.CLASS)) { | 609 if (ElementKind.of(currentHolder).equals(ElementKind.CLASS)) { |
| 609 // Look for this method in super implementations. | 610 // Look for this method in super implementations. |
| 610 ClassElement classElement = (ClassElement) currentHolder; | 611 ClassElement classElement = (ClassElement) currentHolder; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 690 Element element = node.getSymbol(); | 691 Element element = node.getSymbol(); |
| 691 if (expression.getType() != null) { | 692 if (expression.getType() != null) { |
| 692 Elements.setType(element, expression.getType()); | 693 Elements.setType(element, expression.getType()); |
| 693 } | 694 } |
| 694 } else if (isFinal) { | 695 } else if (isFinal) { |
| 695 if (isStatic) { | 696 if (isStatic) { |
| 696 onError(node, ResolverErrorCode.STATIC_FINAL_REQUIRES_VALUE); | 697 onError(node, ResolverErrorCode.STATIC_FINAL_REQUIRES_VALUE); |
| 697 } else { | 698 } else { |
| 698 // If a final instance field wasn't initialized at declaration, we mus
t check | 699 // If a final instance field wasn't initialized at declaration, we mus
t check |
| 699 // at construction time. | 700 // at construction time. |
| 700 this.finalsNeedingInitializing.add(node.getName().getTargetName()); | 701 this.finalsNeedingInitializing.add(node.getSymbol()); |
| 701 } | 702 } |
| 702 } | 703 } |
| 703 | 704 |
| 704 // If field is an accessor, both getter and setter need to be visited (if
present). | 705 // If field is an accessor, both getter and setter need to be visited (if
present). |
| 705 FieldElement field = node.getSymbol(); | 706 FieldElement field = node.getSymbol(); |
| 706 if (field.getGetter() != null) { | 707 if (field.getGetter() != null) { |
| 707 resolve(field.getGetter().getNode()); | 708 resolve(field.getGetter().getNode()); |
| 708 } | 709 } |
| 709 if (field.getSetter() != null) { | 710 if (field.getSetter() != null) { |
| 710 resolve(field.getSetter().getNode()); | 711 resolve(field.getSetter().getNode()); |
| (...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 // If no type specified, use type of field. | 1727 // If no type specified, use type of field. |
| 1727 if (parameter.getTypeNode() == null && element != null) { | 1728 if (parameter.getTypeNode() == null && element != null) { |
| 1728 Elements.setType(parameter.getSymbol(), element.getType()); | 1729 Elements.setType(parameter.getSymbol(), element.getType()); |
| 1729 } | 1730 } |
| 1730 } else { | 1731 } else { |
| 1731 onError(parameter.getName(), | 1732 onError(parameter.getName(), |
| 1732 ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR); | 1733 ResolverErrorCode.PARAMETER_INIT_OUTSIDE_CONSTRUCTOR); |
| 1733 } | 1734 } |
| 1734 } | 1735 } |
| 1735 | 1736 |
| 1736 private void resolveInitializers(DartMethodDefinition node, Set<String> inti
alizedFields) { | 1737 private void resolveInitializers(DartMethodDefinition node, Set<FieldElement
> intializedFields) { |
| 1737 Iterator<DartInitializer> initializers = node.getInitializers().iterator()
; | 1738 Iterator<DartInitializer> initializers = node.getInitializers().iterator()
; |
| 1738 ConstructorElement constructorElement = null; | 1739 ConstructorElement constructorElement = null; |
| 1739 while (initializers.hasNext()) { | 1740 while (initializers.hasNext()) { |
| 1740 DartInitializer initializer = initializers.next(); | 1741 DartInitializer initializer = initializers.next(); |
| 1741 Element element = resolve(initializer); | 1742 Element element = resolve(initializer); |
| 1742 if ((ElementKind.of(element) == ElementKind.CONSTRUCTOR) && initializer.
isInvocation()) { | 1743 if ((ElementKind.of(element) == ElementKind.CONSTRUCTOR) && initializer.
isInvocation()) { |
| 1743 constructorElement = (ConstructorElement) element; | 1744 constructorElement = (ConstructorElement) element; |
| 1744 } else if (initializer.getName() != null && initializer.getName().getSym
bol() != null | 1745 } else if (initializer.getName() != null && initializer.getName().getSym
bol() != null |
| 1745 && initializer.getName().getSymbol().getModifiers() != null | 1746 && initializer.getName().getSymbol().getModifiers() != null |
| 1746 && initializer.getName().getSymbol().getModifiers().isFinal() | 1747 && !intializedFields.add((FieldElement)initializer.getName().getTarg
etSymbol())) { |
| 1747 && !intializedFields.add(initializer.getName().getTargetName())) { | 1748 onError(initializer, ResolverErrorCode.DUPLICATE_INITIALIZATION, initi
alizer.getName()); |
| 1748 onError(initializer, ResolverErrorCode.DUPLICATE_PARAMETER, initialize
r.getName()); | |
| 1749 } | 1749 } |
| 1750 } | 1750 } |
| 1751 | 1751 |
| 1752 checkConstructor(node, constructorElement); | 1752 checkConstructor(node, constructorElement); |
| 1753 } | 1753 } |
| 1754 | 1754 |
| 1755 private void onError(DartNode node, ErrorCode errorCode, Object... arguments
) { | 1755 private void onError(DartNode node, ErrorCode errorCode, Object... arguments
) { |
| 1756 context.onError(node, errorCode, arguments); | 1756 context.onError(node, errorCode, arguments); |
| 1757 } | 1757 } |
| 1758 | 1758 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1830 ClassElement nextClass = (ClassElement) nextConstructorElement.getEnclos
ingElement(); | 1830 ClassElement nextClass = (ClassElement) nextConstructorElement.getEnclos
ingElement(); |
| 1831 ClassElement currentClass = (ClassElement) constructor.getEnclosingEleme
nt(); | 1831 ClassElement currentClass = (ClassElement) constructor.getEnclosingEleme
nt(); |
| 1832 if (nextClass.getName().equals(currentClass.getName())) { | 1832 if (nextClass.getName().equals(currentClass.getName())) { |
| 1833 return nextConstructorElement; | 1833 return nextConstructorElement; |
| 1834 } | 1834 } |
| 1835 } | 1835 } |
| 1836 } | 1836 } |
| 1837 return null; | 1837 return null; |
| 1838 } | 1838 } |
| 1839 } | 1839 } |
| OLD | NEW |