| 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 if (identical(kind, ElementKind.PARAMETER) || | 80 if (identical(kind, ElementKind.PARAMETER) || |
| 81 identical(kind, ElementKind.FIELD_PARAMETER)) { | 81 identical(kind, ElementKind.FIELD_PARAMETER)) { |
| 82 return resolveParameter(element); | 82 return resolveParameter(element); |
| 83 } | 83 } |
| 84 | 84 |
| 85 compiler.unimplemented("resolve($element)", | 85 compiler.unimplemented("resolve($element)", |
| 86 node: element.parseNode(compiler)); | 86 node: element.parseNode(compiler)); |
| 87 }); | 87 }); |
| 88 } | 88 } |
| 89 | 89 |
| 90 bool isNamedConstructor(Send node) => node.receiver != null; | |
| 91 | |
| 92 SourceString getConstructorName(Send node) { | |
| 93 return node.selector.asIdentifier().source; | |
| 94 } | |
| 95 | |
| 96 String constructorNameForDiagnostics(SourceString className, | 90 String constructorNameForDiagnostics(SourceString className, |
| 97 SourceString constructorName) { | 91 SourceString constructorName) { |
| 98 String classNameString = className.slowToString(); | 92 String classNameString = className.slowToString(); |
| 99 String constructorNameString = constructorName.slowToString(); | 93 String constructorNameString = constructorName.slowToString(); |
| 100 return (identical(constructorName, const SourceString(''))) | 94 return (identical(constructorName, const SourceString(''))) |
| 101 ? classNameString | 95 ? classNameString |
| 102 : "$classNameString.$constructorNameString"; | 96 : "$classNameString.$constructorNameString"; |
| 103 } | 97 } |
| 104 | 98 |
| 105 FunctionElement resolveConstructorRedirection(InitializerResolver resolver, | |
| 106 FunctionElement constructor) { | |
| 107 if (constructor.isPatched) { | |
| 108 checkMatchingPatchSignatures(constructor, constructor.patch); | |
| 109 constructor = constructor.patch; | |
| 110 } | |
| 111 FunctionExpression node = constructor.parseNode(compiler); | |
| 112 | |
| 113 // A synthetic constructor does not have a node. | |
| 114 if (node == null) return null; | |
| 115 if (node.initializers == null) return null; | |
| 116 Link<Node> initializers = node.initializers.nodes; | |
| 117 if (!initializers.isEmpty && | |
| 118 Initializers.isConstructorRedirect(initializers.head)) { | |
| 119 final ClassElement classElement = constructor.getEnclosingClass(); | |
| 120 Selector selector; | |
| 121 if (isNamedConstructor(initializers.head)) { | |
| 122 SourceString constructorName = getConstructorName(initializers.head); | |
| 123 selector = new Selector.callConstructor( | |
| 124 constructorName, | |
| 125 resolver.visitor.enclosingElement.getLibrary()); | |
| 126 } else { | |
| 127 selector = new Selector.callDefaultConstructor( | |
| 128 resolver.visitor.enclosingElement.getLibrary()); | |
| 129 } | |
| 130 return classElement.lookupConstructor(selector); | |
| 131 } | |
| 132 return null; | |
| 133 } | |
| 134 | |
| 135 void resolveRedirectingConstructor(InitializerResolver resolver, | 99 void resolveRedirectingConstructor(InitializerResolver resolver, |
| 136 Node node, | 100 Node node, |
| 137 FunctionElement constructor, | 101 FunctionElement constructor, |
| 138 FunctionElement redirection) { | 102 FunctionElement redirection) { |
| 139 Set<FunctionElement> seen = new Set<FunctionElement>(); | 103 Set<FunctionElement> seen = new Set<FunctionElement>(); |
| 140 seen.add(constructor); | 104 seen.add(constructor); |
| 141 while (redirection != null) { | 105 while (redirection != null) { |
| 142 if (seen.contains(redirection)) { | 106 if (seen.contains(redirection)) { |
| 143 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 107 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
| 144 return; | 108 return; |
| 145 } | 109 } |
| 146 seen.add(redirection); | 110 seen.add(redirection); |
| 147 redirection = resolveConstructorRedirection(resolver, redirection); | 111 |
| 112 if (redirection.isPatched) { |
| 113 checkMatchingPatchSignatures(constructor, redirection.patch); |
| 114 redirection = redirection.patch; |
| 115 } |
| 116 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
| 148 } | 117 } |
| 149 } | 118 } |
| 150 | 119 |
| 151 void checkMatchingPatchParameters(FunctionElement origin, | 120 void checkMatchingPatchParameters(FunctionElement origin, |
| 152 Link<Element> originParameters, | 121 Link<Element> originParameters, |
| 153 Link<Element> patchParameters) { | 122 Link<Element> patchParameters) { |
| 154 while (!originParameters.isEmpty) { | 123 while (!originParameters.isEmpty) { |
| 155 Element originParameter = originParameters.head; | 124 Element originParameter = originParameters.head; |
| 156 Element patchParameter = patchParameters.head; | 125 Element patchParameter = patchParameters.head; |
| 157 // Hack: Use unparser to test parameter equality. This only works because | 126 // Hack: Use unparser to test parameter equality. This only works because |
| (...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 visitor.inStaticContext(() { | 705 visitor.inStaticContext(() { |
| 737 visitor.resolveSelector(call); | 706 visitor.resolveSelector(call); |
| 738 visitor.resolveArguments(call.argumentsNode); | 707 visitor.resolveArguments(call.argumentsNode); |
| 739 }); | 708 }); |
| 740 Selector selector = visitor.mapping.getSelector(call); | 709 Selector selector = visitor.mapping.getSelector(call); |
| 741 bool isSuperCall = Initializers.isSuperConstructorCall(call); | 710 bool isSuperCall = Initializers.isSuperConstructorCall(call); |
| 742 | 711 |
| 743 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, | 712 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, |
| 744 isSuperCall, | 713 isSuperCall, |
| 745 call); | 714 call); |
| 746 final SourceString className = lookupTarget.name; | 715 Selector constructorSelector = |
| 747 | 716 visitor.getRedirectingThisOrSuperConstructorSelector(call); |
| 748 SourceString constructorName; | 717 FunctionElement calledConstructor = |
| 749 Selector lookupSelector; | 718 lookupTarget.lookupConstructor(constructorSelector); |
| 750 if (resolver.isNamedConstructor(call)) { | |
| 751 constructorName = resolver.getConstructorName(call); | |
| 752 lookupSelector = new Selector.callConstructor( | |
| 753 constructorName, | |
| 754 visitor.enclosingElement.getLibrary()); | |
| 755 } else { | |
| 756 constructorName = const SourceString(''); | |
| 757 lookupSelector = new Selector.callDefaultConstructor( | |
| 758 visitor.enclosingElement.getLibrary()); | |
| 759 } | |
| 760 | |
| 761 FunctionElement lookedupConstructor = | |
| 762 lookupTarget.lookupConstructor(lookupSelector); | |
| 763 | 719 |
| 764 final bool isImplicitSuperCall = false; | 720 final bool isImplicitSuperCall = false; |
| 765 verifyThatConstructorMatchesCall(lookedupConstructor, | 721 final SourceString className = lookupTarget.name; |
| 722 verifyThatConstructorMatchesCall(calledConstructor, |
| 766 selector, | 723 selector, |
| 767 isImplicitSuperCall, | 724 isImplicitSuperCall, |
| 768 call, | 725 call, |
| 769 constructorName, | 726 className, |
| 770 className); | 727 constructorSelector); |
| 771 | 728 |
| 772 visitor.useElement(call, lookedupConstructor); | 729 visitor.useElement(call, calledConstructor); |
| 773 visitor.world.registerStaticUse(lookedupConstructor); | 730 visitor.world.registerStaticUse(calledConstructor); |
| 774 return lookedupConstructor; | 731 return calledConstructor; |
| 775 } | 732 } |
| 776 | 733 |
| 777 void resolveImplicitSuperConstructorSend(FunctionElement constructor, | 734 void resolveImplicitSuperConstructorSend(FunctionElement constructor, |
| 778 FunctionExpression functionNode) { | 735 FunctionExpression functionNode) { |
| 779 // If the class has a super resolve the implicit super call. | 736 // If the class has a super resolve the implicit super call. |
| 780 ClassElement classElement = constructor.getEnclosingClass(); | 737 ClassElement classElement = constructor.getEnclosingClass(); |
| 781 ClassElement superClass = classElement.superclass; | 738 ClassElement superClass = classElement.superclass; |
| 782 if (classElement != visitor.compiler.objectClass) { | 739 if (classElement != visitor.compiler.objectClass) { |
| 783 assert(superClass != null); | 740 assert(superClass != null); |
| 784 assert(superClass.resolutionState == STATE_DONE); | 741 assert(superClass.resolutionState == STATE_DONE); |
| 785 SourceString constructorName = const SourceString(''); | 742 SourceString constructorName = const SourceString(''); |
| 786 Selector callToMatch = new Selector.call( | 743 Selector callToMatch = new Selector.call( |
| 787 constructorName, | 744 constructorName, |
| 788 classElement.getLibrary(), | 745 classElement.getLibrary(), |
| 789 0); | 746 0); |
| 790 | 747 |
| 791 final bool isSuperCall = true; | 748 final bool isSuperCall = true; |
| 792 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, | 749 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, |
| 793 isSuperCall, | 750 isSuperCall, |
| 794 functionNode); | 751 functionNode); |
| 752 Selector constructorSelector = new Selector.callDefaultConstructor( |
| 753 visitor.enclosingElement.getLibrary()); |
| 754 Element calledConstructor = lookupTarget.lookupConstructor( |
| 755 constructorSelector); |
| 756 |
| 795 final SourceString className = lookupTarget.name; | 757 final SourceString className = lookupTarget.name; |
| 796 Element calledConstructor = lookupTarget.lookupConstructor( | |
| 797 new Selector.callDefaultConstructor( | |
| 798 visitor.enclosingElement.getLibrary())); | |
| 799 | |
| 800 final bool isImplicitSuperCall = true; | 758 final bool isImplicitSuperCall = true; |
| 801 verifyThatConstructorMatchesCall(calledConstructor, | 759 verifyThatConstructorMatchesCall(calledConstructor, |
| 802 callToMatch, | 760 callToMatch, |
| 803 isImplicitSuperCall, | 761 isImplicitSuperCall, |
| 804 functionNode, | 762 functionNode, |
| 805 className, | 763 className, |
| 806 const SourceString('')); | 764 constructorSelector); |
| 807 | 765 |
| 808 visitor.world.registerStaticUse(calledConstructor); | 766 visitor.world.registerStaticUse(calledConstructor); |
| 809 } | 767 } |
| 810 } | 768 } |
| 811 | 769 |
| 812 void verifyThatConstructorMatchesCall( | 770 void verifyThatConstructorMatchesCall( |
| 813 FunctionElement lookedupConstructor, | 771 FunctionElement lookedupConstructor, |
| 814 Selector call, | 772 Selector call, |
| 815 bool isImplicitSuperCall, | 773 bool isImplicitSuperCall, |
| 816 Node diagnosticNode, | 774 Node diagnosticNode, |
| 817 SourceString className, | 775 SourceString className, |
| 818 SourceString constructorName) { | 776 Selector constructorSelector) { |
| 819 if (lookedupConstructor == null | 777 if (lookedupConstructor == null |
| 820 || !lookedupConstructor.isGenerativeConstructor()) { | 778 || !lookedupConstructor.isGenerativeConstructor()) { |
| 821 var fullConstructorName = | 779 var fullConstructorName = |
| 822 visitor.compiler.resolver.constructorNameForDiagnostics(className, | 780 visitor.compiler.resolver.constructorNameForDiagnostics( |
| 823 constructorName); | 781 className, |
| 782 constructorSelector.name); |
| 824 MessageKind kind = isImplicitSuperCall | 783 MessageKind kind = isImplicitSuperCall |
| 825 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT | 784 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT |
| 826 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; | 785 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; |
| 827 error(diagnosticNode, kind, [fullConstructorName]); | 786 error(diagnosticNode, kind, [fullConstructorName]); |
| 828 } else { | 787 } else { |
| 829 if (!call.applies(lookedupConstructor, visitor.compiler)) { | 788 if (!call.applies(lookedupConstructor, visitor.compiler)) { |
| 830 MessageKind kind = isImplicitSuperCall | 789 MessageKind kind = isImplicitSuperCall |
| 831 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT | 790 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT |
| 832 : MessageKind.NO_MATCHING_CONSTRUCTOR; | 791 : MessageKind.NO_MATCHING_CONSTRUCTOR; |
| 833 error(diagnosticNode, kind); | 792 error(diagnosticNode, kind); |
| (...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 } | 1297 } |
| 1339 | 1298 |
| 1340 DartType useType(TypeAnnotation annotation, DartType type) { | 1299 DartType useType(TypeAnnotation annotation, DartType type) { |
| 1341 if (type != null) { | 1300 if (type != null) { |
| 1342 mapping.setType(annotation, type); | 1301 mapping.setType(annotation, type); |
| 1343 useElement(annotation, type.element); | 1302 useElement(annotation, type.element); |
| 1344 } | 1303 } |
| 1345 return type; | 1304 return type; |
| 1346 } | 1305 } |
| 1347 | 1306 |
| 1307 bool isNamedConstructor(Send node) => node.receiver != null; |
| 1308 |
| 1309 Selector getRedirectingThisOrSuperConstructorSelector(Send node) { |
| 1310 if (isNamedConstructor(node)) { |
| 1311 SourceString constructorName = node.selector.asIdentifier().source; |
| 1312 return new Selector.callConstructor( |
| 1313 constructorName, |
| 1314 enclosingElement.getLibrary()); |
| 1315 } else { |
| 1316 return new Selector.callDefaultConstructor( |
| 1317 enclosingElement.getLibrary()); |
| 1318 } |
| 1319 } |
| 1320 |
| 1321 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { |
| 1322 FunctionExpression node = constructor.parseNode(compiler); |
| 1323 |
| 1324 // A synthetic constructor does not have a node. |
| 1325 if (node == null) return null; |
| 1326 if (node.initializers == null) return null; |
| 1327 Link<Node> initializers = node.initializers.nodes; |
| 1328 if (!initializers.isEmpty && |
| 1329 Initializers.isConstructorRedirect(initializers.head)) { |
| 1330 Selector selector = |
| 1331 getRedirectingThisOrSuperConstructorSelector(initializers.head); |
| 1332 final ClassElement classElement = constructor.getEnclosingClass(); |
| 1333 return classElement.lookupConstructor(selector); |
| 1334 } |
| 1335 return null; |
| 1336 } |
| 1337 |
| 1348 void setupFunction(FunctionExpression node, FunctionElement function) { | 1338 void setupFunction(FunctionExpression node, FunctionElement function) { |
| 1349 scope = new MethodScope(scope, function); | 1339 scope = new MethodScope(scope, function); |
| 1350 | 1340 |
| 1351 // Put the parameters in scope. | 1341 // Put the parameters in scope. |
| 1352 FunctionSignature functionParameters = | 1342 FunctionSignature functionParameters = |
| 1353 function.computeSignature(compiler); | 1343 function.computeSignature(compiler); |
| 1354 Link<Node> parameterNodes = (node.parameters == null) | 1344 Link<Node> parameterNodes = (node.parameters == null) |
| 1355 ? const Link<Node>() : node.parameters.nodes; | 1345 ? const Link<Node>() : node.parameters.nodes; |
| 1356 functionParameters.forEachParameter((Element element) { | 1346 functionParameters.forEachParameter((Element element) { |
| 1357 if (element == functionParameters.optionalParameters.head) { | 1347 if (element == functionParameters.optionalParameters.head) { |
| (...skipping 1606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2964 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); | 2954 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); |
| 2965 } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) { | 2955 } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) { |
| 2966 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, [name]); | 2956 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, [name]); |
| 2967 } else if (!identical(e.kind, ElementKind.CLASS) | 2957 } else if (!identical(e.kind, ElementKind.CLASS) |
| 2968 && !identical(e.kind, ElementKind.PREFIX)) { | 2958 && !identical(e.kind, ElementKind.PREFIX)) { |
| 2969 error(node, MessageKind.NOT_A_TYPE, [name]); | 2959 error(node, MessageKind.NOT_A_TYPE, [name]); |
| 2970 } | 2960 } |
| 2971 return e; | 2961 return e; |
| 2972 } | 2962 } |
| 2973 } | 2963 } |
| OLD | NEW |