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

Side by Side Diff: lib/compiler/implementation/resolution/members.dart

Issue 11140018: Ensure that ClassElement.lookupConstructor fails when looking up default constructor using Selector… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Use [==] and [!=] instead of [identical] for SourceString comparison. Created 8 years, 1 month 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
OLDNEW
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
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 (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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698