| 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 Resolution; | 8 import '../common/resolution.dart' show Resolution; |
| 9 import '../constants/constructors.dart' | 9 import '../constants/constructors.dart' |
| 10 show | 10 show |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { | 474 class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> { |
| 475 final ResolverVisitor resolver; | 475 final ResolverVisitor resolver; |
| 476 final bool inConstContext; | 476 final bool inConstContext; |
| 477 | 477 |
| 478 ConstructorResolver(Resolution resolution, this.resolver, | 478 ConstructorResolver(Resolution resolution, this.resolver, |
| 479 {bool this.inConstContext: false}) | 479 {bool this.inConstContext: false}) |
| 480 : super(resolution); | 480 : super(resolution); |
| 481 | 481 |
| 482 ResolutionRegistry get registry => resolver.registry; | 482 ResolutionRegistry get registry => resolver.registry; |
| 483 | 483 |
| 484 Element get context => resolver.enclosingElement; |
| 485 |
| 484 visitNode(Node node) { | 486 visitNode(Node node) { |
| 485 throw 'not supported'; | 487 throw 'not supported'; |
| 486 } | 488 } |
| 487 | 489 |
| 488 ConstructorResult reportAndCreateErroneousConstructorElement( | 490 ConstructorResult reportAndCreateErroneousConstructorElement( |
| 489 Spannable diagnosticNode, | 491 Spannable diagnosticNode, |
| 490 ConstructorResultKind resultKind, | 492 ConstructorResultKind resultKind, |
| 491 DartType type, | 493 DartType type, |
| 492 Element enclosing, | |
| 493 String name, | 494 String name, |
| 494 MessageKind kind, | 495 MessageKind kind, |
| 495 Map arguments, | 496 Map arguments, |
| 496 {bool isError: false, | 497 {bool isError: false, |
| 497 bool missingConstructor: false, | 498 bool missingConstructor: false, |
| 498 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { | 499 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { |
| 499 if (missingConstructor) { | 500 if (missingConstructor) { |
| 500 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); | 501 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); |
| 501 } else { | 502 } else { |
| 502 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 503 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 503 } | 504 } |
| 504 DiagnosticMessage message = | 505 DiagnosticMessage message = |
| 505 reporter.createMessage(diagnosticNode, kind, arguments); | 506 reporter.createMessage(diagnosticNode, kind, arguments); |
| 506 if (isError || inConstContext) { | 507 if (isError || inConstContext) { |
| 507 reporter.reportError(message, infos); | 508 reporter.reportError(message, infos); |
| 508 } else { | 509 } else { |
| 509 reporter.reportWarning(message, infos); | 510 reporter.reportWarning(message, infos); |
| 510 } | 511 } |
| 511 ErroneousElement error = | 512 ErroneousElement error = |
| 512 new ErroneousConstructorElementX(kind, arguments, name, enclosing); | 513 new ErroneousConstructorElementX(kind, arguments, name, context); |
| 513 if (type == null) { | 514 if (type == null) { |
| 514 type = new MalformedType(error, null); | 515 type = new MalformedType(error, null); |
| 515 } | 516 } |
| 516 return new ConstructorResult.forError(resultKind, error, type); | 517 return new ConstructorResult.forError(resultKind, error, type); |
| 517 } | 518 } |
| 518 | 519 |
| 519 ConstructorResult resolveConstructor(PrefixElement prefix, InterfaceType type, | 520 ConstructorResult resolveConstructor(PrefixElement prefix, InterfaceType type, |
| 520 Node diagnosticNode, String constructorName) { | 521 Node diagnosticNode, String constructorName) { |
| 521 ClassElement cls = type.element; | 522 ClassElement cls = type.element; |
| 522 cls.ensureResolved(resolution); | 523 cls.ensureResolved(resolution); |
| 523 ConstructorElement constructor = findConstructor( | 524 ConstructorElement constructor = findConstructor( |
| 524 resolver.enclosingElement.library, cls, constructorName); | 525 context.library, cls, constructorName); |
| 525 if (constructor == null) { | 526 if (constructor == null) { |
| 526 MessageKind kind = constructorName.isEmpty | 527 MessageKind kind = constructorName.isEmpty |
| 527 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR | 528 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR |
| 528 : MessageKind.CANNOT_FIND_CONSTRUCTOR; | 529 : MessageKind.CANNOT_FIND_CONSTRUCTOR; |
| 529 return reportAndCreateErroneousConstructorElement( | 530 return reportAndCreateErroneousConstructorElement( |
| 530 diagnosticNode, | 531 diagnosticNode, |
| 531 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, | 532 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, |
| 532 type, | 533 type, |
| 533 cls, | |
| 534 constructorName, | 534 constructorName, |
| 535 kind, | 535 kind, |
| 536 {'className': cls.name, 'constructorName': constructorName}, | 536 {'className': cls.name, 'constructorName': constructorName}, |
| 537 missingConstructor: true); | 537 missingConstructor: true); |
| 538 } else if (inConstContext && !constructor.isConst) { | 538 } else if (inConstContext && !constructor.isConst) { |
| 539 reporter.reportErrorMessage( | 539 reporter.reportErrorMessage( |
| 540 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); | 540 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); |
| 541 return new ConstructorResult( | 541 return new ConstructorResult( |
| 542 ConstructorResultKind.NON_CONSTANT, prefix, constructor, type); | 542 ConstructorResultKind.NON_CONSTANT, prefix, constructor, type); |
| 543 } else { | 543 } else { |
| 544 if (cls.isEnumClass && resolver.currentClass != cls) { | 544 if (cls.isEnumClass && resolver.currentClass != cls) { |
| 545 return reportAndCreateErroneousConstructorElement( | 545 return reportAndCreateErroneousConstructorElement( |
| 546 diagnosticNode, | 546 diagnosticNode, |
| 547 ConstructorResultKind.INVALID_TYPE, | 547 ConstructorResultKind.INVALID_TYPE, |
| 548 type, | 548 type, |
| 549 cls, | |
| 550 constructorName, | 549 constructorName, |
| 551 MessageKind.CANNOT_INSTANTIATE_ENUM, | 550 MessageKind.CANNOT_INSTANTIATE_ENUM, |
| 552 {'enumName': cls.name}, | 551 {'enumName': cls.name}, |
| 553 isError: true); | 552 isError: true); |
| 554 } | 553 } |
| 555 if (constructor.isGenerativeConstructor) { | 554 if (constructor.isGenerativeConstructor) { |
| 556 if (cls.isAbstract) { | 555 if (cls.isAbstract) { |
| 557 reporter.reportWarningMessage( | 556 reporter.reportWarningMessage( |
| 558 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION); | 557 diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION); |
| 559 registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION); | 558 registry.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 resolveConstructor(result.prefix, result.type, diagnosticNode, ''); | 599 resolveConstructor(result.prefix, result.type, diagnosticNode, ''); |
| 601 } else { | 600 } else { |
| 602 Element element = result.element; | 601 Element element = result.element; |
| 603 if (element.isMalformed) { | 602 if (element.isMalformed) { |
| 604 result = constructorResultForErroneous(diagnosticNode, element); | 603 result = constructorResultForErroneous(diagnosticNode, element); |
| 605 } else { | 604 } else { |
| 606 result = reportAndCreateErroneousConstructorElement( | 605 result = reportAndCreateErroneousConstructorElement( |
| 607 diagnosticNode, | 606 diagnosticNode, |
| 608 ConstructorResultKind.INVALID_TYPE, | 607 ConstructorResultKind.INVALID_TYPE, |
| 609 null, | 608 null, |
| 610 element, | |
| 611 element.name, | 609 element.name, |
| 612 MessageKind.NOT_A_TYPE, | 610 MessageKind.NOT_A_TYPE, |
| 613 {'node': diagnosticNode}); | 611 {'node': diagnosticNode}); |
| 614 } | 612 } |
| 615 } | 613 } |
| 616 resolver.registry.setType(expression, result.type); | 614 resolver.registry.setType(expression, result.type); |
| 617 return result; | 615 return result; |
| 618 } | 616 } |
| 619 | 617 |
| 620 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { | 618 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 if (receiver.type != null) { | 652 if (receiver.type != null) { |
| 655 if (receiver.type.isInterfaceType) { | 653 if (receiver.type.isInterfaceType) { |
| 656 return resolveConstructor( | 654 return resolveConstructor( |
| 657 receiver.prefix, receiver.type, name, name.source); | 655 receiver.prefix, receiver.type, name, name.source); |
| 658 } else { | 656 } else { |
| 659 // TODO(johnniwinther): Update the message for the different types. | 657 // TODO(johnniwinther): Update the message for the different types. |
| 660 return reportAndCreateErroneousConstructorElement( | 658 return reportAndCreateErroneousConstructorElement( |
| 661 name, | 659 name, |
| 662 ConstructorResultKind.INVALID_TYPE, | 660 ConstructorResultKind.INVALID_TYPE, |
| 663 null, | 661 null, |
| 664 resolver.enclosingElement, | |
| 665 name.source, | 662 name.source, |
| 666 MessageKind.NOT_A_TYPE, | 663 MessageKind.NOT_A_TYPE, |
| 667 {'node': name}); | 664 {'node': name}); |
| 668 } | 665 } |
| 669 } else if (receiver.element.isPrefix) { | 666 } else if (receiver.element.isPrefix) { |
| 670 PrefixElement prefix = receiver.element; | 667 PrefixElement prefix = receiver.element; |
| 671 Element member = prefix.lookupLocalMember(name.source); | 668 Element member = prefix.lookupLocalMember(name.source); |
| 672 return constructorResultForElement(node, name.source, member, | 669 return constructorResultForElement(node, name.source, member, |
| 673 prefix: prefix); | 670 prefix: prefix); |
| 674 } else { | 671 } else { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 693 | 690 |
| 694 ConstructorResult constructorResultForElement( | 691 ConstructorResult constructorResultForElement( |
| 695 Node node, String name, Element element, | 692 Node node, String name, Element element, |
| 696 {PrefixElement prefix}) { | 693 {PrefixElement prefix}) { |
| 697 element = Elements.unwrap(element, reporter, node); | 694 element = Elements.unwrap(element, reporter, node); |
| 698 if (element == null) { | 695 if (element == null) { |
| 699 return reportAndCreateErroneousConstructorElement( | 696 return reportAndCreateErroneousConstructorElement( |
| 700 node, | 697 node, |
| 701 ConstructorResultKind.INVALID_TYPE, | 698 ConstructorResultKind.INVALID_TYPE, |
| 702 null, | 699 null, |
| 703 resolver.enclosingElement, | |
| 704 name, | 700 name, |
| 705 MessageKind.CANNOT_RESOLVE, | 701 MessageKind.CANNOT_RESOLVE, |
| 706 {'name': name}); | 702 {'name': name}); |
| 707 } else if (element.isAmbiguous) { | 703 } else if (element.isAmbiguous) { |
| 708 AmbiguousElement ambiguous = element; | 704 AmbiguousElement ambiguous = element; |
| 709 return reportAndCreateErroneousConstructorElement( | 705 return reportAndCreateErroneousConstructorElement( |
| 710 node, | 706 node, |
| 711 ConstructorResultKind.INVALID_TYPE, | 707 ConstructorResultKind.INVALID_TYPE, |
| 712 null, | 708 null, |
| 713 resolver.enclosingElement, | |
| 714 name, | 709 name, |
| 715 ambiguous.messageKind, | 710 ambiguous.messageKind, |
| 716 ambiguous.messageArguments, | 711 ambiguous.messageArguments, |
| 717 infos: ambiguous.computeInfos(resolver.enclosingElement, reporter)); | 712 infos: ambiguous.computeInfos(context, reporter)); |
| 718 } else if (element.isMalformed) { | 713 } else if (element.isMalformed) { |
| 719 return constructorResultForErroneous(node, element); | 714 return constructorResultForErroneous(node, element); |
| 720 } else if (element.isClass) { | 715 } else if (element.isClass) { |
| 721 ClassElement cls = element; | 716 ClassElement cls = element; |
| 722 cls.computeType(resolution); | 717 cls.computeType(resolution); |
| 723 return constructorResultForType(node, cls.rawType, prefix: prefix); | 718 return constructorResultForType(node, cls.rawType, prefix: prefix); |
| 724 } else if (element.isPrefix) { | 719 } else if (element.isPrefix) { |
| 725 return new ConstructorResult.forPrefix(element); | 720 return new ConstructorResult.forPrefix(element); |
| 726 } else if (element.isTypedef) { | 721 } else if (element.isTypedef) { |
| 727 TypedefElement typdef = element; | 722 TypedefElement typdef = element; |
| 728 typdef.ensureResolved(resolution); | 723 typdef.ensureResolved(resolution); |
| 729 return constructorResultForType(node, typdef.rawType); | 724 return constructorResultForType(node, typdef.rawType); |
| 730 } else if (element.isTypeVariable) { | 725 } else if (element.isTypeVariable) { |
| 731 TypeVariableElement typeVariableElement = element; | 726 TypeVariableElement typeVariableElement = element; |
| 732 return constructorResultForType(node, typeVariableElement.type); | 727 return constructorResultForType(node, typeVariableElement.type); |
| 733 } else { | 728 } else { |
| 734 return reportAndCreateErroneousConstructorElement( | 729 return reportAndCreateErroneousConstructorElement( |
| 735 node, | 730 node, |
| 736 ConstructorResultKind.INVALID_TYPE, | 731 ConstructorResultKind.INVALID_TYPE, |
| 737 null, | 732 null, |
| 738 resolver.enclosingElement, | |
| 739 name, | 733 name, |
| 740 MessageKind.NOT_A_TYPE, | 734 MessageKind.NOT_A_TYPE, |
| 741 {'node': name}); | 735 {'node': name}); |
| 742 } | 736 } |
| 743 } | 737 } |
| 744 | 738 |
| 745 ConstructorResult constructorResultForErroneous(Node node, Element error) { | 739 ConstructorResult constructorResultForErroneous(Node node, Element error) { |
| 746 if (error is! ErroneousElementX) { | 740 if (error is! ErroneousElementX) { |
| 747 // Parser error. The error has already been reported. | 741 // Parser error. The error has already been reported. |
| 748 error = new ErroneousConstructorElementX( | 742 error = new ErroneousConstructorElementX( |
| 749 MessageKind.NOT_A_TYPE, {'node': node}, error.name, error); | 743 MessageKind.NOT_A_TYPE, {'node': node}, error.name, error); |
| 750 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 744 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 751 } | 745 } |
| 752 return new ConstructorResult.forError(ConstructorResultKind.INVALID_TYPE, | 746 return new ConstructorResult.forError(ConstructorResultKind.INVALID_TYPE, |
| 753 error, new MalformedType(error, null)); | 747 error, new MalformedType(error, null)); |
| 754 } | 748 } |
| 755 | 749 |
| 756 ConstructorResult constructorResultForType(Node node, DartType type, | 750 ConstructorResult constructorResultForType(Node node, DartType type, |
| 757 {PrefixElement prefix}) { | 751 {PrefixElement prefix}) { |
| 758 String name = type.name; | 752 String name = type.name; |
| 759 if (type.isTypeVariable) { | 753 if (type.isTypeVariable) { |
| 760 return reportAndCreateErroneousConstructorElement( | 754 return reportAndCreateErroneousConstructorElement( |
| 761 node, | 755 node, |
| 762 ConstructorResultKind.INVALID_TYPE, | 756 ConstructorResultKind.INVALID_TYPE, |
| 763 type, | 757 type, |
| 764 resolver.enclosingElement, | |
| 765 name, | 758 name, |
| 766 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, | 759 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, |
| 767 {'typeVariableName': name}); | 760 {'typeVariableName': name}); |
| 768 } else if (type.isMalformed) { | 761 } else if (type.isMalformed) { |
| 769 // `type is MalformedType`: `MethodTypeVariableType` is handled above. | 762 // `type is MalformedType`: `MethodTypeVariableType` is handled above. |
| 770 return new ConstructorResult.forError( | 763 return new ConstructorResult.forError( |
| 771 ConstructorResultKind.INVALID_TYPE, type.element, type); | 764 ConstructorResultKind.INVALID_TYPE, type.element, type); |
| 772 } else if (type.isInterfaceType) { | 765 } else if (type.isInterfaceType) { |
| 773 return new ConstructorResult.forType(prefix, type); | 766 return new ConstructorResult.forType(prefix, type); |
| 774 } else if (type.isTypedef) { | 767 } else if (type.isTypedef) { |
| 775 return reportAndCreateErroneousConstructorElement( | 768 return reportAndCreateErroneousConstructorElement( |
| 776 node, | 769 node, |
| 777 ConstructorResultKind.INVALID_TYPE, | 770 ConstructorResultKind.INVALID_TYPE, |
| 778 type, | 771 type, |
| 779 resolver.enclosingElement, | |
| 780 name, | 772 name, |
| 781 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, | 773 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, |
| 782 {'typedefName': name}); | 774 {'typedefName': name}); |
| 783 } | 775 } |
| 784 return reporter.internalError(node, "Unexpected constructor type $type"); | 776 return reporter.internalError(node, "Unexpected constructor type $type"); |
| 785 } | 777 } |
| 786 } | 778 } |
| 787 | 779 |
| 788 /// The kind of constructor found by the [ConstructorResolver]. | 780 /// The kind of constructor found by the [ConstructorResolver]. |
| 789 enum ConstructorResultKind { | 781 enum ConstructorResultKind { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 // constructors. | 879 // constructors. |
| 888 return null; | 880 return null; |
| 889 } | 881 } |
| 890 // TODO(johnniwinther): Use [Name] for lookup. | 882 // TODO(johnniwinther): Use [Name] for lookup. |
| 891 ConstructorElement constructor = cls.lookupConstructor(constructorName); | 883 ConstructorElement constructor = cls.lookupConstructor(constructorName); |
| 892 if (constructor != null) { | 884 if (constructor != null) { |
| 893 constructor = constructor.declaration; | 885 constructor = constructor.declaration; |
| 894 } | 886 } |
| 895 return constructor; | 887 return constructor; |
| 896 } | 888 } |
| OLD | NEW |