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

Side by Side Diff: lib/compiler/implementation/resolver.dart

Issue 10947024: Made dart2js constructor lookup logic "private"-aware, fixed 4740 bug. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed normalizedConstructorName from Selector. 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 if (kind === ElementKind.PARAMETER || 80 if (kind === ElementKind.PARAMETER ||
81 kind === ElementKind.FIELD_PARAMETER) { 81 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 SourceString getConstructorName(Send node) { 90 bool isNamedConstructor(Send node) => node.receiver !== null;
91 if (node.receiver !== null) { 91 SourceString getConstructorName(Send node) =>
92 return node.selector.asIdentifier().source; 92 node.selector.asIdentifier().source;
93 } else {
94 return const SourceString('');
95 }
96 }
97 93
98 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { 94 String createConstructorFullName(SourceString className,
95 SourceString constructorName) {
96 String classNameString = className.slowToString();
97 String constructorNameString = constructorName.slowToString();
98 return (constructorName === const SourceString(''))
99 ? classNameString
100 : "$classNameString.$constructorNameString";
101 }
102
103 FunctionElement resolveConstructorRedirection(InitializerResolver resolver,
104 FunctionElement constructor) {
99 if (constructor.isPatched) { 105 if (constructor.isPatched) {
100 checkMatchingPatchSignatures(constructor, constructor.patch); 106 checkMatchingPatchSignatures(constructor, constructor.patch);
101 constructor = constructor.patch; 107 constructor = constructor.patch;
102 } 108 }
103 FunctionExpression node = constructor.parseNode(compiler); 109 FunctionExpression node = constructor.parseNode(compiler);
104 110
105 // A synthetic constructor does not have a node. 111 // A synthetic constructor does not have a node.
106 if (node === null) return null; 112 if (node === null) return null;
107 if (node.initializers === null) return null; 113 if (node.initializers === null) return null;
108 Link<Node> initializers = node.initializers.nodes; 114 Link<Node> initializers = node.initializers.nodes;
109 if (!initializers.isEmpty() && 115 if (!initializers.isEmpty() &&
110 Initializers.isConstructorRedirect(initializers.head)) { 116 Initializers.isConstructorRedirect(initializers.head)) {
111 final ClassElement classElement = constructor.getEnclosingClass(); 117 final ClassElement classElement = constructor.getEnclosingClass();
112 final SourceString constructorName = 118 Selector selector;
113 getConstructorName(initializers.head); 119 if (isNamedConstructor(initializers.head)) {
114 final SourceString className = classElement.name; 120 SourceString constructorName = getConstructorName(initializers.head);
115 return classElement.lookupConstructor(className, constructorName); 121 selector = new Selector.callConstructor(
122 constructorName,
123 resolver.visitor.enclosingElement.getLibrary());
124 } else {
125 selector = new Selector.callDefaultConstructor(
126 classElement.name,
127 resolver.visitor.enclosingElement.getLibrary());
128 }
129 return classElement.lookupConstructor(selector);
116 } 130 }
117 return null; 131 return null;
118 } 132 }
119 133
120 void resolveRedirectingConstructor(InitializerResolver resolver, 134 void resolveRedirectingConstructor(InitializerResolver resolver,
121 Node node, 135 Node node,
122 FunctionElement constructor, 136 FunctionElement constructor,
123 FunctionElement redirection) { 137 FunctionElement redirection) {
124 Set<FunctionElement> seen = new Set<FunctionElement>(); 138 Set<FunctionElement> seen = new Set<FunctionElement>();
125 seen.add(constructor); 139 seen.add(constructor);
126 while (redirection !== null) { 140 while (redirection !== null) {
127 if (seen.contains(redirection)) { 141 if (seen.contains(redirection)) {
128 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); 142 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
129 return; 143 return;
130 } 144 }
131 seen.add(redirection); 145 seen.add(redirection);
132 redirection = resolveConstructorRedirection(redirection); 146 redirection = resolveConstructorRedirection(resolver, redirection);
133 } 147 }
134 } 148 }
135 149
136 void checkMatchingPatchParameters(FunctionElement origin, 150 void checkMatchingPatchParameters(FunctionElement origin,
137 Link<Element> originParameters, 151 Link<Element> originParameters,
138 Link<Element> patchParameters) { 152 Link<Element> patchParameters) {
139 while (!originParameters.isEmpty()) { 153 while (!originParameters.isEmpty()) {
140 Element originParameter = originParameters.head; 154 Element originParameter = originParameters.head;
141 Element patchParameter = patchParameters.head; 155 Element patchParameter = patchParameters.head;
142 // Hack: Use unparser to test parameter equality. This only works because 156 // Hack: Use unparser to test parameter equality. This only works because
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 assert(defaultClass.resolutionState == STATE_DONE); 297 assert(defaultClass.resolutionState == STATE_DONE);
284 assert(defaultClass.supertypeLoadState == STATE_DONE); 298 assert(defaultClass.supertypeLoadState == STATE_DONE);
285 if (defaultClass.isInterface()) { 299 if (defaultClass.isInterface()) {
286 error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE, 300 error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE,
287 [defaultClass.name]); 301 [defaultClass.name]);
288 } 302 }
289 // We have now established the following: 303 // We have now established the following:
290 // [intrface] is an interface, let's say "MyInterface". 304 // [intrface] is an interface, let's say "MyInterface".
291 // [defaultClass] is a class, let's say "MyClass". 305 // [defaultClass] is a class, let's say "MyClass".
292 306
307 Selector selector;
293 // If the default class implements the interface then we must use the 308 // If the default class implements the interface then we must use the
294 // default class' name. Otherwise we look for a factory with the name 309 // default class' name. Otherwise we look for a factory with the name
295 // of the interface. 310 // of the interface.
296 SourceString name;
297 if (defaultClass.implementsInterface(intrface)) { 311 if (defaultClass.implementsInterface(intrface)) {
298 // TODO(ahe): Don't use string replacement here. 312 var constructorNameString = constructor.name.slowToString();
299 name = new SourceString(constructor.name.slowToString().replaceFirst( 313 // Create selector based on constructor.name but where interface
300 intrface.name.slowToString(), 314 // is replaced with default class name.
301 defaultClass.name.slowToString())); 315 num ndxDollar = constructorNameString.indexOf('\$');
kasperl 2012/10/09 13:56:02 I would avoid the abbreviation and call this 'int
aam-me 2012/10/10 00:22:40 Done.
316 if (ndxDollar < 0) {
317 selector = new Selector.callDefaultConstructor(
318 defaultClass.name,
319 defaultClass.getLibrary());
320 } else {
321 selector = new Selector.callConstructor(
322 new SourceString(constructorNameString.substring(ndxDollar + 1)),
323 defaultClass.getLibrary());
324 }
325 constructor.defaultImplementation =
326 defaultClass.lookupConstructor(selector);
302 } else { 327 } else {
303 name = constructor.name; 328 selector =
329 new Selector.callDefaultConstructor(constructor.name,
330 defaultClass.getLibrary());
331 constructor.defaultImplementation =
332 defaultClass.lookupFactoryConstructor(selector);
304 } 333 }
305 constructor.defaultImplementation = defaultClass.lookupConstructor(name);
306
307 if (constructor.defaultImplementation === null) { 334 if (constructor.defaultImplementation === null) {
308 // We failed to find a constructor named either 335 // We failed to find a constructor named either
309 // "MyInterface.name" or "MyClass.name". 336 // "MyInterface.name" or "MyClass.name".
310 error(node, 337 error(node,
311 MessageKind.CANNOT_FIND_CONSTRUCTOR2, 338 MessageKind.CANNOT_FIND_CONSTRUCTOR2,
312 [name, defaultClass.name]); 339 [selector.name, defaultClass.name]);
313 } 340 }
314 } 341 }
315 342
316 TreeElements resolveField(Element element) { 343 TreeElements resolveField(Element element) {
317 Node tree = element.parseNode(compiler); 344 Node tree = element.parseNode(compiler);
318 ResolverVisitor visitor = new ResolverVisitor(compiler, element); 345 ResolverVisitor visitor = new ResolverVisitor(compiler, element);
319 initializerDo(tree, visitor.visit); 346 initializerDo(tree, visitor.visit);
320 return visitor.mapping; 347 return visitor.mapping;
321 } 348 }
322 349
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
672 } else { 699 } else {
673 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 700 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
674 } 701 }
675 visitor.useElement(init, target); 702 visitor.useElement(init, target);
676 visitor.world.registerStaticUse(target); 703 visitor.world.registerStaticUse(target);
677 checkForDuplicateInitializers(name, init); 704 checkForDuplicateInitializers(name, init);
678 // Resolve initializing value. 705 // Resolve initializing value.
679 visitor.visitInStaticContext(init.arguments.head); 706 visitor.visitInStaticContext(init.arguments.head);
680 } 707 }
681 708
709 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
710 bool isSuperCall,
711 Node diagnosticNode) {
712 ClassElement lookupTarget = constructor.getEnclosingClass();
713 if (isSuperCall) {
714 // Calculate correct lookup target and constructor name.
715 if (lookupTarget === visitor.compiler.objectClass) {
716 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
717 } else {
718 lookupTarget = lookupTarget.supertype.element;
719 }
720 }
721 return lookupTarget;
722 }
723
682 Element resolveSuperOrThisForSend(FunctionElement constructor, 724 Element resolveSuperOrThisForSend(FunctionElement constructor,
683 FunctionExpression functionNode, 725 FunctionExpression functionNode,
684 Send call) { 726 Send call) {
685 // Resolve the selector and the arguments. 727 // Resolve the selector and the arguments.
686 ResolverTask resolver = visitor.compiler.resolver; 728 ResolverTask resolver = visitor.compiler.resolver;
687 visitor.inStaticContext(() { 729 visitor.inStaticContext(() {
688 visitor.resolveSelector(call); 730 visitor.resolveSelector(call);
689 visitor.resolveArguments(call.argumentsNode); 731 visitor.resolveArguments(call.argumentsNode);
690 }); 732 });
691 Selector selector = visitor.mapping.getSelector(call); 733 Selector selector = visitor.mapping.getSelector(call);
692 bool isSuperCall = Initializers.isSuperConstructorCall(call); 734 bool isSuperCall = Initializers.isSuperConstructorCall(call);
693 SourceString constructorName = resolver.getConstructorName(call); 735
694 Element result = resolveSuperOrThis( 736 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
695 constructor, isSuperCall, false, constructorName, selector, call); 737 isSuperCall,
696 visitor.useElement(call, result); 738 call);
697 visitor.world.registerStaticUse(result); 739 final SourceString className = lookupTarget.name;
698 return result; 740
741 SourceString constructorName;
742 Selector lookupSelector;
743 if (resolver.isNamedConstructor(call)) {
744 constructorName = resolver.getConstructorName(call);
745 lookupSelector = new Selector.callConstructor(
746 constructorName,
747 visitor.enclosingElement.getLibrary());
748 } else {
749 constructorName = const SourceString('');
750 lookupSelector = new Selector.callDefaultConstructor(
751 className,
752 visitor.enclosingElement.getLibrary());
753 }
754
755 FunctionElement lookedupConstructor =
756 lookupTarget.lookupConstructor(lookupSelector);
757
758 final bool isImplicitSuperCall = false;
759 verifyThatConstructorMatchesCall(lookedupConstructor,
760 selector,
761 isImplicitSuperCall,
762 call,
763 constructorName,
764 className);
765
766 visitor.useElement(call, lookedupConstructor);
767 visitor.world.registerStaticUse(lookedupConstructor);
768 return lookedupConstructor;
699 } 769 }
700 770
701 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 771 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
702 FunctionExpression functionNode) { 772 FunctionExpression functionNode) {
703 // If the class has a super resolve the implicit super call. 773 // If the class has a super resolve the implicit super call.
704 ClassElement classElement = constructor.getEnclosingClass(); 774 ClassElement classElement = constructor.getEnclosingClass();
705 ClassElement superClass = classElement.superclass; 775 ClassElement superClass = classElement.superclass;
706 if (classElement != visitor.compiler.objectClass) { 776 if (classElement != visitor.compiler.objectClass) {
707 assert(superClass !== null); 777 assert(superClass !== null);
708 assert(superClass.resolutionState == STATE_DONE); 778 assert(superClass.resolutionState == STATE_DONE);
709 SourceString name = const SourceString(''); 779 SourceString constructorName = const SourceString('');
710 Selector call = new Selector.call(name, classElement.getLibrary(), 0); 780 Selector callToMatch = new Selector.call(
711 var element = resolveSuperOrThis(constructor, true, true, 781 constructorName,
712 name, call, functionNode); 782 classElement.getLibrary(),
713 visitor.world.registerStaticUse(element); 783 0);
784
785 final bool isSuperCall = true;
786 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
787 isSuperCall,
788 functionNode);
789 final SourceString className = lookupTarget.name;
790 Element calledConstructor = lookupTarget.lookupConstructor(
791 new Selector.callDefaultConstructor(
792 className,
793 visitor.enclosingElement.getLibrary()));
794
795 final bool isImplicitSuperCall = true;
796 verifyThatConstructorMatchesCall(calledConstructor,
797 callToMatch,
798 isImplicitSuperCall,
799 functionNode,
800 className,
801 const SourceString(''));
802
803 visitor.world.registerStaticUse(calledConstructor);
714 } 804 }
715 } 805 }
716 806
717 Element resolveSuperOrThis(FunctionElement constructor, 807 void verifyThatConstructorMatchesCall(
718 bool isSuperCall, 808 FunctionElement lookedupConstructor,
719 bool isImplicitSuperCall, 809 Selector call,
720 SourceString constructorName, 810 bool isImplicitSuperCall,
721 Selector selector, 811 Node diagnosticNode,
722 Node diagnosticNode) { 812 SourceString className,
723 ClassElement lookupTarget = constructor.getEnclosingClass(); 813 SourceString constructorName) {
724 bool validTarget = true; 814 if (lookedupConstructor === null
725 FunctionElement result; 815 || !lookedupConstructor.isGenerativeConstructor()) {
726 if (isSuperCall) { 816 var fullConstructorName =
727 // Calculate correct lookup target and constructor name. 817 visitor.compiler.resolver.createConstructorFullName(className,
728 if (lookupTarget === visitor.compiler.objectClass) { 818 constructorName);
729 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
730 } else {
731 lookupTarget = lookupTarget.supertype.element;
732 }
733 }
734
735 // Lookup constructor and try to match it to the selector.
736 ResolverTask resolver = visitor.compiler.resolver;
737 final SourceString className = lookupTarget.name;
738 result = lookupTarget.lookupConstructor(className, constructorName);
739 if (result === null || !result.isGenerativeConstructor()) {
740 String classNameString = className.slowToString();
741 String constructorNameString = constructorName.slowToString();
742 String name = (constructorName === const SourceString(''))
743 ? classNameString
744 : "$classNameString.$constructorNameString";
745 MessageKind kind = isImplicitSuperCall 819 MessageKind kind = isImplicitSuperCall
746 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 820 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
747 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 821 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
748 error(diagnosticNode, kind, [name]); 822 error(diagnosticNode, kind, [fullConstructorName]);
749 } else { 823 } else {
750 if (!selector.applies(result, visitor.compiler)) { 824 if (!call.applies(lookedupConstructor, visitor.compiler)) {
751 MessageKind kind = isImplicitSuperCall 825 MessageKind kind = isImplicitSuperCall
752 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 826 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
753 : MessageKind.NO_MATCHING_CONSTRUCTOR; 827 : MessageKind.NO_MATCHING_CONSTRUCTOR;
754 error(diagnosticNode, kind); 828 error(diagnosticNode, kind);
755 } 829 }
756 } 830 }
757 return result;
758 } 831 }
759 832
760 FunctionElement resolveRedirection(FunctionElement constructor, 833 FunctionElement resolveRedirection(FunctionElement constructor,
761 FunctionExpression functionNode) { 834 FunctionExpression functionNode) {
762 if (functionNode.initializers === null) return null; 835 if (functionNode.initializers === null) return null;
763 Link<Node> link = functionNode.initializers.nodes; 836 Link<Node> link = functionNode.initializers.nodes;
764 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) { 837 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) {
765 return resolveSuperOrThisForSend(constructor, functionNode, link.head); 838 return resolveSuperOrThisForSend(constructor, functionNode, link.head);
766 } 839 }
767 return null; 840 return null;
(...skipping 2019 matching lines...) Expand 10 before | Expand all | Expand 10 after
2787 return new ErroneousFunctionElement(kind, arguments, targetName, 2860 return new ErroneousFunctionElement(kind, arguments, targetName,
2788 enclosing); 2861 enclosing);
2789 } 2862 }
2790 } 2863 }
2791 2864
2792 // TODO(ngeoffray): method named lookup should not report errors. 2865 // TODO(ngeoffray): method named lookup should not report errors.
2793 FunctionElement lookupConstructor(ClassElement cls, 2866 FunctionElement lookupConstructor(ClassElement cls,
2794 Node diagnosticNode, 2867 Node diagnosticNode,
2795 SourceString constructorName) { 2868 SourceString constructorName) {
2796 cls.ensureResolved(compiler); 2869 cls.ensureResolved(compiler);
2797 Element result = cls.lookupConstructor(cls.name, constructorName); 2870 Selector selector =
2871 constructorName === const SourceString('')
2872 ? new Selector.callDefaultConstructor(
2873 cls.name,
2874 resolver.enclosingElement.getLibrary())
2875 : new Selector.callConstructor(
2876 constructorName,
2877 resolver.enclosingElement.getLibrary());
2878 Element result = cls.lookupConstructor(selector);
2798 if (result === null) { 2879 if (result === null) {
2799 String fullConstructorName = cls.name.slowToString(); 2880 String fullConstructorName =
2800 if (constructorName !== const SourceString('')) { 2881 resolver.compiler.resolver.createConstructorFullName(
2801 fullConstructorName = '$fullConstructorName' 2882 cls.name,
2802 '.${constructorName.slowToString()}'; 2883 constructorName);
2803 } 2884 return failOrReturnErroneousElement(
2804 return failOrReturnErroneousElement(cls, diagnosticNode, 2885 cls,
2805 new SourceString(fullConstructorName), 2886 diagnosticNode,
2806 MessageKind.CANNOT_FIND_CONSTRUCTOR, 2887 new SourceString(fullConstructorName),
2807 [fullConstructorName]); 2888 MessageKind.CANNOT_FIND_CONSTRUCTOR,
2889 [fullConstructorName]);
2808 } else if (inConstContext && !result.modifiers.isConst()) { 2890 } else if (inConstContext && !result.modifiers.isConst()) {
2809 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 2891 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
2810 } 2892 }
2811 return result; 2893 return result;
2812 } 2894 }
2813 2895
2814 visitNewExpression(NewExpression node) { 2896 visitNewExpression(NewExpression node) {
2815 Node selector = node.send.selector; 2897 Node selector = node.send.selector;
2816 Element e = visit(selector); 2898 Element e = visit(selector);
2817 if (!Elements.isUnresolved(e) && e.kind === ElementKind.CLASS) { 2899 if (!Elements.isUnresolved(e) && e.kind === ElementKind.CLASS) {
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
3132 return result; 3214 return result;
3133 } 3215 }
3134 Element lookup(SourceString name) => localLookup(name); 3216 Element lookup(SourceString name) => localLookup(name);
3135 Element lexicalLookup(SourceString name) => localLookup(name); 3217 Element lexicalLookup(SourceString name) => localLookup(name);
3136 3218
3137 Element add(Element newElement) { 3219 Element add(Element newElement) {
3138 throw "Cannot add an element in a patch library scope"; 3220 throw "Cannot add an element in a patch library scope";
3139 } 3221 }
3140 String toString() => 'PatchLibraryScope($origin,$patch)'; 3222 String toString() => 'PatchLibraryScope($origin,$patch)';
3141 } 3223 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698