| 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 | 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |