| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dart2js.resolution.constructors; | 5 library dart2js.resolution.constructors; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/resolution.dart' show | 8 import '../common/resolution.dart' show |
| 9 Feature; | 9 Feature; |
| 10 import '../compiler.dart' show | 10 import '../compiler.dart' show |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 diagnosticNode, kind, arguments); | 496 diagnosticNode, kind, arguments); |
| 497 } else { | 497 } else { |
| 498 reporter.reportWarningMessage( | 498 reporter.reportWarningMessage( |
| 499 diagnosticNode, kind, arguments); | 499 diagnosticNode, kind, arguments); |
| 500 } | 500 } |
| 501 ErroneousElement error = new ErroneousConstructorElementX( | 501 ErroneousElement error = new ErroneousConstructorElementX( |
| 502 kind, arguments, name, enclosing); | 502 kind, arguments, name, enclosing); |
| 503 if (type == null) { | 503 if (type == null) { |
| 504 type = new MalformedType(error, null); | 504 type = new MalformedType(error, null); |
| 505 } | 505 } |
| 506 return new ConstructorResult(resultKind, error, type); | 506 return new ConstructorResult.forError(resultKind, error, type); |
| 507 } | 507 } |
| 508 | 508 |
| 509 ConstructorResult resolveConstructor( | 509 ConstructorResult resolveConstructor( |
| 510 PrefixElement prefix, |
| 510 InterfaceType type, | 511 InterfaceType type, |
| 511 Node diagnosticNode, | 512 Node diagnosticNode, |
| 512 String constructorName) { | 513 String constructorName) { |
| 513 ClassElement cls = type.element; | 514 ClassElement cls = type.element; |
| 514 cls.ensureResolved(resolution); | 515 cls.ensureResolved(resolution); |
| 515 ConstructorElement constructor = findConstructor( | 516 ConstructorElement constructor = findConstructor( |
| 516 resolver.enclosingElement.library, cls, constructorName); | 517 resolver.enclosingElement.library, cls, constructorName); |
| 517 if (constructor == null) { | 518 if (constructor == null) { |
| 518 MessageKind kind = constructorName.isEmpty | 519 MessageKind kind = constructorName.isEmpty |
| 519 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR | 520 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR |
| 520 : MessageKind.CANNOT_FIND_CONSTRUCTOR; | 521 : MessageKind.CANNOT_FIND_CONSTRUCTOR; |
| 521 return reportAndCreateErroneousConstructorElement( | 522 return reportAndCreateErroneousConstructorElement( |
| 522 diagnosticNode, | 523 diagnosticNode, |
| 523 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type, | 524 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type, |
| 524 cls, constructorName, kind, | 525 cls, constructorName, kind, |
| 525 {'className': cls.name, 'constructorName': constructorName}, | 526 {'className': cls.name, 'constructorName': constructorName}, |
| 526 missingConstructor: true); | 527 missingConstructor: true); |
| 527 } else if (inConstContext && !constructor.isConst) { | 528 } else if (inConstContext && !constructor.isConst) { |
| 528 reporter.reportErrorMessage( | 529 reporter.reportErrorMessage( |
| 529 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); | 530 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); |
| 530 return new ConstructorResult( | 531 return new ConstructorResult( |
| 531 ConstructorResultKind.NON_CONSTANT, constructor, type); | 532 ConstructorResultKind.NON_CONSTANT, prefix, constructor, type); |
| 532 } else { | 533 } else { |
| 534 if (cls.isEnumClass && resolver.currentClass != cls) { |
| 535 return reportAndCreateErroneousConstructorElement( |
| 536 diagnosticNode, |
| 537 ConstructorResultKind.INVALID_TYPE, type, |
| 538 cls, constructorName, |
| 539 MessageKind.CANNOT_INSTANTIATE_ENUM, |
| 540 {'enumName': cls.name}, |
| 541 isError: true); |
| 542 } |
| 533 if (constructor.isGenerativeConstructor) { | 543 if (constructor.isGenerativeConstructor) { |
| 534 if (cls.isAbstract) { | 544 if (cls.isAbstract) { |
| 535 reporter.reportWarningMessage( | 545 reporter.reportWarningMessage( |
| 536 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION); | 546 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION); |
| 537 registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION); | 547 registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION); |
| 538 return new ConstructorResult( | 548 return new ConstructorResult( |
| 539 ConstructorResultKind.ABSTRACT, constructor, type); | 549 ConstructorResultKind.ABSTRACT, prefix, constructor, type); |
| 540 } else { | 550 } else { |
| 541 return new ConstructorResult( | 551 return new ConstructorResult( |
| 542 ConstructorResultKind.GENERATIVE, constructor, type); | 552 ConstructorResultKind.GENERATIVE, prefix, constructor, type); |
| 543 } | 553 } |
| 544 } else { | 554 } else { |
| 545 assert(invariant(diagnosticNode, constructor.isFactoryConstructor, | 555 assert(invariant(diagnosticNode, constructor.isFactoryConstructor, |
| 546 message: "Unexpected constructor $constructor.")); | 556 message: "Unexpected constructor $constructor.")); |
| 547 return new ConstructorResult( | 557 return new ConstructorResult( |
| 548 ConstructorResultKind.FACTORY, constructor, type); | 558 ConstructorResultKind.FACTORY, prefix, constructor, type); |
| 549 } | 559 } |
| 550 } | 560 } |
| 551 } | 561 } |
| 552 | 562 |
| 553 ConstructorResult visitNewExpression(NewExpression node) { | 563 ConstructorResult visitNewExpression(NewExpression node) { |
| 554 Node selector = node.send.selector; | 564 Node selector = node.send.selector; |
| 555 ConstructorResult result = visit(selector); | 565 ConstructorResult result = visit(selector); |
| 556 assert(invariant(selector, result != null, | 566 assert(invariant(selector, result != null, |
| 557 message: 'No result returned for $selector.')); | 567 message: 'No result returned for $selector.')); |
| 558 return finishConstructorReference(result, node.send.selector, node); | 568 return finishConstructorReference(result, node.send.selector, node); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 569 | 579 |
| 570 if (result.kind != null) { | 580 if (result.kind != null) { |
| 571 resolver.registry.setType(expression, result.type); | 581 resolver.registry.setType(expression, result.type); |
| 572 return result; | 582 return result; |
| 573 } | 583 } |
| 574 | 584 |
| 575 // Find the unnamed constructor if the reference resolved to a | 585 // Find the unnamed constructor if the reference resolved to a |
| 576 // class. | 586 // class. |
| 577 if (result.type != null) { | 587 if (result.type != null) { |
| 578 // The unnamed constructor may not exist, so [e] may become unresolved. | 588 // The unnamed constructor may not exist, so [e] may become unresolved. |
| 579 result = resolveConstructor(result.type, diagnosticNode, ''); | 589 result = resolveConstructor( |
| 590 result.prefix, result.type, diagnosticNode, ''); |
| 580 } else { | 591 } else { |
| 581 Element element = result.element; | 592 Element element = result.element; |
| 582 if (element.isMalformed) { | 593 if (element.isMalformed) { |
| 583 result = constructorResultForErroneous(diagnosticNode, element); | 594 result = constructorResultForErroneous(diagnosticNode, element); |
| 584 } else { | 595 } else { |
| 585 result = reportAndCreateErroneousConstructorElement( | 596 result = reportAndCreateErroneousConstructorElement( |
| 586 diagnosticNode, | 597 diagnosticNode, |
| 587 ConstructorResultKind.INVALID_TYPE, null, | 598 ConstructorResultKind.INVALID_TYPE, null, |
| 588 element, element.name, | 599 element, element.name, |
| 589 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}); | 600 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}); |
| 590 } | 601 } |
| 591 } | 602 } |
| 592 resolver.registry.setType(expression, result.type); | 603 resolver.registry.setType(expression, result.type); |
| 593 return result; | 604 return result; |
| 594 } | 605 } |
| 595 | 606 |
| 596 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { | 607 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { |
| 597 // This is not really resolving a type-annotation, but the name of the | 608 // This is not really resolving a type-annotation, but the name of the |
| 598 // constructor. Therefore we allow deferred types. | 609 // constructor. Therefore we allow deferred types. |
| 599 DartType type = resolver.resolveTypeAnnotation( | 610 DartType type = resolver.resolveTypeAnnotation( |
| 600 node, | 611 node, |
| 601 malformedIsError: inConstContext, | 612 malformedIsError: inConstContext, |
| 602 deferredIsMalformed: false); | 613 deferredIsMalformed: false); |
| 603 return constructorResultForType(node, type); | 614 Send send = node.typeName.asSend(); |
| 615 PrefixElement prefix; |
| 616 if (send != null) { |
| 617 // The type name is of the form [: prefix . identifier :]. |
| 618 String name = send.receiver.asIdentifier().source; |
| 619 Element element = resolver.reportLookupErrorIfAny( |
| 620 lookupInScope(reporter, send, resolver.scope, name), node, name); |
| 621 if (element != null && element.isPrefix) { |
| 622 prefix = element; |
| 623 } |
| 624 } |
| 625 return constructorResultForType(node, type, prefix: prefix); |
| 604 } | 626 } |
| 605 | 627 |
| 606 ConstructorResult visitSend(Send node) { | 628 ConstructorResult visitSend(Send node) { |
| 607 ConstructorResult receiver = visit(node.receiver); | 629 ConstructorResult receiver = visit(node.receiver); |
| 608 assert(invariant(node.receiver, receiver != null, | 630 assert(invariant(node.receiver, receiver != null, |
| 609 message: 'No result returned for $node.receiver.')); | 631 message: 'No result returned for $node.receiver.')); |
| 610 if (receiver.kind != null) { | 632 if (receiver.kind != null) { |
| 611 assert(invariant(node, receiver.element.isMalformed, | 633 assert(invariant(node, receiver.element.isMalformed, |
| 612 message: "Unexpected prefix result: $receiver.")); | 634 message: "Unexpected prefix result: $receiver.")); |
| 613 // We have already found an error. | 635 // We have already found an error. |
| 614 return receiver; | 636 return receiver; |
| 615 } | 637 } |
| 616 | 638 |
| 617 Identifier name = node.selector.asIdentifier(); | 639 Identifier name = node.selector.asIdentifier(); |
| 618 if (name == null) { | 640 if (name == null) { |
| 619 reporter.internalError(node.selector, 'unexpected node'); | 641 reporter.internalError(node.selector, 'unexpected node'); |
| 620 } | 642 } |
| 621 | 643 |
| 622 if (receiver.type != null) { | 644 if (receiver.type != null) { |
| 623 if (receiver.type.isInterfaceType) { | 645 if (receiver.type.isInterfaceType) { |
| 624 return resolveConstructor(receiver.type, name, name.source); | 646 return resolveConstructor( |
| 647 receiver.prefix, receiver.type, name, name.source); |
| 625 } else { | 648 } else { |
| 626 // TODO(johnniwinther): Update the message for the different types. | 649 // TODO(johnniwinther): Update the message for the different types. |
| 627 return reportAndCreateErroneousConstructorElement( | 650 return reportAndCreateErroneousConstructorElement( |
| 628 name, | 651 name, |
| 629 ConstructorResultKind.INVALID_TYPE, null, | 652 ConstructorResultKind.INVALID_TYPE, null, |
| 630 resolver.enclosingElement, name.source, | 653 resolver.enclosingElement, name.source, |
| 631 MessageKind.NOT_A_TYPE, {'node': name}); | 654 MessageKind.NOT_A_TYPE, {'node': name}); |
| 632 } | 655 } |
| 633 } else if (receiver.element.isPrefix) { | 656 } else if (receiver.element.isPrefix) { |
| 634 PrefixElement prefix = receiver.element; | 657 PrefixElement prefix = receiver.element; |
| 635 Element member = prefix.lookupLocalMember(name.source); | 658 Element member = prefix.lookupLocalMember(name.source); |
| 636 return constructorResultForElement(node, name.source, member); | 659 return constructorResultForElement( |
| 660 node, name.source, member, prefix: prefix); |
| 637 } else { | 661 } else { |
| 638 return reporter.internalError( | 662 return reporter.internalError( |
| 639 node.receiver, 'unexpected receiver $receiver'); | 663 node.receiver, 'unexpected receiver $receiver'); |
| 640 } | 664 } |
| 641 } | 665 } |
| 642 | 666 |
| 643 ConstructorResult visitIdentifier(Identifier node) { | 667 ConstructorResult visitIdentifier(Identifier node) { |
| 644 String name = node.source; | 668 String name = node.source; |
| 645 Element element = resolver.reportLookupErrorIfAny( | 669 Element element = resolver.reportLookupErrorIfAny( |
| 646 lookupInScope(reporter, node, resolver.scope, name), node, name); | 670 lookupInScope(reporter, node, resolver.scope, name), node, name); |
| 647 registry.useElement(node, element); | 671 registry.useElement(node, element); |
| 648 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. | 672 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. |
| 649 return constructorResultForElement(node, name, element); | 673 return constructorResultForElement(node, name, element); |
| 650 } | 674 } |
| 651 | 675 |
| 652 /// Assumed to be called by [resolveRedirectingFactory]. | 676 /// Assumed to be called by [resolveRedirectingFactory]. |
| 653 ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) { | 677 ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) { |
| 654 Node constructorReference = node.constructorReference; | 678 Node constructorReference = node.constructorReference; |
| 655 return finishConstructorReference(visit(constructorReference), | 679 return finishConstructorReference(visit(constructorReference), |
| 656 constructorReference, node); | 680 constructorReference, node); |
| 657 } | 681 } |
| 658 | 682 |
| 659 ConstructorResult constructorResultForElement( | 683 ConstructorResult constructorResultForElement( |
| 660 Node node, String name, Element element) { | 684 Node node, String name, Element element, |
| 685 {PrefixElement prefix}) { |
| 661 element = Elements.unwrap(element, reporter, node); | 686 element = Elements.unwrap(element, reporter, node); |
| 662 if (element == null) { | 687 if (element == null) { |
| 663 return reportAndCreateErroneousConstructorElement( | 688 return reportAndCreateErroneousConstructorElement( |
| 664 node, | 689 node, |
| 665 ConstructorResultKind.INVALID_TYPE, null, | 690 ConstructorResultKind.INVALID_TYPE, null, |
| 666 resolver.enclosingElement, name, | 691 resolver.enclosingElement, name, |
| 667 MessageKind.CANNOT_RESOLVE, | 692 MessageKind.CANNOT_RESOLVE, |
| 668 {'name': name}); | 693 {'name': name}); |
| 669 } else if (element.isMalformed) { | 694 } else if (element.isMalformed) { |
| 670 return constructorResultForErroneous(node, element); | 695 return constructorResultForErroneous(node, element); |
| 671 } else if (element.isClass) { | 696 } else if (element.isClass) { |
| 672 ClassElement cls = element; | 697 ClassElement cls = element; |
| 673 cls.computeType(resolution); | 698 cls.computeType(resolution); |
| 674 return constructorResultForType(node, cls.rawType); | 699 return constructorResultForType(node, cls.rawType, prefix: prefix); |
| 675 } else if (element.isPrefix) { | 700 } else if (element.isPrefix) { |
| 676 return new ConstructorResult.forElement(element); | 701 return new ConstructorResult.forPrefix(element); |
| 677 } else if (element.isTypedef) { | 702 } else if (element.isTypedef) { |
| 678 TypedefElement typdef = element; | 703 TypedefElement typdef = element; |
| 679 typdef.ensureResolved(resolution); | 704 typdef.ensureResolved(resolution); |
| 680 return constructorResultForType(node, typdef.rawType); | 705 return constructorResultForType(node, typdef.rawType); |
| 681 } else if (element.isTypeVariable) { | 706 } else if (element.isTypeVariable) { |
| 682 TypeVariableElement typeVariableElement = element; | 707 TypeVariableElement typeVariableElement = element; |
| 683 return constructorResultForType(node, typeVariableElement.type); | 708 return constructorResultForType(node, typeVariableElement.type); |
| 684 } else { | 709 } else { |
| 685 return reportAndCreateErroneousConstructorElement( | 710 return reportAndCreateErroneousConstructorElement( |
| 686 node, | 711 node, |
| 687 ConstructorResultKind.INVALID_TYPE, null, | 712 ConstructorResultKind.INVALID_TYPE, null, |
| 688 resolver.enclosingElement, name, | 713 resolver.enclosingElement, name, |
| 689 MessageKind.NOT_A_TYPE, {'node': name}); | 714 MessageKind.NOT_A_TYPE, {'node': name}); |
| 690 } | 715 } |
| 691 } | 716 } |
| 692 | 717 |
| 693 ConstructorResult constructorResultForErroneous( | 718 ConstructorResult constructorResultForErroneous( |
| 694 Node node, Element error) { | 719 Node node, Element error) { |
| 695 if (error is! ErroneousElementX) { | 720 if (error is! ErroneousElementX) { |
| 696 // Parser error. The error has already been reported. | 721 // Parser error. The error has already been reported. |
| 697 error = new ErroneousConstructorElementX( | 722 error = new ErroneousConstructorElementX( |
| 698 MessageKind.NOT_A_TYPE, {'node': node}, | 723 MessageKind.NOT_A_TYPE, {'node': node}, |
| 699 error.name, error); | 724 error.name, error); |
| 700 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 725 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 701 } | 726 } |
| 702 return new ConstructorResult( | 727 return new ConstructorResult.forError( |
| 703 ConstructorResultKind.INVALID_TYPE, | 728 ConstructorResultKind.INVALID_TYPE, |
| 704 error, | 729 error, |
| 705 new MalformedType(error, null)); | 730 new MalformedType(error, null)); |
| 706 } | 731 } |
| 707 | 732 |
| 708 ConstructorResult constructorResultForType( | 733 ConstructorResult constructorResultForType( |
| 709 Node node, | 734 Node node, |
| 710 DartType type) { | 735 DartType type, |
| 736 {PrefixElement prefix}) { |
| 711 String name = type.name; | 737 String name = type.name; |
| 712 if (type.isMalformed) { | 738 if (type.isMalformed) { |
| 713 return new ConstructorResult( | 739 return new ConstructorResult.forError( |
| 714 ConstructorResultKind.INVALID_TYPE, type.element, type); | 740 ConstructorResultKind.INVALID_TYPE, type.element, type); |
| 715 } else if (type.isInterfaceType) { | 741 } else if (type.isInterfaceType) { |
| 716 return new ConstructorResult.forType(type); | 742 return new ConstructorResult.forType(prefix, type); |
| 717 } else if (type.isTypedef) { | 743 } else if (type.isTypedef) { |
| 718 return reportAndCreateErroneousConstructorElement( | 744 return reportAndCreateErroneousConstructorElement( |
| 719 node, | 745 node, |
| 720 ConstructorResultKind.INVALID_TYPE, type, | 746 ConstructorResultKind.INVALID_TYPE, type, |
| 721 resolver.enclosingElement, name, | 747 resolver.enclosingElement, name, |
| 722 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name}); | 748 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name}); |
| 723 } else if (type.isTypeVariable) { | 749 } else if (type.isTypeVariable) { |
| 724 return reportAndCreateErroneousConstructorElement( | 750 return reportAndCreateErroneousConstructorElement( |
| 725 node, | 751 node, |
| 726 ConstructorResultKind.INVALID_TYPE, type, | 752 ConstructorResultKind.INVALID_TYPE, type, |
| 727 resolver.enclosingElement, name, | 753 resolver.enclosingElement, name, |
| 728 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, | 754 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, |
| 729 {'typeVariableName': name}); | 755 {'typeVariableName': name}); |
| 730 } | 756 } |
| 731 return reporter.internalError(node, "Unexpected constructor type $type"); | 757 return reporter.internalError(node, "Unexpected constructor type $type"); |
| 732 } | 758 } |
| 733 | 759 |
| 734 } | 760 } |
| 735 | 761 |
| 762 /// The kind of constructor found by the [ConstructorResolver]. |
| 736 enum ConstructorResultKind { | 763 enum ConstructorResultKind { |
| 764 /// A generative or redirecting generative constructor. |
| 737 GENERATIVE, | 765 GENERATIVE, |
| 766 /// A factory or redirecting factory constructor. |
| 738 FACTORY, | 767 FACTORY, |
| 768 /// A generative or redirecting generative constructor on an abstract class. |
| 739 ABSTRACT, | 769 ABSTRACT, |
| 770 /// No constructor was found because the type was invalid, for instance |
| 771 /// unresolved, an enum class, a type variable, a typedef or a non-type. |
| 740 INVALID_TYPE, | 772 INVALID_TYPE, |
| 773 /// No constructor of the sought name was found on the class. |
| 741 UNRESOLVED_CONSTRUCTOR, | 774 UNRESOLVED_CONSTRUCTOR, |
| 775 /// A non-constant constructor was found for a const constructor invocation. |
| 742 NON_CONSTANT, | 776 NON_CONSTANT, |
| 743 } | 777 } |
| 744 | 778 |
| 779 /// The (partial) result of the resolution of a new expression used in |
| 780 /// [ConstructorResolver]. |
| 745 class ConstructorResult { | 781 class ConstructorResult { |
| 782 /// The prefix used to access the constructor. For instance `prefix` in `new |
| 783 /// prefix.Class.constructorName()`. |
| 784 final PrefixElement prefix; |
| 785 |
| 786 /// The kind of the found constructor. |
| 746 final ConstructorResultKind kind; | 787 final ConstructorResultKind kind; |
| 788 |
| 789 /// The currently found element. Since [ConstructorResult] is used for partial |
| 790 /// results, this might be a [PrefixElement], a [ClassElement], a |
| 791 /// [ConstructorElement] or in the negative cases an [ErroneousElement]. |
| 747 final Element element; | 792 final Element element; |
| 793 |
| 794 /// The type of the new expression. For instance `Foo<String>` in |
| 795 /// `new prefix.Foo<String>.constructorName()`. |
| 748 final DartType type; | 796 final DartType type; |
| 749 | 797 |
| 750 ConstructorResult(this.kind, this.element, this.type); | 798 /// Creates a fully resolved constructor access where [element] is resolved |
| 799 /// to a constructor and [type] to an interface type. |
| 800 ConstructorResult(this.kind, |
| 801 this.prefix, |
| 802 ConstructorElement this.element, |
| 803 InterfaceType this.type); |
| 751 | 804 |
| 752 ConstructorResult.forElement(this.element) | 805 /// Creates a fully resolved constructor access where [element] is an |
| 753 : kind = null, | 806 /// [ErroneousElement]. |
| 807 // TODO(johnniwinther): Do we still need the prefix for cases like |
| 808 // `new deferred.Class.unresolvedConstructor()` ? |
| 809 ConstructorResult.forError( |
| 810 this.kind, ErroneousElement this.element, this.type) |
| 811 : prefix = null; |
| 812 |
| 813 /// Creates a constructor access that is partially resolved to a prefix. For |
| 814 /// instance `prefix` of `new prefix.Class()`. |
| 815 ConstructorResult.forPrefix(this.element) |
| 816 : prefix = null, |
| 817 kind = null, |
| 754 type = null; | 818 type = null; |
| 755 | 819 |
| 756 ConstructorResult.forType(this.type) | 820 /// Creates a constructor access that is partially resolved to a type. For |
| 821 /// instance `Foo<String>` of `new Foo<String>.constructorName()`. |
| 822 ConstructorResult.forType(this.prefix, this.type) |
| 757 : kind = null, | 823 : kind = null, |
| 758 element = null; | 824 element = null; |
| 759 | 825 |
| 826 bool get isDeferred => prefix != null && prefix.isDeferred; |
| 827 |
| 760 String toString() { | 828 String toString() { |
| 761 StringBuffer sb = new StringBuffer(); | 829 StringBuffer sb = new StringBuffer(); |
| 762 sb.write('ConstructorResult('); | 830 sb.write('ConstructorResult('); |
| 763 if (kind != null) { | 831 if (kind != null) { |
| 764 sb.write('kind=$kind,'); | 832 sb.write('kind=$kind,'); |
| 833 if (prefix != null) { |
| 834 sb.write('prefix=$prefix,'); |
| 835 } |
| 765 sb.write('element=$element,'); | 836 sb.write('element=$element,'); |
| 766 sb.write('type=$type'); | 837 sb.write('type=$type'); |
| 767 } else if (element != null) { | 838 } else if (element != null) { |
| 768 sb.write('element=$element'); | 839 sb.write('element=$element'); |
| 769 } else { | 840 } else { |
| 841 if (prefix != null) { |
| 842 sb.write('prefix=$prefix,'); |
| 843 } |
| 770 sb.write('type=$type'); | 844 sb.write('type=$type'); |
| 771 } | 845 } |
| 772 sb.write(')'); | 846 sb.write(')'); |
| 773 return sb.toString(); | 847 return sb.toString(); |
| 774 } | 848 } |
| 775 } | 849 } |
| 776 | 850 |
| 777 /// Lookup the [constructorName] constructor in [cls] and normalize the result | 851 /// Lookup the [constructorName] constructor in [cls] and normalize the result |
| 778 /// with respect to privacy and patching. | 852 /// with respect to privacy and patching. |
| 779 ConstructorElement findConstructor( | 853 ConstructorElement findConstructor( |
| 780 LibraryElement currentLibrary, | 854 LibraryElement currentLibrary, |
| 781 ClassElement cls, | 855 ClassElement cls, |
| 782 String constructorName) { | 856 String constructorName) { |
| 783 if (Name.isPrivateName(constructorName) && | 857 if (Name.isPrivateName(constructorName) && |
| 784 currentLibrary.library != cls.library) { | 858 currentLibrary.library != cls.library) { |
| 785 // TODO(johnniwinther): Report a special error on unaccessible private | 859 // TODO(johnniwinther): Report a special error on unaccessible private |
| 786 // constructors. | 860 // constructors. |
| 787 return null; | 861 return null; |
| 788 } | 862 } |
| 789 // TODO(johnniwinther): Use [Name] for lookup. | 863 // TODO(johnniwinther): Use [Name] for lookup. |
| 790 ConstructorElement constructor = cls.lookupConstructor(constructorName); | 864 ConstructorElement constructor = cls.lookupConstructor(constructorName); |
| 791 if (constructor != null) { | 865 if (constructor != null) { |
| 792 constructor = constructor.declaration; | 866 constructor = constructor.declaration; |
| 793 } | 867 } |
| 794 return constructor; | 868 return constructor; |
| 795 } | 869 } |
| OLD | NEW |