| 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 abstract class TreeElements { | 5 abstract class TreeElements { |
| 6 Element operator[](Node node); | 6 Element operator[](Node node); |
| 7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
| 8 DartType getType(Node node); | 8 DartType getType(Node node); |
| 9 bool isParameterChecked(Element element); | 9 bool isParameterChecked(Element element); |
| 10 } | 10 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 if (identical(kind, ElementKind.PARAMETER) || | 86 if (identical(kind, ElementKind.PARAMETER) || |
| 87 identical(kind, ElementKind.FIELD_PARAMETER)) { | 87 identical(kind, ElementKind.FIELD_PARAMETER)) { |
| 88 return resolveParameter(element); | 88 return resolveParameter(element); |
| 89 } | 89 } |
| 90 | 90 |
| 91 compiler.unimplemented("resolve($element)", | 91 compiler.unimplemented("resolve($element)", |
| 92 node: element.parseNode(compiler)); | 92 node: element.parseNode(compiler)); |
| 93 }); | 93 }); |
| 94 } | 94 } |
| 95 | 95 |
| 96 bool isNamedConstructor(Send node) => node.receiver != null; | |
| 97 | |
| 98 SourceString getConstructorName(Send node) { | |
| 99 return node.selector.asIdentifier().source; | |
| 100 } | |
| 101 | |
| 102 String constructorNameForDiagnostics(SourceString className, | 96 String constructorNameForDiagnostics(SourceString className, |
| 103 SourceString constructorName) { | 97 SourceString constructorName) { |
| 104 String classNameString = className.slowToString(); | 98 String classNameString = className.slowToString(); |
| 105 String constructorNameString = constructorName.slowToString(); | 99 String constructorNameString = constructorName.slowToString(); |
| 106 return (identical(constructorName, const SourceString(''))) | 100 return (identical(constructorName, const SourceString(''))) |
| 107 ? classNameString | 101 ? classNameString |
| 108 : "$classNameString.$constructorNameString"; | 102 : "$classNameString.$constructorNameString"; |
| 109 } | 103 } |
| 110 | 104 |
| 111 FunctionElement resolveConstructorRedirection(InitializerResolver resolver, | |
| 112 FunctionElement constructor) { | |
| 113 if (constructor.isPatched) { | |
| 114 checkMatchingPatchSignatures(constructor, constructor.patch); | |
| 115 constructor = constructor.patch; | |
| 116 } | |
| 117 FunctionExpression node = constructor.parseNode(compiler); | |
| 118 | |
| 119 // A synthetic constructor does not have a node. | |
| 120 if (node == null) return null; | |
| 121 if (node.initializers == null) return null; | |
| 122 Link<Node> initializers = node.initializers.nodes; | |
| 123 if (!initializers.isEmpty && | |
| 124 Initializers.isConstructorRedirect(initializers.head)) { | |
| 125 final ClassElement classElement = constructor.getEnclosingClass(); | |
| 126 Selector selector; | |
| 127 if (isNamedConstructor(initializers.head)) { | |
| 128 SourceString constructorName = getConstructorName(initializers.head); | |
| 129 selector = new Selector.callConstructor( | |
| 130 constructorName, | |
| 131 resolver.visitor.enclosingElement.getLibrary()); | |
| 132 } else { | |
| 133 selector = new Selector.callDefaultConstructor( | |
| 134 resolver.visitor.enclosingElement.getLibrary()); | |
| 135 } | |
| 136 return classElement.lookupConstructor(selector); | |
| 137 } | |
| 138 return null; | |
| 139 } | |
| 140 | |
| 141 void resolveRedirectingConstructor(InitializerResolver resolver, | 105 void resolveRedirectingConstructor(InitializerResolver resolver, |
| 142 Node node, | 106 Node node, |
| 143 FunctionElement constructor, | 107 FunctionElement constructor, |
| 144 FunctionElement redirection) { | 108 FunctionElement redirection) { |
| 145 Set<FunctionElement> seen = new Set<FunctionElement>(); | 109 Set<FunctionElement> seen = new Set<FunctionElement>(); |
| 146 seen.add(constructor); | 110 seen.add(constructor); |
| 147 while (redirection != null) { | 111 while (redirection != null) { |
| 148 if (seen.contains(redirection)) { | 112 if (seen.contains(redirection)) { |
| 149 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 113 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
| 150 return; | 114 return; |
| 151 } | 115 } |
| 152 seen.add(redirection); | 116 seen.add(redirection); |
| 153 redirection = resolveConstructorRedirection(resolver, redirection); | 117 |
| 118 if (redirection.isPatched) { |
| 119 checkMatchingPatchSignatures(constructor, redirection.patch); |
| 120 redirection = redirection.patch; |
| 121 } |
| 122 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
| 154 } | 123 } |
| 155 } | 124 } |
| 156 | 125 |
| 157 void checkMatchingPatchParameters(FunctionElement origin, | 126 void checkMatchingPatchParameters(FunctionElement origin, |
| 158 Link<Element> originParameters, | 127 Link<Element> originParameters, |
| 159 Link<Element> patchParameters) { | 128 Link<Element> patchParameters) { |
| 160 while (!originParameters.isEmpty) { | 129 while (!originParameters.isEmpty) { |
| 161 Element originParameter = originParameters.head; | 130 Element originParameter = originParameters.head; |
| 162 Element patchParameter = patchParameters.head; | 131 Element patchParameter = patchParameters.head; |
| 163 // Hack: Use unparser to test parameter equality. This only works because | 132 // Hack: Use unparser to test parameter equality. This only works because |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 visitor.inStaticContext(() { | 716 visitor.inStaticContext(() { |
| 748 visitor.resolveSelector(call); | 717 visitor.resolveSelector(call); |
| 749 visitor.resolveArguments(call.argumentsNode); | 718 visitor.resolveArguments(call.argumentsNode); |
| 750 }); | 719 }); |
| 751 Selector selector = visitor.mapping.getSelector(call); | 720 Selector selector = visitor.mapping.getSelector(call); |
| 752 bool isSuperCall = Initializers.isSuperConstructorCall(call); | 721 bool isSuperCall = Initializers.isSuperConstructorCall(call); |
| 753 | 722 |
| 754 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, | 723 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, |
| 755 isSuperCall, | 724 isSuperCall, |
| 756 call); | 725 call); |
| 757 final SourceString className = lookupTarget.name; | 726 Selector constructorSelector = |
| 758 | 727 visitor.getRedirectingThisOrSuperConstructorSelector(call); |
| 759 SourceString constructorName; | 728 FunctionElement calledConstructor = |
| 760 Selector lookupSelector; | 729 lookupTarget.lookupConstructor(constructorSelector); |
| 761 if (resolver.isNamedConstructor(call)) { | |
| 762 constructorName = resolver.getConstructorName(call); | |
| 763 lookupSelector = new Selector.callConstructor( | |
| 764 constructorName, | |
| 765 visitor.enclosingElement.getLibrary()); | |
| 766 } else { | |
| 767 constructorName = const SourceString(''); | |
| 768 lookupSelector = new Selector.callDefaultConstructor( | |
| 769 visitor.enclosingElement.getLibrary()); | |
| 770 } | |
| 771 | |
| 772 FunctionElement lookedupConstructor = | |
| 773 lookupTarget.lookupConstructor(lookupSelector); | |
| 774 | 730 |
| 775 final bool isImplicitSuperCall = false; | 731 final bool isImplicitSuperCall = false; |
| 776 verifyThatConstructorMatchesCall(lookedupConstructor, | 732 final SourceString className = lookupTarget.name; |
| 733 verifyThatConstructorMatchesCall(calledConstructor, |
| 777 selector, | 734 selector, |
| 778 isImplicitSuperCall, | 735 isImplicitSuperCall, |
| 779 call, | 736 call, |
| 780 constructorName, | 737 className, |
| 781 className); | 738 constructorSelector); |
| 782 | 739 |
| 783 visitor.useElement(call, lookedupConstructor); | 740 visitor.useElement(call, calledConstructor); |
| 784 visitor.world.registerStaticUse(lookedupConstructor); | 741 visitor.world.registerStaticUse(calledConstructor); |
| 785 return lookedupConstructor; | 742 return calledConstructor; |
| 786 } | 743 } |
| 787 | 744 |
| 788 void resolveImplicitSuperConstructorSend(FunctionElement constructor, | 745 void resolveImplicitSuperConstructorSend(FunctionElement constructor, |
| 789 FunctionExpression functionNode) { | 746 FunctionExpression functionNode) { |
| 790 // If the class has a super resolve the implicit super call. | 747 // If the class has a super resolve the implicit super call. |
| 791 ClassElement classElement = constructor.getEnclosingClass(); | 748 ClassElement classElement = constructor.getEnclosingClass(); |
| 792 ClassElement superClass = classElement.superclass; | 749 ClassElement superClass = classElement.superclass; |
| 793 if (classElement != visitor.compiler.objectClass) { | 750 if (classElement != visitor.compiler.objectClass) { |
| 794 assert(superClass != null); | 751 assert(superClass != null); |
| 795 assert(superClass.resolutionState == STATE_DONE); | 752 assert(superClass.resolutionState == STATE_DONE); |
| 796 SourceString constructorName = const SourceString(''); | 753 SourceString constructorName = const SourceString(''); |
| 797 Selector callToMatch = new Selector.call( | 754 Selector callToMatch = new Selector.call( |
| 798 constructorName, | 755 constructorName, |
| 799 classElement.getLibrary(), | 756 classElement.getLibrary(), |
| 800 0); | 757 0); |
| 801 | 758 |
| 802 final bool isSuperCall = true; | 759 final bool isSuperCall = true; |
| 803 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, | 760 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, |
| 804 isSuperCall, | 761 isSuperCall, |
| 805 functionNode); | 762 functionNode); |
| 763 Selector constructorSelector = new Selector.callDefaultConstructor( |
| 764 visitor.enclosingElement.getLibrary()); |
| 765 Element calledConstructor = lookupTarget.lookupConstructor( |
| 766 constructorSelector); |
| 767 |
| 806 final SourceString className = lookupTarget.name; | 768 final SourceString className = lookupTarget.name; |
| 807 Element calledConstructor = lookupTarget.lookupConstructor( | |
| 808 new Selector.callDefaultConstructor( | |
| 809 visitor.enclosingElement.getLibrary())); | |
| 810 | |
| 811 final bool isImplicitSuperCall = true; | 769 final bool isImplicitSuperCall = true; |
| 812 verifyThatConstructorMatchesCall(calledConstructor, | 770 verifyThatConstructorMatchesCall(calledConstructor, |
| 813 callToMatch, | 771 callToMatch, |
| 814 isImplicitSuperCall, | 772 isImplicitSuperCall, |
| 815 functionNode, | 773 functionNode, |
| 816 className, | 774 className, |
| 817 const SourceString('')); | 775 constructorSelector); |
| 818 | 776 |
| 819 visitor.world.registerStaticUse(calledConstructor); | 777 visitor.world.registerStaticUse(calledConstructor); |
| 820 } | 778 } |
| 821 } | 779 } |
| 822 | 780 |
| 823 void verifyThatConstructorMatchesCall( | 781 void verifyThatConstructorMatchesCall( |
| 824 FunctionElement lookedupConstructor, | 782 FunctionElement lookedupConstructor, |
| 825 Selector call, | 783 Selector call, |
| 826 bool isImplicitSuperCall, | 784 bool isImplicitSuperCall, |
| 827 Node diagnosticNode, | 785 Node diagnosticNode, |
| 828 SourceString className, | 786 SourceString className, |
| 829 SourceString constructorName) { | 787 Selector constructorSelector) { |
| 830 if (lookedupConstructor == null | 788 if (lookedupConstructor == null |
| 831 || !lookedupConstructor.isGenerativeConstructor()) { | 789 || !lookedupConstructor.isGenerativeConstructor()) { |
| 832 var fullConstructorName = | 790 var fullConstructorName = |
| 833 visitor.compiler.resolver.constructorNameForDiagnostics(className, | 791 visitor.compiler.resolver.constructorNameForDiagnostics( |
| 834 constructorName); | 792 className, |
| 793 constructorSelector.name); |
| 835 MessageKind kind = isImplicitSuperCall | 794 MessageKind kind = isImplicitSuperCall |
| 836 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT | 795 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT |
| 837 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; | 796 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; |
| 838 error(diagnosticNode, kind, [fullConstructorName]); | 797 error(diagnosticNode, kind, [fullConstructorName]); |
| 839 } else { | 798 } else { |
| 840 if (!call.applies(lookedupConstructor, visitor.compiler)) { | 799 if (!call.applies(lookedupConstructor, visitor.compiler)) { |
| 841 MessageKind kind = isImplicitSuperCall | 800 MessageKind kind = isImplicitSuperCall |
| 842 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT | 801 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT |
| 843 : MessageKind.NO_MATCHING_CONSTRUCTOR; | 802 : MessageKind.NO_MATCHING_CONSTRUCTOR; |
| 844 error(diagnosticNode, kind); | 803 error(diagnosticNode, kind); |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 } | 1313 } |
| 1355 | 1314 |
| 1356 DartType useType(TypeAnnotation annotation, DartType type) { | 1315 DartType useType(TypeAnnotation annotation, DartType type) { |
| 1357 if (type != null) { | 1316 if (type != null) { |
| 1358 mapping.setType(annotation, type); | 1317 mapping.setType(annotation, type); |
| 1359 useElement(annotation, type.element); | 1318 useElement(annotation, type.element); |
| 1360 } | 1319 } |
| 1361 return type; | 1320 return type; |
| 1362 } | 1321 } |
| 1363 | 1322 |
| 1323 bool isNamedConstructor(Send node) => node.receiver != null; |
| 1324 |
| 1325 Selector getRedirectingThisOrSuperConstructorSelector(Send node) { |
| 1326 if (isNamedConstructor(node)) { |
| 1327 SourceString constructorName = node.selector.asIdentifier().source; |
| 1328 return new Selector.callConstructor( |
| 1329 constructorName, |
| 1330 enclosingElement.getLibrary()); |
| 1331 } else { |
| 1332 return new Selector.callDefaultConstructor( |
| 1333 enclosingElement.getLibrary()); |
| 1334 } |
| 1335 } |
| 1336 |
| 1337 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { |
| 1338 FunctionExpression node = constructor.parseNode(compiler); |
| 1339 |
| 1340 // A synthetic constructor does not have a node. |
| 1341 if (node == null) return null; |
| 1342 if (node.initializers == null) return null; |
| 1343 Link<Node> initializers = node.initializers.nodes; |
| 1344 if (!initializers.isEmpty && |
| 1345 Initializers.isConstructorRedirect(initializers.head)) { |
| 1346 Selector selector = |
| 1347 getRedirectingThisOrSuperConstructorSelector(initializers.head); |
| 1348 final ClassElement classElement = constructor.getEnclosingClass(); |
| 1349 return classElement.lookupConstructor(selector); |
| 1350 } |
| 1351 return null; |
| 1352 } |
| 1353 |
| 1364 void setupFunction(FunctionExpression node, FunctionElement function) { | 1354 void setupFunction(FunctionExpression node, FunctionElement function) { |
| 1365 scope = new MethodScope(scope, function); | 1355 scope = new MethodScope(scope, function); |
| 1366 | 1356 |
| 1367 // Put the parameters in scope. | 1357 // Put the parameters in scope. |
| 1368 FunctionSignature functionParameters = | 1358 FunctionSignature functionParameters = |
| 1369 function.computeSignature(compiler); | 1359 function.computeSignature(compiler); |
| 1370 Link<Node> parameterNodes = (node.parameters == null) | 1360 Link<Node> parameterNodes = (node.parameters == null) |
| 1371 ? const Link<Node>() : node.parameters.nodes; | 1361 ? const Link<Node>() : node.parameters.nodes; |
| 1372 functionParameters.forEachParameter((Element element) { | 1362 functionParameters.forEachParameter((Element element) { |
| 1373 if (element == functionParameters.optionalParameters.head) { | 1363 if (element == functionParameters.optionalParameters.head) { |
| (...skipping 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2993 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); | 2983 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); |
| 2994 } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) { | 2984 } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) { |
| 2995 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, [name]); | 2985 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, [name]); |
| 2996 } else if (!identical(e.kind, ElementKind.CLASS) | 2986 } else if (!identical(e.kind, ElementKind.CLASS) |
| 2997 && !identical(e.kind, ElementKind.PREFIX)) { | 2987 && !identical(e.kind, ElementKind.PREFIX)) { |
| 2998 error(node, MessageKind.NOT_A_TYPE, [name]); | 2988 error(node, MessageKind.NOT_A_TYPE, [name]); |
| 2999 } | 2989 } |
| 3000 return e; | 2990 return e; |
| 3001 } | 2991 } |
| 3002 } | 2992 } |
| OLD | NEW |