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

Side by Side Diff: lib/compiler/implementation/resolver.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: Replaced getConstructorName with getConstructorSelector. 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(TypeAnnotation annotation); 8 DartType getType(TypeAnnotation annotation);
9 bool isParameterChecked(Element element); 9 bool isParameterChecked(Element element);
10 } 10 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
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; 90 bool isNamedConstructor(Send node) => node.receiver !== null;
91 91
92 SourceString getConstructorName(Send node) { 92 Selector getConstructorSelector(Send node, SourceString className, ResolverVis itor visitor) {
kasperl 2012/10/15 12:14:12 Long line.
aam-me 2012/10/16 04:09:32 Done.
93 return node.selector.asIdentifier().source; 93 SourceString constructorName;
94 if (!isNamedConstructor(node)) {
95 constructorName = const SourceString("");
kasperl 2012/10/15 12:14:12 Why don't you just return the selector here? It fe
aam-me 2012/10/16 04:09:32 Done.
96 } else {
97 constructorName = node.selector.asIdentifier().source;
98 if (constructorName.slowToString() == className.slowToString()) {
kasperl 2012/10/15 12:14:12 Add a comment that explains when this happens? Thi
aam-me 2012/10/16 04:09:32 You are right, Kasper. The code above is wrong. It
99 constructorName = const SourceString("");
100 }
101 }
102 Selector selector;
kasperl 2012/10/15 12:14:12 I would get rid of this part and just put the retu
aam-me 2012/10/16 04:09:32 Done.
103 if (constructorName != const SourceString("")) {
104 selector = new Selector.callConstructor(
105 constructorName,
106 visitor.enclosingElement.getLibrary());
107 } else {
108 selector = new Selector.callDefaultConstructor(
109 visitor.enclosingElement.getLibrary());
110 }
111 return selector;
94 } 112 }
95 113
96 String constructorNameForDiagnostics(SourceString className, 114 String constructorNameForDiagnostics(SourceString className,
97 SourceString constructorName) { 115 SourceString constructorName) {
kasperl 2012/10/15 12:14:12 Weird indentation.
aam-me 2012/10/16 04:09:32 Done.
98 String classNameString = className.slowToString(); 116 String classNameString = className.slowToString();
99 String constructorNameString = constructorName.slowToString(); 117 String constructorNameString = constructorName.slowToString();
100 return (constructorName === const SourceString('')) 118 return (constructorName === const SourceString(''))
101 ? classNameString 119 ? classNameString
102 : "$classNameString.$constructorNameString"; 120 : "$classNameString.$constructorNameString";
103 } 121 }
104 122
105 FunctionElement resolveConstructorRedirection(InitializerResolver resolver, 123 FunctionElement resolveConstructorRedirection(InitializerResolver resolver,
106 FunctionElement constructor) { 124 FunctionElement constructor) {
107 if (constructor.isPatched) { 125 if (constructor.isPatched) {
108 checkMatchingPatchSignatures(constructor, constructor.patch); 126 checkMatchingPatchSignatures(constructor, constructor.patch);
109 constructor = constructor.patch; 127 constructor = constructor.patch;
110 } 128 }
111 FunctionExpression node = constructor.parseNode(compiler); 129 FunctionExpression node = constructor.parseNode(compiler);
112 130
113 // A synthetic constructor does not have a node. 131 // A synthetic constructor does not have a node.
114 if (node === null) return null; 132 if (node === null) return null;
115 if (node.initializers === null) return null; 133 if (node.initializers === null) return null;
116 Link<Node> initializers = node.initializers.nodes; 134 Link<Node> initializers = node.initializers.nodes;
117 if (!initializers.isEmpty() && 135 if (!initializers.isEmpty() &&
118 Initializers.isConstructorRedirect(initializers.head)) { 136 Initializers.isConstructorRedirect(initializers.head)) {
119 final ClassElement classElement = constructor.getEnclosingClass(); 137 final ClassElement classElement = constructor.getEnclosingClass();
120 Selector selector; 138 Selector selector = getConstructorSelector(initializers.head,
121 if (isNamedConstructor(initializers.head)) { 139 classElement.name,
122 SourceString constructorName = getConstructorName(initializers.head); 140 resolver.visitor);
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); 141 return classElement.lookupConstructor(selector);
131 } 142 }
132 return null; 143 return null;
133 } 144 }
134 145
135 void resolveRedirectingConstructor(InitializerResolver resolver, 146 void resolveRedirectingConstructor(InitializerResolver resolver,
136 Node node, 147 Node node,
137 FunctionElement constructor, 148 FunctionElement constructor,
138 FunctionElement redirection) { 149 FunctionElement redirection) {
139 Set<FunctionElement> seen = new Set<FunctionElement>(); 150 Set<FunctionElement> seen = new Set<FunctionElement>();
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 visitor.resolveArguments(call.argumentsNode); 749 visitor.resolveArguments(call.argumentsNode);
739 }); 750 });
740 Selector selector = visitor.mapping.getSelector(call); 751 Selector selector = visitor.mapping.getSelector(call);
741 bool isSuperCall = Initializers.isSuperConstructorCall(call); 752 bool isSuperCall = Initializers.isSuperConstructorCall(call);
742 753
743 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, 754 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
744 isSuperCall, 755 isSuperCall,
745 call); 756 call);
746 final SourceString className = lookupTarget.name; 757 final SourceString className = lookupTarget.name;
747 758
748 SourceString constructorName; 759 Selector constructorSelector =
749 Selector lookupSelector; 760 resolver.getConstructorSelector(call, className, visitor);
750 if (resolver.isNamedConstructor(call)) { 761 FunctionElement calledConstructor =
751 constructorName = resolver.getConstructorName(call); 762 lookupTarget.lookupConstructor(constructorSelector);
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 763
764 final bool isImplicitSuperCall = false; 764 final bool isImplicitSuperCall = false;
765 verifyThatConstructorMatchesCall(lookedupConstructor, 765 verifyThatConstructorMatchesCall(calledConstructor,
766 selector, 766 selector,
767 isImplicitSuperCall, 767 isImplicitSuperCall,
768 call, 768 call,
769 constructorName, 769 className,
770 className); 770 constructorSelector);
771 771
772 visitor.useElement(call, lookedupConstructor); 772 visitor.useElement(call, calledConstructor);
773 visitor.world.registerStaticUse(lookedupConstructor); 773 visitor.world.registerStaticUse(calledConstructor);
774 return lookedupConstructor; 774 return calledConstructor;
775 } 775 }
776 776
777 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 777 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
778 FunctionExpression functionNode) { 778 FunctionExpression functionNode) {
779 // If the class has a super resolve the implicit super call. 779 // If the class has a super resolve the implicit super call.
780 ClassElement classElement = constructor.getEnclosingClass(); 780 ClassElement classElement = constructor.getEnclosingClass();
781 ClassElement superClass = classElement.superclass; 781 ClassElement superClass = classElement.superclass;
782 if (classElement != visitor.compiler.objectClass) { 782 if (classElement != visitor.compiler.objectClass) {
783 assert(superClass !== null); 783 assert(superClass !== null);
784 assert(superClass.resolutionState == STATE_DONE); 784 assert(superClass.resolutionState == STATE_DONE);
785 SourceString constructorName = const SourceString(''); 785 SourceString constructorName = const SourceString('');
786 Selector callToMatch = new Selector.call( 786 Selector callToMatch = new Selector.call(
787 constructorName, 787 constructorName,
788 classElement.getLibrary(), 788 classElement.getLibrary(),
789 0); 789 0);
790 790
791 final bool isSuperCall = true; 791 final bool isSuperCall = true;
792 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, 792 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
793 isSuperCall, 793 isSuperCall,
794 functionNode); 794 functionNode);
795 Selector constructorSelector = new Selector.callDefaultConstructor(
796 visitor.enclosingElement.getLibrary());
797 Element calledConstructor = lookupTarget.lookupConstructor(
798 constructorSelector);
799
795 final SourceString className = lookupTarget.name; 800 final SourceString className = lookupTarget.name;
796 Element calledConstructor = lookupTarget.lookupConstructor(
797 new Selector.callDefaultConstructor(
798 visitor.enclosingElement.getLibrary()));
799
800 final bool isImplicitSuperCall = true; 801 final bool isImplicitSuperCall = true;
801 verifyThatConstructorMatchesCall(calledConstructor, 802 verifyThatConstructorMatchesCall(calledConstructor,
802 callToMatch, 803 callToMatch,
803 isImplicitSuperCall, 804 isImplicitSuperCall,
804 functionNode, 805 functionNode,
805 className, 806 className,
806 const SourceString('')); 807 constructorSelector);
807 808
808 visitor.world.registerStaticUse(calledConstructor); 809 visitor.world.registerStaticUse(calledConstructor);
809 } 810 }
810 } 811 }
811 812
812 void verifyThatConstructorMatchesCall( 813 void verifyThatConstructorMatchesCall(
813 FunctionElement lookedupConstructor, 814 FunctionElement lookedupConstructor,
814 Selector call, 815 Selector call,
815 bool isImplicitSuperCall, 816 bool isImplicitSuperCall,
816 Node diagnosticNode, 817 Node diagnosticNode,
817 SourceString className, 818 SourceString className,
818 SourceString constructorName) { 819 Selector constructorSelector) {
819 if (lookedupConstructor === null 820 if (lookedupConstructor === null
820 || !lookedupConstructor.isGenerativeConstructor()) { 821 || !lookedupConstructor.isGenerativeConstructor()) {
821 var fullConstructorName = 822 var fullConstructorName =
822 visitor.compiler.resolver.constructorNameForDiagnostics(className, 823 visitor.compiler.resolver.constructorNameForDiagnostics(
823 constructorName); 824 className,
825 constructorSelector.name);
824 MessageKind kind = isImplicitSuperCall 826 MessageKind kind = isImplicitSuperCall
825 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 827 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
826 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 828 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
827 error(diagnosticNode, kind, [fullConstructorName]); 829 error(diagnosticNode, kind, [fullConstructorName]);
828 } else { 830 } else {
829 if (!call.applies(lookedupConstructor, visitor.compiler)) { 831 if (!call.applies(lookedupConstructor, visitor.compiler)) {
830 MessageKind kind = isImplicitSuperCall 832 MessageKind kind = isImplicitSuperCall
831 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 833 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
832 : MessageKind.NO_MATCHING_CONSTRUCTOR; 834 : MessageKind.NO_MATCHING_CONSTRUCTOR;
833 error(diagnosticNode, kind); 835 error(diagnosticNode, kind);
(...skipping 2393 matching lines...) Expand 10 before | Expand all | Expand 10 after
3227 return result; 3229 return result;
3228 } 3230 }
3229 Element lookup(SourceString name) => localLookup(name); 3231 Element lookup(SourceString name) => localLookup(name);
3230 Element lexicalLookup(SourceString name) => localLookup(name); 3232 Element lexicalLookup(SourceString name) => localLookup(name);
3231 3233
3232 Element add(Element newElement) { 3234 Element add(Element newElement) {
3233 throw "Cannot add an element in a patch library scope"; 3235 throw "Cannot add an element in a patch library scope";
3234 } 3236 }
3235 String toString() => 'PatchLibraryScope($origin,$patch)'; 3237 String toString() => 'PatchLibraryScope($origin,$patch)';
3236 } 3238 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | tests/compiler/dart2js/resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698