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

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: Use resolver.enclosingElement. Fixed line wrapping. 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
kasperl 2012/10/08 08:06:41 4 space indent of ? and :.
aam-me 2012/10/09 04:08:42 Done.
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 classElement.name,
123 constructorName,
124 resolver.visitor.enclosingElement.getLibrary());
125 } else {
126 selector = new Selector.callDefaultConstructor(
127 classElement.name,
128 resolver.visitor.enclosingElement.getLibrary());
129 }
130 return classElement.lookupConstructor(selector);
116 } 131 }
117 return null; 132 return null;
118 } 133 }
119 134
120 void resolveRedirectingConstructor(InitializerResolver resolver, 135 void resolveRedirectingConstructor(InitializerResolver resolver,
121 Node node, 136 Node node,
122 FunctionElement constructor, 137 FunctionElement constructor,
123 FunctionElement redirection) { 138 FunctionElement redirection) {
124 Set<FunctionElement> seen = new Set<FunctionElement>(); 139 Set<FunctionElement> seen = new Set<FunctionElement>();
125 seen.add(constructor); 140 seen.add(constructor);
126 while (redirection !== null) { 141 while (redirection !== null) {
127 if (seen.contains(redirection)) { 142 if (seen.contains(redirection)) {
128 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); 143 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
129 return; 144 return;
130 } 145 }
131 seen.add(redirection); 146 seen.add(redirection);
132 redirection = resolveConstructorRedirection(redirection); 147 redirection = resolveConstructorRedirection(resolver, redirection);
133 } 148 }
134 } 149 }
135 150
136 void checkMatchingPatchSignatures(FunctionElement origin, 151 void checkMatchingPatchSignatures(FunctionElement origin,
137 FunctionElement patch) { 152 FunctionElement patch) {
138 // TODO(johnniwinther): Stub. Implementation in a later CL. 153 // TODO(johnniwinther): Stub. Implementation in a later CL.
139 } 154 }
140 155
141 TreeElements resolveMethodElement(FunctionElement element) { 156 TreeElements resolveMethodElement(FunctionElement element) {
142 assert(invariant(element, element.isDeclaration)); 157 assert(invariant(element, element.isDeclaration));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // We have now established the following: 222 // We have now established the following:
208 // [intrface] is an interface, let's say "MyInterface". 223 // [intrface] is an interface, let's say "MyInterface".
209 // [defaultClass] is a class, let's say "MyClass". 224 // [defaultClass] is a class, let's say "MyClass".
210 225
211 // If the default class implements the interface then we must use the 226 // If the default class implements the interface then we must use the
212 // default class' name. Otherwise we look for a factory with the name 227 // default class' name. Otherwise we look for a factory with the name
213 // of the interface. 228 // of the interface.
214 SourceString name; 229 SourceString name;
215 if (defaultClass.implementsInterface(intrface)) { 230 if (defaultClass.implementsInterface(intrface)) {
216 // TODO(ahe): Don't use string replacement here. 231 // TODO(ahe): Don't use string replacement here.
217 name = new SourceString(constructor.name.slowToString().replaceFirst( 232 name = new SourceString(constructor.name.slowToString().replaceFirst(
ahe 2012/10/08 08:25:43 It is code like this I would like to get rid of.
aam-me 2012/10/09 04:08:42 This code is gone, but is replaced with another st
218 intrface.name.slowToString(), 233 intrface.name.slowToString(),
219 defaultClass.name.slowToString())); 234 defaultClass.name.slowToString()));
220 } else { 235 } else {
221 name = constructor.name; 236 name = constructor.name;
222 } 237 }
223 constructor.defaultImplementation = defaultClass.lookupConstructor(name);
224 238
239 constructor.defaultImplementation = defaultClass.lookupConstructor(
ahe 2012/10/08 08:25:43 Currently, lookupConstructor expects something lik
aam-me 2012/10/08 15:03:35 Peter, I see, but you can have multiple factor
ahe 2012/10/08 16:35:52 I'll send an email to Anton and see if he has time
aam-me 2012/10/09 04:08:42 Thanks, Peter. Further issues down the path of us
240 new Selector.callDefaultConstructor(name,
241 defaultClass.getLibrary()));
225 if (constructor.defaultImplementation === null) { 242 if (constructor.defaultImplementation === null) {
226 // We failed to find a constructor named either 243 // We failed to find a constructor named either
227 // "MyInterface.name" or "MyClass.name". 244 // "MyInterface.name" or "MyClass.name".
228 error(node, 245 error(node,
229 MessageKind.CANNOT_FIND_CONSTRUCTOR2, 246 MessageKind.CANNOT_FIND_CONSTRUCTOR2,
230 [name, defaultClass.name]); 247 [name, defaultClass.name]);
231 } 248 }
232 } 249 }
233 250
234 TreeElements resolveField(Element element) { 251 TreeElements resolveField(Element element) {
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 } else { 607 } else {
591 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 608 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
592 } 609 }
593 visitor.useElement(init, target); 610 visitor.useElement(init, target);
594 visitor.world.registerStaticUse(target); 611 visitor.world.registerStaticUse(target);
595 checkForDuplicateInitializers(name, init); 612 checkForDuplicateInitializers(name, init);
596 // Resolve initializing value. 613 // Resolve initializing value.
597 visitor.visitInStaticContext(init.arguments.head); 614 visitor.visitInStaticContext(init.arguments.head);
598 } 615 }
599 616
617 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
618 bool isSuperCall,
619 Node diagnosticNode) {
620 ClassElement lookupTarget = constructor.getEnclosingClass();
621 if (isSuperCall) {
622 // Calculate correct lookup target and constructor name.
623 if (lookupTarget === visitor.compiler.objectClass) {
624 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
625 } else {
626 lookupTarget = lookupTarget.supertype.element;
627 }
628 }
629 return lookupTarget;
630 }
631
600 Element resolveSuperOrThisForSend(FunctionElement constructor, 632 Element resolveSuperOrThisForSend(FunctionElement constructor,
601 FunctionExpression functionNode, 633 FunctionExpression functionNode,
602 Send call) { 634 Send call) {
603 // Resolve the selector and the arguments. 635 // Resolve the selector and the arguments.
604 ResolverTask resolver = visitor.compiler.resolver; 636 ResolverTask resolver = visitor.compiler.resolver;
605 visitor.inStaticContext(() { 637 visitor.inStaticContext(() {
606 visitor.resolveSelector(call); 638 visitor.resolveSelector(call);
607 visitor.resolveArguments(call.argumentsNode); 639 visitor.resolveArguments(call.argumentsNode);
608 }); 640 });
609 Selector selector = visitor.mapping.getSelector(call); 641 Selector selector = visitor.mapping.getSelector(call);
610 bool isSuperCall = Initializers.isSuperConstructorCall(call); 642 bool isSuperCall = Initializers.isSuperConstructorCall(call);
611 SourceString constructorName = resolver.getConstructorName(call); 643
612 Element result = resolveSuperOrThis( 644 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
613 constructor, isSuperCall, false, constructorName, selector, call); 645 isSuperCall,
614 visitor.useElement(call, result); 646 call);
615 visitor.world.registerStaticUse(result); 647 final SourceString className = lookupTarget.name;
616 return result; 648
649 SourceString constructorName;
650 Selector lookupSelector;
651 if (resolver.isNamedConstructor(call)) {
652 constructorName = resolver.getConstructorName(call);
653 lookupSelector = new Selector.callConstructor(
654 className,
655 constructorName,
656 visitor.enclosingElement.getLibrary());
657 } else {
658 constructorName = const SourceString('');
659 lookupSelector = new Selector.callDefaultConstructor(
660 className,
661 visitor.enclosingElement.getLibrary());
662 }
663
664 FunctionElement lookedupConstructor =
665 lookupTarget.lookupConstructor(lookupSelector);
666
667 final bool isImplicitSuperCall = false;
668 verifyThatConstructorMatchesCall(lookedupConstructor,
669 selector,
670 isImplicitSuperCall,
671 call,
672 constructorName,
673 className);
674
675 visitor.useElement(call, lookedupConstructor);
676 visitor.world.registerStaticUse(lookedupConstructor);
677 return lookedupConstructor;
617 } 678 }
618 679
619 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 680 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
620 FunctionExpression functionNode) { 681 FunctionExpression functionNode) {
621 // If the class has a super resolve the implicit super call. 682 // If the class has a super resolve the implicit super call.
622 ClassElement classElement = constructor.getEnclosingClass(); 683 ClassElement classElement = constructor.getEnclosingClass();
623 ClassElement superClass = classElement.superclass; 684 ClassElement superClass = classElement.superclass;
624 if (classElement != visitor.compiler.objectClass) { 685 if (classElement != visitor.compiler.objectClass) {
625 assert(superClass !== null); 686 assert(superClass !== null);
626 assert(superClass.resolutionState == STATE_DONE); 687 assert(superClass.resolutionState == STATE_DONE);
627 SourceString name = const SourceString(''); 688 SourceString constructorName = const SourceString('');
628 Selector call = new Selector.call(name, classElement.getLibrary(), 0); 689 Selector callToMatch = new Selector.call(
629 var element = resolveSuperOrThis(constructor, true, true, 690 constructorName,
630 name, call, functionNode); 691 classElement.getLibrary(),
631 visitor.world.registerStaticUse(element); 692 0);
693
694 final bool isSuperCall = true;
695 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
696 isSuperCall,
697 functionNode);
698 final SourceString className = lookupTarget.name;
699 Element calledConstructor = lookupTarget.lookupConstructor(
700 new Selector.callDefaultConstructor(
701 className,
702 visitor.enclosingElement.getLibrary()));
703
704 final bool isImplicitSuperCall = true;
705 verifyThatConstructorMatchesCall(calledConstructor,
706 callToMatch,
707 isImplicitSuperCall,
708 functionNode,
709 className,
710 const SourceString(''));
711
712 visitor.world.registerStaticUse(calledConstructor);
632 } 713 }
633 } 714 }
634 715
635 Element resolveSuperOrThis(FunctionElement constructor, 716 void verifyThatConstructorMatchesCall(
636 bool isSuperCall, 717 FunctionElement lookedupConstructor,
637 bool isImplicitSuperCall, 718 Selector call,
638 SourceString constructorName, 719 bool isImplicitSuperCall,
639 Selector selector, 720 Node diagnosticNode,
640 Node diagnosticNode) { 721 SourceString className,
641 ClassElement lookupTarget = constructor.getEnclosingClass(); 722 SourceString constructorName) {
642 bool validTarget = true; 723 if (lookedupConstructor === null
643 FunctionElement result; 724 || !lookedupConstructor.isGenerativeConstructor()) {
644 if (isSuperCall) { 725 var fullConstructorName =
645 // Calculate correct lookup target and constructor name. 726 visitor.compiler.resolver.createConstructorFullName(className,
646 if (lookupTarget === visitor.compiler.objectClass) { 727 constructorName);
647 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
648 } else {
649 lookupTarget = lookupTarget.supertype.element;
650 }
651 }
652
653 // Lookup constructor and try to match it to the selector.
654 ResolverTask resolver = visitor.compiler.resolver;
655 final SourceString className = lookupTarget.name;
656 result = lookupTarget.lookupConstructor(className, constructorName);
657 if (result === null || !result.isGenerativeConstructor()) {
658 String classNameString = className.slowToString();
659 String constructorNameString = constructorName.slowToString();
660 String name = (constructorName === const SourceString(''))
661 ? classNameString
662 : "$classNameString.$constructorNameString";
663 MessageKind kind = isImplicitSuperCall 728 MessageKind kind = isImplicitSuperCall
664 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 729 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
665 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 730 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
666 error(diagnosticNode, kind, [name]); 731 error(diagnosticNode, kind, [fullConstructorName]);
667 } else { 732 } else {
668 if (!selector.applies(result, visitor.compiler)) { 733 if (!call.applies(lookedupConstructor, visitor.compiler)) {
669 MessageKind kind = isImplicitSuperCall 734 MessageKind kind = isImplicitSuperCall
670 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 735 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
671 : MessageKind.NO_MATCHING_CONSTRUCTOR; 736 : MessageKind.NO_MATCHING_CONSTRUCTOR;
672 error(diagnosticNode, kind); 737 error(diagnosticNode, kind);
673 } 738 }
674 } 739 }
675 return result;
676 } 740 }
677 741
678 FunctionElement resolveRedirection(FunctionElement constructor, 742 FunctionElement resolveRedirection(FunctionElement constructor,
679 FunctionExpression functionNode) { 743 FunctionExpression functionNode) {
680 if (functionNode.initializers === null) return null; 744 if (functionNode.initializers === null) return null;
681 Link<Node> link = functionNode.initializers.nodes; 745 Link<Node> link = functionNode.initializers.nodes;
682 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) { 746 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) {
683 return resolveSuperOrThisForSend(constructor, functionNode, link.head); 747 return resolveSuperOrThisForSend(constructor, functionNode, link.head);
684 } 748 }
685 return null; 749 return null;
(...skipping 2024 matching lines...) Expand 10 before | Expand all | Expand 10 after
2710 return new ErroneousFunctionElement(kind, arguments, targetName, 2774 return new ErroneousFunctionElement(kind, arguments, targetName,
2711 enclosing); 2775 enclosing);
2712 } 2776 }
2713 } 2777 }
2714 2778
2715 // TODO(ngeoffray): method named lookup should not report errors. 2779 // TODO(ngeoffray): method named lookup should not report errors.
2716 FunctionElement lookupConstructor(ClassElement cls, 2780 FunctionElement lookupConstructor(ClassElement cls,
2717 Node diagnosticNode, 2781 Node diagnosticNode,
2718 SourceString constructorName) { 2782 SourceString constructorName) {
2719 cls.ensureResolved(compiler); 2783 cls.ensureResolved(compiler);
2720 Element result = cls.lookupConstructor(cls.name, constructorName); 2784 Selector selector =
2785 constructorName === const SourceString('')
2786 ? new Selector.callDefaultConstructor(
kasperl 2012/10/08 08:06:41 4 space indent of ? and :.
aam-me 2012/10/09 04:08:42 Done.
2787 cls.name,
2788 resolver.enclosingElement.getLibrary())
2789 : new Selector.callConstructor(cls.name,
2790 constructorName,
2791 resolver.enclosingElement.getLibrary());
2792 Element result = cls.lookupConstructor(selector);
2721 if (result === null) { 2793 if (result === null) {
2722 String fullConstructorName = cls.name.slowToString(); 2794 String fullConstructorName =
2723 if (constructorName !== const SourceString('')) { 2795 resolver.compiler.resolver.createConstructorFullName(
2724 fullConstructorName = '$fullConstructorName' 2796 cls.name,
2725 '.${constructorName.slowToString()}'; 2797 constructorName);
2726 } 2798 return failOrReturnErroneousElement(
2727 return failOrReturnErroneousElement(cls, diagnosticNode, 2799 cls,
2728 new SourceString(fullConstructorName), 2800 diagnosticNode,
2729 MessageKind.CANNOT_FIND_CONSTRUCTOR, 2801 new SourceString(fullConstructorName),
2730 [fullConstructorName]); 2802 MessageKind.CANNOT_FIND_CONSTRUCTOR,
2803 [fullConstructorName]);
2731 } else if (inConstContext && !result.modifiers.isConst()) { 2804 } else if (inConstContext && !result.modifiers.isConst()) {
2732 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 2805 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
2733 } 2806 }
2734 return result; 2807 return result;
2735 } 2808 }
2736 2809
2737 visitNewExpression(NewExpression node) { 2810 visitNewExpression(NewExpression node) {
2738 Node selector = node.send.selector; 2811 Node selector = node.send.selector;
2739 Element e = visit(selector); 2812 Element e = visit(selector);
2740 if (!Elements.isUnresolved(e) && e.kind === ElementKind.CLASS) { 2813 if (!Elements.isUnresolved(e) && e.kind === ElementKind.CLASS) {
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
3055 return result; 3128 return result;
3056 } 3129 }
3057 Element lookup(SourceString name) => localLookup(name); 3130 Element lookup(SourceString name) => localLookup(name);
3058 Element lexicalLookup(SourceString name) => localLookup(name); 3131 Element lexicalLookup(SourceString name) => localLookup(name);
3059 3132
3060 Element add(Element newElement) { 3133 Element add(Element newElement) {
3061 throw "Cannot add an element in a patch library scope"; 3134 throw "Cannot add an element in a patch library scope";
3062 } 3135 }
3063 String toString() => 'PatchLibraryScope($origin,$patch)'; 3136 String toString() => 'PatchLibraryScope($origin,$patch)';
3064 } 3137 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698