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

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: Rebased. Created 8 years, 2 months 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698