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

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: Another attempt at implementing private-aware constructor lookup logic - with normalized constructo… 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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 if (kind === ElementKind.PARAMETER || 78 if (kind === ElementKind.PARAMETER ||
79 kind === ElementKind.FIELD_PARAMETER) { 79 kind === ElementKind.FIELD_PARAMETER) {
80 return resolveParameter(element); 80 return resolveParameter(element);
81 } 81 }
82 82
83 compiler.unimplemented("resolve($element)", 83 compiler.unimplemented("resolve($element)",
84 node: element.parseNode(compiler)); 84 node: element.parseNode(compiler));
85 }); 85 });
86 } 86 }
87 87
88 SourceString getConstructorName(Send node) { 88 bool isNamedConstructor(Send node) => node.receiver !== null;
89 if (node.receiver !== null) { 89 SourceString getConstructorName(Send node) => node.selector.asIdentifier().sou rce;
kasperl 2012/09/28 08:48:54 Line a bit too long.
90 return node.selector.asIdentifier().source; 90
91 } else { 91 String createConstructorFullName(SourceString className,
92 return const SourceString(''); 92 SourceString constructorName) {
93 } 93 String classNameString = className.slowToString();
94 String constructorNameString = constructorName.slowToString();
95 return (constructorName === const SourceString(''))
96 ? classNameString
kasperl 2012/09/28 08:48:54 4 space indent.
97 : "$classNameString.$constructorNameString";
94 } 98 }
95 99
96 FunctionElement resolveConstructorRedirection(FunctionElement constructor) { 100 FunctionElement resolveConstructorRedirection(FunctionElement constructor) {
97 FunctionExpression node = constructor.parseNode(compiler); 101 FunctionExpression node = constructor.parseNode(compiler);
98 // A synthetic constructor does not have a node. 102 // A synthetic constructor does not have a node.
99 if (node === null) return null; 103 if (node === null) return null;
100 if (node.initializers === null) return null; 104 if (node.initializers === null) return null;
101 Link<Node> initializers = node.initializers.nodes; 105 Link<Node> initializers = node.initializers.nodes;
102 if (!initializers.isEmpty() && 106 if (!initializers.isEmpty() &&
103 Initializers.isConstructorRedirect(initializers.head)) { 107 Initializers.isConstructorRedirect(initializers.head)) {
104 final ClassElement classElement = constructor.getEnclosingClass(); 108 final ClassElement classElement = constructor.getEnclosingClass();
105 final SourceString constructorName = 109 Selector selector;
106 getConstructorName(initializers.head); 110 if (isNamedConstructor(initializers.head)) {
107 final SourceString className = classElement.name; 111 SourceString constructorName = getConstructorName(initializers.head);
108 return classElement.lookupConstructor(className, constructorName); 112 selector = new Selector.callConstructor(classElement.name,
113 constructorName,
114 constructor.getLibrary());
kasperl 2012/09/28 08:48:54 I'm still a bit worried about computing the librar
115 } else {
116 selector = new Selector.callDefaultConstructor(
117 classElement.name,
118 constructor.getLibrary());
119 }
120 return classElement.lookupConstructor(selector);
109 } 121 }
110 return null; 122 return null;
111 } 123 }
112 124
113 void resolveRedirectingConstructor(InitializerResolver resolver, 125 void resolveRedirectingConstructor(InitializerResolver resolver,
114 Node node, 126 Node node,
115 FunctionElement constructor, 127 FunctionElement constructor,
116 FunctionElement redirection) { 128 FunctionElement redirection) {
117 Set<FunctionElement> seen = new Set<FunctionElement>(); 129 Set<FunctionElement> seen = new Set<FunctionElement>();
118 seen.add(constructor); 130 seen.add(constructor);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 // of the interface. 207 // of the interface.
196 SourceString name; 208 SourceString name;
197 if (defaultClass.implementsInterface(intrface)) { 209 if (defaultClass.implementsInterface(intrface)) {
198 // TODO(ahe): Don't use string replacement here. 210 // TODO(ahe): Don't use string replacement here.
199 name = new SourceString(constructor.name.slowToString().replaceFirst( 211 name = new SourceString(constructor.name.slowToString().replaceFirst(
200 intrface.name.slowToString(), 212 intrface.name.slowToString(),
201 defaultClass.name.slowToString())); 213 defaultClass.name.slowToString()));
202 } else { 214 } else {
203 name = constructor.name; 215 name = constructor.name;
204 } 216 }
205 constructor.defaultImplementation = defaultClass.lookupConstructor(name); 217 constructor.defaultImplementation = defaultClass.lookupConstructor(
206 218 new Selector.callDefaultConstructor(name,
219 defaultClass.getLibrary()));
207 if (constructor.defaultImplementation === null) { 220 if (constructor.defaultImplementation === null) {
208 // We failed to find a constructor named either 221 // We failed to find a constructor named either
209 // "MyInterface.name" or "MyClass.name". 222 // "MyInterface.name" or "MyClass.name".
210 error(node, 223 error(node,
211 MessageKind.CANNOT_FIND_CONSTRUCTOR2, 224 MessageKind.CANNOT_FIND_CONSTRUCTOR2,
212 [name, defaultClass.name]); 225 [name, defaultClass.name]);
213 } 226 }
214 } 227 }
215 228
216 TreeElements resolveField(Element element) { 229 TreeElements resolveField(Element element) {
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 } else { 559 } else {
547 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 560 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
548 } 561 }
549 visitor.useElement(init, target); 562 visitor.useElement(init, target);
550 visitor.world.registerStaticUse(target); 563 visitor.world.registerStaticUse(target);
551 checkForDuplicateInitializers(name, init); 564 checkForDuplicateInitializers(name, init);
552 // Resolve initializing value. 565 // Resolve initializing value.
553 visitor.visitInStaticContext(init.arguments.head); 566 visitor.visitInStaticContext(init.arguments.head);
554 } 567 }
555 568
569 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
570 bool isSuperCall,
571 Node diagnosticNode) {
572 ClassElement lookupTarget = constructor.getEnclosingClass();
573 if (isSuperCall) {
574 // Calculate correct lookup target and constructor name.
575 if (lookupTarget === visitor.compiler.objectClass) {
576 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
577 } else {
578 lookupTarget = lookupTarget.supertype.element;
579 }
580 }
581 return lookupTarget;
582 }
583
556 Element resolveSuperOrThisForSend(FunctionElement constructor, 584 Element resolveSuperOrThisForSend(FunctionElement constructor,
557 FunctionExpression functionNode, 585 FunctionExpression functionNode,
558 Send call) { 586 Send call) {
559 // Resolve the selector and the arguments. 587 // Resolve the selector and the arguments.
560 ResolverTask resolver = visitor.compiler.resolver; 588 ResolverTask resolver = visitor.compiler.resolver;
561 visitor.inStaticContext(() { 589 visitor.inStaticContext(() {
562 visitor.resolveSelector(call); 590 visitor.resolveSelector(call);
563 visitor.resolveArguments(call.argumentsNode); 591 visitor.resolveArguments(call.argumentsNode);
564 }); 592 });
565 Selector selector = visitor.mapping.getSelector(call); 593 Selector selector = visitor.mapping.getSelector(call);
566 bool isSuperCall = Initializers.isSuperConstructorCall(call); 594 bool isSuperCall = Initializers.isSuperConstructorCall(call);
567 SourceString constructorName = resolver.getConstructorName(call); 595
568 Element result = resolveSuperOrThis( 596 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
569 constructor, isSuperCall, false, constructorName, selector, call); 597 isSuperCall,
570 visitor.useElement(call, result); 598 call);
571 visitor.world.registerStaticUse(result); 599 final SourceString className = lookupTarget.name;
572 return result; 600
601 SourceString constructorName;
602 Selector lookupSelector;
603 if (resolver.isNamedConstructor(call)) {
604 constructorName = resolver.getConstructorName(call);
605 lookupSelector = new Selector.callConstructor(
606 className,
607 constructorName,
608 visitor.enclosingElement.getLibrary());
609 } else {
610 constructorName = const SourceString('');
611 lookupSelector = new Selector.callDefaultConstructor(
612 className,
613 visitor.enclosingElement.getLibrary());
614 }
615
616 FunctionElement lookedupConstructor =
617 lookupTarget.lookupConstructor(lookupSelector);
618
619 final bool isImplicitSuperCall = false;
620 verifyThatConstructorMatchesCall(lookedupConstructor,
621 selector,
622 isImplicitSuperCall,
623 call,
624 constructorName,
625 className);
626
627 visitor.useElement(call, lookedupConstructor);
628 visitor.world.registerStaticUse(lookedupConstructor);
629 return lookedupConstructor;
573 } 630 }
574 631
575 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 632 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
576 FunctionExpression functionNode) { 633 FunctionExpression functionNode) {
577 // If the class has a super resolve the implicit super call. 634 // If the class has a super resolve the implicit super call.
578 ClassElement classElement = constructor.getEnclosingClass(); 635 ClassElement classElement = constructor.getEnclosingClass();
579 ClassElement superClass = classElement.superclass; 636 ClassElement superClass = classElement.superclass;
580 if (classElement != visitor.compiler.objectClass) { 637 if (classElement != visitor.compiler.objectClass) {
581 assert(superClass !== null); 638 assert(superClass !== null);
582 assert(superClass.resolutionState == STATE_DONE); 639 assert(superClass.resolutionState == STATE_DONE);
583 SourceString name = const SourceString(''); 640 SourceString constructorName = const SourceString('');
584 Selector call = new Selector.call(name, classElement.getLibrary(), 0); 641 Selector callToMatch = new Selector.call(
585 var element = resolveSuperOrThis(constructor, true, true, 642 constructorName,
586 name, call, functionNode); 643 classElement.getLibrary(),
587 visitor.world.registerStaticUse(element); 644 0);
645
646 final bool isSuperCall = true;
647 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
648 isSuperCall,
649 functionNode);
650 final SourceString className = lookupTarget.name;
651 Element calledConstructor = lookupTarget.lookupConstructor(
652 new Selector.callDefaultConstructor(
653 className,
654 visitor.enclosingElement.getLibrary()));
655
656 final bool isImplicitSuperCall = true;
657 verifyThatConstructorMatchesCall(calledConstructor,
658 callToMatch,
659 isImplicitSuperCall,
660 functionNode,
661 className,
662 const SourceString(''));
663
664 visitor.world.registerStaticUse(calledConstructor);
588 } 665 }
589 } 666 }
590 667
591 Element resolveSuperOrThis(FunctionElement constructor, 668 void verifyThatConstructorMatchesCall(
592 bool isSuperCall, 669 FunctionElement lookedupConstructor,
593 bool isImplicitSuperCall, 670 Selector call,
594 SourceString constructorName, 671 bool isImplicitSuperCall,
595 Selector selector, 672 Node diagnosticNode,
596 Node diagnosticNode) { 673 SourceString className,
597 ClassElement lookupTarget = constructor.getEnclosingClass(); 674 SourceString constructorName) {
598 bool validTarget = true; 675 if (lookedupConstructor === null
599 FunctionElement result; 676 || !lookedupConstructor.isGenerativeConstructor()) {
600 if (isSuperCall) { 677 var fullConstructorName =
601 // Calculate correct lookup target and constructor name. 678 visitor.compiler.resolver.createConstructorFullName(className,
602 if (lookupTarget === visitor.compiler.objectClass) { 679 constructorName);
603 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
604 } else {
605 lookupTarget = lookupTarget.supertype.element;
606 }
607 }
608
609 // Lookup constructor and try to match it to the selector.
610 ResolverTask resolver = visitor.compiler.resolver;
611 final SourceString className = lookupTarget.name;
612 result = lookupTarget.lookupConstructor(className, constructorName);
613 if (result === null || !result.isGenerativeConstructor()) {
614 String classNameString = className.slowToString();
615 String constructorNameString = constructorName.slowToString();
616 String name = (constructorName === const SourceString(''))
617 ? classNameString
618 : "$classNameString.$constructorNameString";
619 MessageKind kind = isImplicitSuperCall 680 MessageKind kind = isImplicitSuperCall
620 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 681 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
621 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 682 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
622 error(diagnosticNode, kind, [name]); 683 error(diagnosticNode, kind, [fullConstructorName]);
623 } else { 684 } else {
624 if (!selector.applies(result, visitor.compiler)) { 685 if (!call.applies(lookedupConstructor, visitor.compiler)) {
625 MessageKind kind = isImplicitSuperCall 686 MessageKind kind = isImplicitSuperCall
626 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 687 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
627 : MessageKind.NO_MATCHING_CONSTRUCTOR; 688 : MessageKind.NO_MATCHING_CONSTRUCTOR;
628 error(diagnosticNode, kind); 689 error(diagnosticNode, kind);
629 } 690 }
630 } 691 }
631 return result;
632 } 692 }
633 693
634 FunctionElement resolveRedirection(FunctionElement constructor, 694 FunctionElement resolveRedirection(FunctionElement constructor,
635 FunctionExpression functionNode) { 695 FunctionExpression functionNode) {
636 if (functionNode.initializers === null) return null; 696 if (functionNode.initializers === null) return null;
637 Link<Node> link = functionNode.initializers.nodes; 697 Link<Node> link = functionNode.initializers.nodes;
638 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) { 698 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) {
639 return resolveSuperOrThisForSend(constructor, functionNode, link.head); 699 return resolveSuperOrThisForSend(constructor, functionNode, link.head);
640 } 700 }
641 return null; 701 return null;
(...skipping 1998 matching lines...) Expand 10 before | Expand all | Expand 10 after
2640 return new ErroneousFunctionElement(kind, arguments, targetName, 2700 return new ErroneousFunctionElement(kind, arguments, targetName,
2641 enclosing); 2701 enclosing);
2642 } 2702 }
2643 } 2703 }
2644 2704
2645 // TODO(ngeoffray): method named lookup should not report errors. 2705 // TODO(ngeoffray): method named lookup should not report errors.
2646 FunctionElement lookupConstructor(ClassElement cls, 2706 FunctionElement lookupConstructor(ClassElement cls,
2647 Node diagnosticNode, 2707 Node diagnosticNode,
2648 SourceString constructorName) { 2708 SourceString constructorName) {
2649 cls.ensureResolved(compiler); 2709 cls.ensureResolved(compiler);
2650 Element result = cls.lookupConstructor(cls.name, constructorName); 2710 Selector selector =
2711 constructorName === const SourceString('')
2712 ? new Selector.callDefaultConstructor(
2713 cls.name,
2714 resolver.enclosingElement.getLibrary())
2715 : new Selector.callConstructor(cls.name,
2716 constructorName,
2717 resolver.enclosingElement.getLibrary());
2718 Element result = cls.lookupConstructor(selector);
2651 if (result === null) { 2719 if (result === null) {
2652 String fullConstructorName = cls.name.slowToString(); 2720 String fullConstructorName =
2653 if (constructorName !== const SourceString('')) { 2721 resolver.compiler.resolver.createConstructorFullName(
2654 fullConstructorName = '$fullConstructorName' 2722 cls.name,
2655 '.${constructorName.slowToString()}'; 2723 constructorName);
2656 } 2724 return failOrReturnErroneousElement(
2657 return failOrReturnErroneousElement(cls, diagnosticNode, 2725 cls,
2658 new SourceString(fullConstructorName), 2726 diagnosticNode,
2659 MessageKind.CANNOT_FIND_CONSTRUCTOR, 2727 new SourceString(fullConstructorName),
2660 [fullConstructorName]); 2728 MessageKind.CANNOT_FIND_CONSTRUCTOR,
2729 [fullConstructorName]);
2661 } else if (inConstContext && 2730 } else if (inConstContext &&
2662 (result.modifiers == null || !result.modifiers.isConst())) { 2731 (result.modifiers == null || !result.modifiers.isConst())) {
2663 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 2732 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
2664 } 2733 }
2665 return result; 2734 return result;
2666 } 2735 }
2667 2736
2668 visitNewExpression(NewExpression node) { 2737 visitNewExpression(NewExpression node) {
2669 Node selector = node.send.selector; 2738 Node selector = node.send.selector;
2670 Element e = visit(selector); 2739 Element e = visit(selector);
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2871 2940
2872 Element localLookup(SourceString name) => library.find(name); 2941 Element localLookup(SourceString name) => library.find(name);
2873 Element lookup(SourceString name) => localLookup(name); 2942 Element lookup(SourceString name) => localLookup(name);
2874 Element lexicalLookup(SourceString name) => localLookup(name); 2943 Element lexicalLookup(SourceString name) => localLookup(name);
2875 2944
2876 Element add(Element newElement) { 2945 Element add(Element newElement) {
2877 throw "Cannot add an element in the top scope"; 2946 throw "Cannot add an element in the top scope";
2878 } 2947 }
2879 String toString() => '$element'; 2948 String toString() => '$element';
2880 } 2949 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698