Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |