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 library dart2js.resolution.members; | 5 library dart2js.resolution.members; |
| 6 | 6 |
| 7 import '../common/names.dart' show | 7 import '../common/names.dart' show |
| 8 Selectors; | 8 Selectors; |
| 9 import '../compiler.dart' show | 9 import '../compiler.dart' show |
| 10 Compiler, | 10 Compiler, |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 } | 632 } |
| 633 | 633 |
| 634 ResolutionResult visitIf(If node) { | 634 ResolutionResult visitIf(If node) { |
| 635 doInPromotionScope(node.condition.expression, () => visit(node.condition)); | 635 doInPromotionScope(node.condition.expression, () => visit(node.condition)); |
| 636 doInPromotionScope(node.thenPart, | 636 doInPromotionScope(node.thenPart, |
| 637 () => visitIn(node.thenPart, new BlockScope(scope))); | 637 () => visitIn(node.thenPart, new BlockScope(scope))); |
| 638 visitIn(node.elsePart, new BlockScope(scope)); | 638 visitIn(node.elsePart, new BlockScope(scope)); |
| 639 return const NoneResult(); | 639 return const NoneResult(); |
| 640 } | 640 } |
| 641 | 641 |
| 642 ResolutionResult resolveSend(Send node) { | |
| 643 Selector selector = resolveSelector(node, null); | |
| 644 if (node.isSuperCall) registry.registerSuperUse(node); | |
| 645 | |
| 646 if (node.receiver == null) { | |
| 647 // If this send is of the form "assert(expr);", then | |
| 648 // this is an assertion. | |
| 649 if (selector.isAssert) { | |
| 650 internalError(node, "Unexpected assert: $node"); | |
| 651 } | |
| 652 | |
| 653 return node.selector.accept(this); | |
| 654 } | |
| 655 | |
| 656 var oldCategory = allowedCategory; | |
| 657 allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER; | |
| 658 | |
| 659 bool oldSendIsMemberAccess = sendIsMemberAccess; | |
| 660 int oldAllowedCategory = allowedCategory; | |
| 661 | |
| 662 // Conditional sends like `e?.foo` treat the receiver as an expression. So | |
| 663 // `C?.foo` needs to be treated like `(C).foo`, not like C.foo. Prefixes and | |
| 664 // super are not allowed on their own in that context. | |
| 665 if (node.isConditional) { | |
| 666 sendIsMemberAccess = false; | |
| 667 allowedCategory = | |
| 668 ElementCategory.VARIABLE | | |
| 669 ElementCategory.FUNCTION | | |
| 670 ElementCategory.IMPLIES_TYPE; | |
| 671 } | |
| 672 ResolutionResult resolvedReceiver = visit(node.receiver); | |
| 673 if (node.isConditional) { | |
| 674 sendIsMemberAccess = oldSendIsMemberAccess; | |
| 675 allowedCategory = oldAllowedCategory; | |
| 676 } | |
| 677 | |
| 678 allowedCategory = oldCategory; | |
| 679 | |
| 680 Element target; | |
| 681 String name = node.selector.asIdentifier().source; | |
| 682 if (identical(name, 'this')) { | |
| 683 error(node.selector, MessageKind.THIS_PROPERTY); | |
| 684 return const NoneResult(); | |
| 685 } else if (node.isSuperCall) { | |
| 686 if (node.isOperator) { | |
| 687 if (isUserDefinableOperator(name)) { | |
| 688 name = selector.name; | |
| 689 } else { | |
| 690 error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name}); | |
| 691 return const NoneResult(); | |
| 692 } | |
| 693 } | |
| 694 if (!inInstanceContext) { | |
| 695 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name}); | |
| 696 return const NoneResult(); | |
| 697 } | |
| 698 if (currentClass.supertype == null) { | |
| 699 // This is just to guard against internal errors, so no need | |
| 700 // for a real error message. | |
| 701 error(node.receiver, MessageKind.GENERIC, | |
| 702 {'text': "Object has no superclass"}); | |
| 703 return const NoneResult(); | |
| 704 } | |
| 705 // TODO(johnniwinther): Ensure correct behavior if currentClass is a | |
| 706 // patch. | |
| 707 target = currentClass.lookupSuperByName(selector.memberName); | |
| 708 // [target] may be null which means invoking noSuchMethod on | |
| 709 // super. | |
| 710 if (target == null) { | |
| 711 target = reportAndCreateErroneousElement( | |
| 712 node, name, MessageKind.NO_SUCH_SUPER_MEMBER, | |
| 713 {'className': currentClass.name, 'memberName': name}); | |
| 714 // We still need to register the invocation, because we might | |
| 715 // call [:super.noSuchMethod:] which calls | |
| 716 // [JSInvocationMirror._invokeOn]. | |
| 717 registry.registerDynamicInvocation( | |
| 718 new UniverseSelector(selector, null)); | |
| 719 registry.registerSuperNoSuchMethod(); | |
| 720 } | |
| 721 } else if (Elements.isUnresolved(resolvedReceiver.element)) { | |
| 722 return const NoneResult(); | |
| 723 } else if (resolvedReceiver.element.isClass) { | |
| 724 ClassElement receiverClass = resolvedReceiver.element; | |
| 725 receiverClass.ensureResolved(compiler); | |
| 726 if (node.isOperator) { | |
| 727 // When the resolved receiver is a class, we can have two cases: | |
| 728 // 1) a static send: C.foo, or | |
| 729 // 2) an operator send, where the receiver is a class literal: 'C + 1'. | |
| 730 // The following code that looks up the selector on the resolved | |
| 731 // receiver will treat the second as the invocation of a static operator | |
| 732 // if the resolved receiver is not null. | |
| 733 return const NoneResult(); | |
| 734 } | |
| 735 MembersCreator.computeClassMembersByName( | |
| 736 compiler, receiverClass.declaration, name); | |
| 737 target = receiverClass.lookupLocalMember(name); | |
| 738 if (target == null || target.isInstanceMember) { | |
| 739 registry.registerThrowNoSuchMethod(); | |
| 740 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | |
| 741 // try to resolve injected elements if [currentClass] is in the patch | |
| 742 // library of [receiverClass]. | |
| 743 | |
| 744 // TODO(karlklose): this should be reported by the caller of | |
| 745 // [resolveSend] to select better warning messages for getters and | |
| 746 // setters. | |
| 747 MessageKind kind = (target == null) | |
| 748 ? MessageKind.MEMBER_NOT_FOUND | |
| 749 : MessageKind.MEMBER_NOT_STATIC; | |
| 750 return new ElementResult(reportAndCreateErroneousElement( | |
| 751 node, name, kind, | |
| 752 {'className': receiverClass.name, 'memberName': name})); | |
| 753 } else if (isPrivateName(name) && | |
| 754 target.library != enclosingElement.library) { | |
| 755 registry.registerThrowNoSuchMethod(); | |
| 756 return new ElementResult(reportAndCreateErroneousElement( | |
| 757 node, name, MessageKind.PRIVATE_ACCESS, | |
| 758 {'libraryName': target.library.getLibraryOrScriptName(), | |
| 759 'name': name})); | |
| 760 } | |
| 761 } else if (resolvedReceiver.element.isPrefix) { | |
| 762 PrefixElement prefix = resolvedReceiver.element; | |
| 763 target = prefix.lookupLocalMember(name); | |
| 764 if (Elements.isUnresolved(target)) { | |
| 765 registry.registerThrowNoSuchMethod(); | |
| 766 return new ElementResult(reportAndCreateErroneousElement( | |
| 767 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, | |
| 768 {'libraryName': prefix.name, 'memberName': name})); | |
| 769 } else if (target.isAmbiguous) { | |
| 770 registry.registerThrowNoSuchMethod(); | |
| 771 AmbiguousElement ambiguous = target; | |
| 772 target = reportAndCreateErroneousElement( | |
| 773 node, name, ambiguous.messageKind, ambiguous.messageArguments); | |
| 774 ambiguous.diagnose(enclosingElement, compiler); | |
| 775 return new ElementResult(target); | |
| 776 } else if (target.kind == ElementKind.CLASS) { | |
| 777 ClassElement classElement = target; | |
| 778 classElement.ensureResolved(compiler); | |
| 779 } | |
| 780 } | |
| 781 return new ResolutionResult.forElement(target); | |
| 782 } | |
| 783 | |
| 784 static Selector computeSendSelector(Send node, | 642 static Selector computeSendSelector(Send node, |
| 785 LibraryElement library, | 643 LibraryElement library, |
| 786 Element element) { | 644 Element element) { |
| 787 // First determine if this is part of an assignment. | 645 // First determine if this is part of an assignment. |
| 788 bool isSet = node.asSendSet() != null; | 646 bool isSet = node.asSendSet() != null; |
| 789 | 647 |
| 790 if (node.isIndex) { | 648 if (node.isIndex) { |
| 791 return isSet ? new Selector.indexSet() : new Selector.index(); | 649 return isSet ? new Selector.indexSet() : new Selector.index(); |
| 792 } | 650 } |
| 793 | 651 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 893 } | 751 } |
| 894 argumentCount++; | 752 argumentCount++; |
| 895 } | 753 } |
| 896 sendIsMemberAccess = oldSendIsMemberAccess; | 754 sendIsMemberAccess = oldSendIsMemberAccess; |
| 897 return new ArgumentsResult( | 755 return new ArgumentsResult( |
| 898 new CallStructure(argumentCount, namedArguments), | 756 new CallStructure(argumentCount, namedArguments), |
| 899 argumentResults, | 757 argumentResults, |
| 900 isValidAsConstant: isValidAsConstant); | 758 isValidAsConstant: isValidAsConstant); |
| 901 } | 759 } |
| 902 | 760 |
| 903 void registerTypeLiteralAccess(Send node, Element target) { | |
| 904 // Set the type of the node to [Type] to mark this send as a | |
| 905 // type literal. | |
| 906 DartType type; | |
| 907 | |
| 908 // TODO(johnniwinther): Remove this hack when we can pass more complex | |
| 909 // information between methods than resolved elements. | |
| 910 if (target == compiler.typeClass && node.receiver == null) { | |
| 911 // Potentially a 'dynamic' type literal. | |
| 912 type = registry.getType(node.selector); | |
| 913 } | |
| 914 if (type == null) { | |
| 915 if (target.isTypedef || target.isClass) { | |
| 916 TypeDeclarationElement typeDeclaration = target; | |
| 917 typeDeclaration.computeType(compiler); | |
| 918 type = typeDeclaration.rawType; | |
| 919 } else { | |
| 920 TypeVariableElement typeVariable = target; | |
| 921 type = typeVariable.type; | |
| 922 } | |
| 923 } | |
| 924 registry.registerTypeLiteral(node, type); | |
| 925 | |
| 926 if (!target.isTypeVariable) { | |
| 927 // Don't try to make constants of calls and assignments to type literals. | |
| 928 if (!node.isCall && node.asSendSet() == null) { | |
| 929 analyzeConstantDeferred(node, enforceConst: false); | |
| 930 } else { | |
| 931 // The node itself is not a constant but we register the selector (the | |
| 932 // identifier that refers to the class/typedef) as a constant. | |
| 933 if (node.receiver != null) { | |
| 934 // This is a hack for the case of prefix.Type, we need to store | |
| 935 // the element on the selector, so [analyzeConstant] can build | |
| 936 // the type literal from the selector. | |
| 937 registry.useElement(node.selector, target); | |
| 938 } | |
| 939 analyzeConstantDeferred(node.selector, enforceConst: false); | |
| 940 } | |
| 941 } | |
| 942 } | |
| 943 | |
| 944 /// Check that access to `super` is currently allowed. Returns an | 761 /// Check that access to `super` is currently allowed. Returns an |
| 945 /// [AccessSemantics] in case of an error, `null` otherwise. | 762 /// [AccessSemantics] in case of an error, `null` otherwise. |
| 946 AccessSemantics checkSuperAccess(Send node) { | 763 AccessSemantics checkSuperAccess(Send node) { |
| 947 if (!inInstanceContext) { | 764 if (!inInstanceContext) { |
| 948 return new StaticAccess.invalid( | 765 return new StaticAccess.invalid( |
| 949 reportAndCreateErroneousElement( | 766 reportAndCreateErroneousElement( |
| 950 node, 'super', | 767 node, 'super', |
| 951 MessageKind.NO_SUPER_IN_STATIC, {}, | 768 MessageKind.NO_SUPER_IN_STATIC, {}, |
| 952 isError: true)); | 769 isError: true)); |
| 953 } | 770 } |
| (...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1940 // setters. | 1757 // setters. |
| 1941 ErroneousElement error = reportAndCreateErroneousElement( | 1758 ErroneousElement error = reportAndCreateErroneousElement( |
| 1942 node, name.text, MessageKind.MEMBER_NOT_FOUND, | 1759 node, name.text, MessageKind.MEMBER_NOT_FOUND, |
| 1943 {'className': receiverClass.name, 'memberName': name.text}); | 1760 {'className': receiverClass.name, 'memberName': name.text}); |
| 1944 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static | 1761 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static |
| 1945 // member access. | 1762 // member access. |
| 1946 return handleErroneousAccess( | 1763 return handleErroneousAccess( |
| 1947 node, name, new StaticAccess.unresolved(error)); | 1764 node, name, new StaticAccess.unresolved(error)); |
| 1948 } | 1765 } |
| 1949 | 1766 |
| 1767 /// Handle qualified update to an unresolved static class member, like | |
| 1768 /// `a.b = c` or `a.b++` where `a` is a class and `b` is unresolved. | |
| 1769 ResolutionResult handleUnresolvedStaticMemberUpdate( | |
| 1770 SendSet node, Name name, ClassElement receiverClass) { | |
| 1771 // TODO(johnniwinther): Share code with [handleStaticInstanceMemberUpdate] | |
| 1772 // and [handlePrivateStaticMemberUpdate]. | |
| 1773 registry.registerThrowNoSuchMethod(); | |
| 1774 // TODO(johnniwinther): Produce a different error if [name] is resolves to | |
| 1775 // a constructor. | |
| 1776 | |
| 1777 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | |
| 1778 // try to resolve injected elements if [currentClass] is in the patch | |
| 1779 // library of [receiverClass]. | |
| 1780 | |
| 1781 // TODO(johnniwinther): Produce a different error for complex update. | |
| 1782 ErroneousElement error = reportAndCreateErroneousElement( | |
| 1783 node, name.text, MessageKind.MEMBER_NOT_FOUND, | |
| 1784 {'className': receiverClass.name, 'memberName': name.text}); | |
| 1785 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static | |
| 1786 // member access. | |
| 1787 return handleUpdate(node, name, new StaticAccess.unresolved(error)); | |
| 1788 } | |
| 1789 | |
| 1950 /// Handle qualified access of an instance member, like `a.b` or `a.b()` where | 1790 /// Handle qualified access of an instance member, like `a.b` or `a.b()` where |
| 1951 /// `a` is a class and `b` is a non-static member. | 1791 /// `a` is a class and `b` is a non-static member. |
| 1952 ResolutionResult handleStaticInstanceMemberAccess( | 1792 ResolutionResult handleStaticInstanceMemberAccess( |
| 1953 Send node, Name name, ClassElement receiverClass, Element member) { | 1793 Send node, Name name, ClassElement receiverClass, Element member) { |
| 1954 | 1794 |
| 1955 registry.registerThrowNoSuchMethod(); | 1795 registry.registerThrowNoSuchMethod(); |
| 1956 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | 1796 // TODO(johnniwinther): With the simplified [TreeElements] invariant, |
| 1957 // try to resolve injected elements if [currentClass] is in the patch | 1797 // try to resolve injected elements if [currentClass] is in the patch |
| 1958 // library of [receiverClass]. | 1798 // library of [receiverClass]. |
| 1959 | 1799 |
| 1960 // TODO(karlklose): this should be reported by the caller of | 1800 // TODO(karlklose): this should be reported by the caller of |
| 1961 // [resolveSend] to select better warning messages for getters and | 1801 // [resolveSend] to select better warning messages for getters and |
| 1962 // setters. | 1802 // setters. |
| 1963 ErroneousElement error = reportAndCreateErroneousElement( | 1803 ErroneousElement error = reportAndCreateErroneousElement( |
| 1964 node, name.text, MessageKind.MEMBER_NOT_STATIC, | 1804 node, name.text, MessageKind.MEMBER_NOT_STATIC, |
| 1965 {'className': receiverClass.name, 'memberName': name}); | 1805 {'className': receiverClass.name, 'memberName': name}); |
| 1966 | 1806 |
| 1967 // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed | 1807 // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed |
| 1968 // instance members. | 1808 // instance members. |
| 1969 return handleErroneousAccess( | 1809 return handleErroneousAccess( |
| 1970 node, name, new StaticAccess.unresolved(error)); | 1810 node, name, new StaticAccess.unresolved(error)); |
| 1971 } | 1811 } |
| 1972 | 1812 |
| 1813 /// Handle qualified update of an instance member, like `a.b = c` or `a.b++` | |
| 1814 /// where `a` is a class and `b` is a non-static member. | |
| 1815 ResolutionResult handleStaticInstanceMemberUpdate( | |
| 1816 SendSet node, Name name, ClassElement receiverClass, Element member) { | |
| 1817 | |
| 1818 registry.registerThrowNoSuchMethod(); | |
| 1819 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | |
| 1820 // try to resolve injected elements if [currentClass] is in the patch | |
| 1821 // library of [receiverClass]. | |
| 1822 | |
| 1823 // TODO(johnniwinther): Produce a different error for complex update. | |
| 1824 ErroneousElement error = reportAndCreateErroneousElement( | |
| 1825 node, name.text, MessageKind.MEMBER_NOT_STATIC, | |
| 1826 {'className': receiverClass.name, 'memberName': name}); | |
| 1827 | |
| 1828 // TODO(johnniwinther): Add an [AccessSemantics] for statically accessed | |
| 1829 // instance members. | |
| 1830 return handleUpdate(node, name, new StaticAccess.unresolved(error)); | |
| 1831 } | |
| 1832 | |
| 1973 /// Handle qualified access of an inaccessible private static class member, | 1833 /// Handle qualified access of an inaccessible private static class member, |
| 1974 /// like `a._b` or `a.b()` where `a` is class, `_b` is static member of `a` | 1834 /// like `a._b` or `a._b()` where `a` is class, `_b` is static member of `a` |
| 1975 /// but `a` is not defined in the current library. | 1835 /// but `a` is not defined in the current library. |
| 1976 ResolutionResult handlePrivateStaticMemberAccess( | 1836 ResolutionResult handlePrivateStaticMemberAccess( |
| 1977 Send node, Name name, ClassElement receiverClass, Element member) { | 1837 Send node, Name name, ClassElement receiverClass, Element member) { |
| 1978 registry.registerThrowNoSuchMethod(); | 1838 registry.registerThrowNoSuchMethod(); |
| 1979 ErroneousElement error = reportAndCreateErroneousElement( | 1839 ErroneousElement error = reportAndCreateErroneousElement( |
| 1980 node, name.text, MessageKind.PRIVATE_ACCESS, | 1840 node, name.text, MessageKind.PRIVATE_ACCESS, |
| 1981 {'libraryName': member.library.getLibraryOrScriptName(), | 1841 {'libraryName': member.library.getLibraryOrScriptName(), |
| 1982 'name': name}); | 1842 'name': name}); |
| 1983 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static | 1843 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static |
| 1984 // member access. | 1844 // member access. |
| 1985 return handleErroneousAccess( | 1845 return handleErroneousAccess( |
| 1986 node, name, new StaticAccess.unresolved(error)); | 1846 node, name, new StaticAccess.unresolved(error)); |
| 1987 } | 1847 } |
| 1988 | 1848 |
| 1849 /// Handle qualified update of an inaccessible private static class member, | |
| 1850 /// like `a._b = c` or `a._b++` where `a` is class, `_b` is static member of | |
| 1851 /// `a` but `a` is not defined in the current library. | |
| 1852 ResolutionResult handlePrivateStaticMemberUpdate( | |
| 1853 SendSet node, Name name, ClassElement receiverClass, Element member) { | |
| 1854 registry.registerThrowNoSuchMethod(); | |
| 1855 ErroneousElement error = reportAndCreateErroneousElement( | |
| 1856 node, name.text, MessageKind.PRIVATE_ACCESS, | |
| 1857 {'libraryName': member.library.getLibraryOrScriptName(), | |
| 1858 'name': name}); | |
| 1859 // TODO(johnniwinther): Add an [AccessSemantics] for unresolved static | |
| 1860 // member access. | |
| 1861 return handleUpdate(node, name, new StaticAccess.unresolved(error)); | |
| 1862 } | |
| 1863 | |
| 1989 /// Handle qualified access to a static member, like `a.b` or `a.b()` where | 1864 /// Handle qualified access to a static member, like `a.b` or `a.b()` where |
| 1990 /// `a` is a class and `b` is a static member of `a`. | 1865 /// `a` is a class and `b` is a static member of `a`. |
| 1991 ResolutionResult handleStaticMemberAccess( | 1866 ResolutionResult handleStaticMemberAccess( |
| 1992 Send node, Name memberName, ClassElement receiverClass) { | 1867 Send node, Name memberName, ClassElement receiverClass) { |
| 1993 String name = memberName.text; | 1868 String name = memberName.text; |
| 1994 receiverClass.ensureResolved(compiler); | 1869 receiverClass.ensureResolved(compiler); |
| 1995 if (node.isOperator) { | 1870 if (node.isOperator) { |
| 1996 // When the resolved receiver is a class, we can have two cases: | 1871 // When the resolved receiver is a class, we can have two cases: |
| 1997 // 1) a static send: C.foo, or | 1872 // 1) a static send: C.foo, or |
| 1998 // 2) an operator send, where the receiver is a class literal: 'C + 1'. | 1873 // 2) an operator send, where the receiver is a class literal: 'C + 1'. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2013 return handleStaticInstanceMemberAccess( | 1888 return handleStaticInstanceMemberAccess( |
| 2014 node, memberName, receiverClass, member); | 1889 node, memberName, receiverClass, member); |
| 2015 } else if (memberName.isPrivate && memberName.library != member.library) { | 1890 } else if (memberName.isPrivate && memberName.library != member.library) { |
| 2016 return handlePrivateStaticMemberAccess( | 1891 return handlePrivateStaticMemberAccess( |
| 2017 node, memberName, receiverClass, member); | 1892 node, memberName, receiverClass, member); |
| 2018 } else { | 1893 } else { |
| 2019 return handleStaticOrTopLevelAccess(node, memberName, member); | 1894 return handleStaticOrTopLevelAccess(node, memberName, member); |
| 2020 } | 1895 } |
| 2021 } | 1896 } |
| 2022 | 1897 |
| 1898 /// Handle qualified update to a static member, like `a.b = c` or `a.b++` | |
| 1899 /// where `a` is a class and `b` is a static member of `a`. | |
| 1900 ResolutionResult handleStaticMemberUpdate( | |
| 1901 Send node, Name memberName, ClassElement receiverClass) { | |
| 1902 String name = memberName.text; | |
| 1903 receiverClass.ensureResolved(compiler); | |
| 1904 MembersCreator.computeClassMembersByName( | |
| 1905 compiler, receiverClass.declaration, name); | |
| 1906 Element member = receiverClass.lookupLocalMember(name); | |
| 1907 if (member == null) { | |
| 1908 return handleUnresolvedStaticMemberUpdate( | |
| 1909 node, memberName, receiverClass); | |
| 1910 } else if (member.isAmbiguous) { | |
| 1911 return handleAmbiguousUpdate(node, memberName, member); | |
| 1912 } else if (member.isInstanceMember) { | |
| 1913 return handleStaticInstanceMemberUpdate( | |
| 1914 node, memberName, receiverClass, member); | |
| 1915 } else if (memberName.isPrivate && memberName.library != member.library) { | |
| 1916 return handlePrivateStaticMemberUpdate( | |
| 1917 node, memberName, receiverClass, member); | |
| 1918 } else { | |
| 1919 return handleStaticOrTopLevelUpdate(node, memberName, member); | |
| 1920 } | |
| 1921 } | |
| 1922 | |
| 2023 /// Handle access to a type literal of type variable [element]. Like `T` or | 1923 /// Handle access to a type literal of type variable [element]. Like `T` or |
| 2024 /// `T()` where 'T' is type variable. | 1924 /// `T()` where 'T' is type variable. |
| 2025 // TODO(johnniwinther): Remove [name] when [Selector] is not required for the | 1925 // TODO(johnniwinther): Remove [name] when [Selector] is not required for the |
| 2026 // the [GetStructure]. | 1926 // the [GetStructure]. |
| 2027 // TODO(johnniwinther): Remove [element] when it is no longer needed for | 1927 // TODO(johnniwinther): Remove [element] when it is no longer needed for |
| 2028 // evaluating constants. | 1928 // evaluating constants. |
| 2029 ResolutionResult handleTypeVariableTypeLiteralAccess( | 1929 ResolutionResult handleTypeVariableTypeLiteralAccess( |
| 2030 Send node, | 1930 Send node, |
| 2031 Name name, | 1931 Name name, |
| 2032 TypeVariableElement element) { | 1932 TypeVariableElement element) { |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2324 // `prefix.Class.foo`. No need to call [handleDeferredAccess]; it will | 2224 // `prefix.Class.foo`. No need to call [handleDeferredAccess]; it will |
| 2325 // called on the parent `prefix.Class.foo` node. | 2225 // called on the parent `prefix.Class.foo` node. |
| 2326 result = new PrefixResult(prefix, result.element); | 2226 result = new PrefixResult(prefix, result.element); |
| 2327 } else if (prefix.isDeferred && | 2227 } else if (prefix.isDeferred && |
| 2328 (member == null || !member.isDeferredLoaderGetter)) { | 2228 (member == null || !member.isDeferredLoaderGetter)) { |
| 2329 result = handleDeferredAccess(node, prefix, result); | 2229 result = handleDeferredAccess(node, prefix, result); |
| 2330 } | 2230 } |
| 2331 return result; | 2231 return result; |
| 2332 } | 2232 } |
| 2333 | 2233 |
| 2234 /// Handle qualified [SendSet] where the receiver resolves to a [prefix], | |
| 2235 /// like `prefix.toplevelField = b` or `prefix.Class.staticField++` where | |
| 2236 /// `prefix` is a library prefix. | |
| 2237 ResolutionResult handleLibraryPrefixSendSet( | |
| 2238 SendSet node, Name name, PrefixElement prefix) { | |
| 2239 ResolutionResult result; | |
| 2240 Element member = prefix.lookupLocalMember(name.text); | |
| 2241 if (member == null) { | |
| 2242 registry.registerThrowNoSuchMethod(); | |
| 2243 Element error = reportAndCreateErroneousElement( | |
| 2244 node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER, | |
| 2245 {'libraryName': prefix.name, 'memberName': name}); | |
| 2246 return handleUpdate(node, name, new StaticAccess.unresolved(error)); | |
| 2247 } else { | |
| 2248 result = handleResolvedSendSet(node, name, member); | |
| 2249 } | |
| 2250 if (result.kind == ResultKind.PREFIX) { | |
| 2251 // [member] is a class prefix of a static access like `prefix.Class` of | |
| 2252 // `prefix.Class.foo`. No need to call [handleDeferredAccess]; it will | |
| 2253 // called on the parent `prefix.Class.foo` node. | |
| 2254 result = new PrefixResult(prefix, result.element); | |
| 2255 } else if (prefix.isDeferred && | |
| 2256 (member == null || !member.isDeferredLoaderGetter)) { | |
| 2257 result = handleDeferredAccess(node, prefix, result); | |
| 2258 } | |
| 2259 return result; | |
| 2260 } | |
| 2261 | |
| 2334 /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in | 2262 /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in |
| 2335 /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time | 2263 /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time |
| 2336 /// error. | 2264 /// error. |
| 2337 ResolutionResult handleLibraryPrefix( | 2265 ResolutionResult handleLibraryPrefix( |
| 2338 Send node, | 2266 Send node, |
| 2339 Name name, | 2267 Name name, |
| 2340 PrefixElement prefix) { | 2268 PrefixElement prefix) { |
| 2341 if ((ElementCategory.PREFIX & allowedCategory) == 0) { | 2269 if ((ElementCategory.PREFIX & allowedCategory) == 0) { |
| 2342 ErroneousElement error = reportAndCreateErroneousElement( | 2270 ErroneousElement error = reportAndCreateErroneousElement( |
| 2343 node, | 2271 node, |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2371 } else { | 2299 } else { |
| 2372 assert(element.isClass); | 2300 assert(element.isClass); |
| 2373 ResolutionResult result = handleStaticMemberAccess(node, name, element); | 2301 ResolutionResult result = handleStaticMemberAccess(node, name, element); |
| 2374 if (prefixResult.isDeferred) { | 2302 if (prefixResult.isDeferred) { |
| 2375 result = handleDeferredAccess(node, prefixResult.prefix, result); | 2303 result = handleDeferredAccess(node, prefixResult.prefix, result); |
| 2376 } | 2304 } |
| 2377 return result; | 2305 return result; |
| 2378 } | 2306 } |
| 2379 } | 2307 } |
| 2380 | 2308 |
| 2309 /// Handle qualified [SendSet] where the receiver resolves to an [Element], | |
| 2310 /// like `a.b = c` where `a` is a prefix or a class. | |
| 2311 ResolutionResult handlePrefixSendSet( | |
| 2312 SendSet node, Name name, PrefixResult prefixResult) { | |
| 2313 Element element = prefixResult.element; | |
| 2314 if (element.isPrefix) { | |
| 2315 if (node.isConditional) { | |
| 2316 return handleLibraryPrefix(node, name, element); | |
| 2317 } else { | |
| 2318 return handleLibraryPrefixSendSet(node, name, element); | |
| 2319 } | |
| 2320 } else { | |
| 2321 assert(element.isClass); | |
| 2322 ResolutionResult result = handleStaticMemberUpdate(node, name, element); | |
| 2323 if (prefixResult.isDeferred) { | |
| 2324 result = handleDeferredAccess(node, prefixResult.prefix, result); | |
| 2325 } | |
| 2326 return result; | |
| 2327 } | |
| 2328 } | |
| 2329 | |
| 2381 /// Handle dynamic access of [semantics]. | 2330 /// Handle dynamic access of [semantics]. |
| 2382 ResolutionResult handleDynamicAccessSemantics( | 2331 ResolutionResult handleDynamicAccessSemantics( |
| 2383 Send node, Name name, AccessSemantics semantics) { | 2332 Send node, Name name, AccessSemantics semantics) { |
| 2384 SendStructure sendStructure; | 2333 SendStructure sendStructure; |
| 2385 Selector selector; | 2334 Selector selector; |
| 2386 if (node.isCall) { | 2335 if (node.isCall) { |
| 2387 CallStructure callStructure = | 2336 CallStructure callStructure = |
| 2388 resolveArguments(node.argumentsNode).callStructure; | 2337 resolveArguments(node.argumentsNode).callStructure; |
| 2389 selector = new Selector(SelectorKind.CALL, name, callStructure); | 2338 selector = new Selector(SelectorKind.CALL, name, callStructure); |
| 2390 registry.registerDynamicInvocation( | 2339 registry.registerDynamicInvocation( |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2475 node, name, const DynamicAccess.ifNotNullProperty()); | 2424 node, name, const DynamicAccess.ifNotNullProperty()); |
| 2476 } else { | 2425 } else { |
| 2477 // Handle dynamic property access, like `a.b` or `a.b()` where `a` is not | 2426 // Handle dynamic property access, like `a.b` or `a.b()` where `a` is not |
| 2478 // a prefix or class. | 2427 // a prefix or class. |
| 2479 // TODO(johnniwinther): Use the `element` of [result]. | 2428 // TODO(johnniwinther): Use the `element` of [result]. |
| 2480 return handleDynamicAccessSemantics( | 2429 return handleDynamicAccessSemantics( |
| 2481 node, name, const DynamicAccess.dynamicProperty()); | 2430 node, name, const DynamicAccess.dynamicProperty()); |
| 2482 } | 2431 } |
| 2483 } | 2432 } |
| 2484 | 2433 |
| 2434 /// Handle a qualified [SendSet], that is where the receiver is non-null, like | |
| 2435 /// `a.b = c`, `a.b++`, and `a.b += c`. | |
| 2436 ResolutionResult handleQualifiedSendSet(SendSet node) { | |
| 2437 Identifier selector = node.selector.asIdentifier(); | |
| 2438 String text = selector.source; | |
| 2439 Name name = new Name(text, enclosingElement.library); | |
| 2440 if (text == 'this') { | |
|
floitsch
2015/08/20 16:28:34
That feels like a weird check.
Is it for captured
Johnni Winther
2015/08/21 07:17:36
This is for cases like 'C.this' for which there is
floitsch
2015/08/21 09:27:50
Ah...
Didn't realize this was the selector and not
| |
| 2441 return handleQualifiedThisAccess(node, name); | |
| 2442 } else if (node.receiver.isThis()) { | |
| 2443 if (checkThisAccess(node)) { | |
| 2444 return handleThisPropertyUpdate(node, name, null); | |
| 2445 } | |
| 2446 // TODO(johnniwinther): Handle invalid this access as an | |
| 2447 // [AccessSemantics]. | |
| 2448 return const NoneResult(); | |
| 2449 } | |
| 2450 ResolutionResult result = visitExpressionPrefix(node.receiver); | |
| 2451 if (result.kind == ResultKind.PREFIX) { | |
| 2452 return handlePrefixSendSet(node, name, result); | |
| 2453 } else if (node.isConditional) { | |
| 2454 return handleDynamicUpdateSemantics( | |
| 2455 node, name, null, const DynamicAccess.ifNotNullProperty()); | |
| 2456 } else { | |
| 2457 // Handle dynamic property access, like `a.b = c`, `a.b++` or `a.b += c` | |
| 2458 // where `a` is not a prefix or class. | |
| 2459 // TODO(johnniwinther): Use the `element` of [result]. | |
| 2460 return handleDynamicUpdateSemantics( | |
| 2461 node, name, null, const DynamicAccess.dynamicProperty()); | |
| 2462 } | |
| 2463 } | |
| 2464 | |
| 2485 /// Handle access unresolved access to [name] in a non-instance context. | 2465 /// Handle access unresolved access to [name] in a non-instance context. |
| 2486 ResolutionResult handleUnresolvedAccess( | 2466 ResolutionResult handleUnresolvedAccess( |
| 2487 Send node, Name name, Element element) { | 2467 Send node, Name name, Element element) { |
| 2488 // TODO(johnniwinther): Support unresolved top level access as an | 2468 // TODO(johnniwinther): Support unresolved top level access as an |
| 2489 // [AccessSemantics]. | 2469 // [AccessSemantics]. |
| 2490 AccessSemantics semantics = new StaticAccess.unresolved(element); | 2470 AccessSemantics semantics = new StaticAccess.unresolved(element); |
| 2491 return handleErroneousAccess(node, name, semantics); | 2471 return handleErroneousAccess(node, name, semantics); |
| 2492 } | 2472 } |
| 2493 | 2473 |
| 2494 /// Handle erroneous access of [element] of the given [semantics]. | 2474 /// Handle erroneous access of [element] of the given [semantics]. |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3023 // `C = b`, `C++`, or 'C += b` where 'F' is a typedef. | 3003 // `C = b`, `C++`, or 'C += b` where 'F' is a typedef. |
| 3024 return handleTypedefTypeLiteralUpdate(node, name, element); | 3004 return handleTypedefTypeLiteralUpdate(node, name, element); |
| 3025 } else if (element.isTypeVariable) { | 3005 } else if (element.isTypeVariable) { |
| 3026 // `T = b`, `T++`, or 'T += b` where 'T' is a type variable. | 3006 // `T = b`, `T++`, or 'T += b` where 'T' is a type variable. |
| 3027 return handleTypeVariableTypeLiteralUpdate(node, name, element); | 3007 return handleTypeVariableTypeLiteralUpdate(node, name, element); |
| 3028 } else if (element.isLocal) { | 3008 } else if (element.isLocal) { |
| 3029 return handleLocalUpdate(node, name, element); | 3009 return handleLocalUpdate(node, name, element); |
| 3030 } else if (element.isStatic || element.isTopLevel) { | 3010 } else if (element.isStatic || element.isTopLevel) { |
| 3031 return handleStaticOrTopLevelUpdate(node, name, element); | 3011 return handleStaticOrTopLevelUpdate(node, name, element); |
| 3032 } | 3012 } |
| 3033 return oldVisitSendSet(node); | 3013 return internalError(node, "Unexpected resolved send: $element"); |
| 3034 } | 3014 } |
| 3035 | 3015 |
| 3036 /// Handle an unqualified [Send], that is where the `node.receiver` is null, | 3016 /// Handle an unqualified [Send], that is where the `node.receiver` is null, |
| 3037 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. | 3017 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. |
| 3038 ResolutionResult handleUnqualifiedSend(Send node) { | 3018 ResolutionResult handleUnqualifiedSend(Send node) { |
| 3039 Identifier selector = node.selector.asIdentifier(); | 3019 Identifier selector = node.selector.asIdentifier(); |
| 3040 if (selector == null) { | 3020 if (selector == null) { |
| 3041 // `(){}()` and `(foo)()`. | 3021 // `(){}()` and `(foo)()`. |
| 3042 return handleExpressionInvoke(node); | 3022 return handleExpressionInvoke(node); |
| 3043 } | 3023 } |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3492 SendStructure sendStructure = new CompoundStructure( | 3472 SendStructure sendStructure = new CompoundStructure( |
| 3493 semantics, operator, getterSelector, setterSelector); | 3473 semantics, operator, getterSelector, setterSelector); |
| 3494 registry.registerSendStructure(node, sendStructure); | 3474 registry.registerSendStructure(node, sendStructure); |
| 3495 } | 3475 } |
| 3496 } | 3476 } |
| 3497 return new ResolutionResult.forElement(semantics.setter); | 3477 return new ResolutionResult.forElement(semantics.setter); |
| 3498 } | 3478 } |
| 3499 | 3479 |
| 3500 ResolutionResult visitSendSet(SendSet node) { | 3480 ResolutionResult visitSendSet(SendSet node) { |
| 3501 if (node.isIndex) { | 3481 if (node.isIndex) { |
| 3482 // `a[b] = c` | |
| 3502 if (node.isSuperCall) { | 3483 if (node.isSuperCall) { |
| 3484 // `super[b] = c` | |
| 3503 return handleSuperIndexSendSet(node); | 3485 return handleSuperIndexSendSet(node); |
| 3504 } else { | 3486 } else { |
| 3505 return handleIndexSendSet(node); | 3487 return handleIndexSendSet(node); |
| 3506 } | 3488 } |
| 3507 } else if (node.isSuperCall) { | 3489 } else if (node.isSuperCall) { |
| 3490 // `super.a = c` | |
| 3508 return handleSuperSendSet(node); | 3491 return handleSuperSendSet(node); |
| 3509 } else if (node.receiver == null) { | 3492 } else if (node.receiver == null) { |
| 3493 // `a = c` | |
| 3510 return handleUnqualifiedSendSet(node); | 3494 return handleUnqualifiedSendSet(node); |
| 3495 } else { | |
| 3496 // `a.b = c` | |
| 3497 return handleQualifiedSendSet(node); | |
| 3511 } | 3498 } |
| 3512 return oldVisitSendSet(node); | |
| 3513 } | |
| 3514 | |
| 3515 ResolutionResult oldVisitSendSet(SendSet node) { | |
| 3516 bool oldSendIsMemberAccess = sendIsMemberAccess; | |
| 3517 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | |
| 3518 ResolutionResult result = resolveSend(node); | |
| 3519 sendIsMemberAccess = oldSendIsMemberAccess; | |
| 3520 Element target = result.element; | |
| 3521 Element setter = target; | |
| 3522 Element getter = target; | |
| 3523 String operatorName = node.assignmentOperator.source; | |
| 3524 String source = operatorName; | |
| 3525 bool isComplex = !identical(source, '='); | |
| 3526 if (!(result is AssertResult || Elements.isUnresolved(target))) { | |
| 3527 if (target.isAbstractField) { | |
| 3528 AbstractFieldElement field = target; | |
| 3529 setter = field.setter; | |
| 3530 getter = field.getter; | |
| 3531 if (setter == null) { | |
| 3532 if (!inInstanceContext || getter.isTopLevel || getter.isStatic) { | |
| 3533 setter = reportAndCreateErroneousElement(node.selector, field.name, | |
| 3534 MessageKind.CANNOT_RESOLVE_SETTER, const {}); | |
| 3535 registry.registerThrowNoSuchMethod(); | |
| 3536 } | |
| 3537 } | |
| 3538 if (isComplex && getter == null && !inInstanceContext) { | |
| 3539 getter = reportAndCreateErroneousElement(node.selector, field.name, | |
| 3540 MessageKind.CANNOT_RESOLVE_GETTER, const {}); | |
| 3541 registry.registerThrowNoSuchMethod(); | |
| 3542 } | |
| 3543 } else if (target.impliesType) { | |
| 3544 if (node.isIfNullAssignment) { | |
| 3545 setter = reportAndCreateErroneousElement(node.selector, target.name, | |
| 3546 MessageKind.IF_NULL_ASSIGNING_TYPE, const {}); | |
| 3547 // In this case, no assignment happens, the rest of the compiler can | |
| 3548 // treat the expression `C ??= e` as if it's just reading `C`. | |
| 3549 } else { | |
| 3550 setter = reportAndCreateErroneousElement(node.selector, target.name, | |
| 3551 MessageKind.ASSIGNING_TYPE, const {}); | |
| 3552 registry.registerThrowNoSuchMethod(); | |
| 3553 } | |
| 3554 registerTypeLiteralAccess(node, target); | |
| 3555 } else if (target.isFinal || target.isConst) { | |
| 3556 if (Elements.isStaticOrTopLevelField(target) || target.isLocal) { | |
| 3557 setter = reportAndCreateErroneousElement( | |
| 3558 node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER, | |
| 3559 const {}); | |
| 3560 } else if (node.isSuperCall) { | |
| 3561 setter = reportAndCreateErroneousElement( | |
| 3562 node.selector, target.name, MessageKind.SETTER_NOT_FOUND_IN_SUPER, | |
| 3563 {'name': target.name, 'className': currentClass.name}); | |
| 3564 registry.registerSuperNoSuchMethod(); | |
| 3565 } else { | |
| 3566 // For instance fields we don't report a warning here because the type | |
| 3567 // checker will detect this as well and report a better error message | |
| 3568 // with the context of the containing class. | |
| 3569 } | |
| 3570 registry.registerThrowNoSuchMethod(); | |
| 3571 } else if (target.isFunction && target.name != '[]=') { | |
| 3572 assert(!target.isSetter); | |
| 3573 if (Elements.isStaticOrTopLevelFunction(target) || target.isLocal) { | |
| 3574 setter = reportAndCreateErroneousElement( | |
| 3575 node.selector, target.name, MessageKind.ASSIGNING_METHOD, | |
| 3576 const {}); | |
| 3577 } else if (node.isSuperCall) { | |
| 3578 setter = reportAndCreateErroneousElement( | |
| 3579 node.selector, target.name, MessageKind.ASSIGNING_METHOD_IN_SUPER, | |
| 3580 {'name': target.name, | |
| 3581 'superclassName': target.enclosingClass.name}); | |
| 3582 registry.registerSuperNoSuchMethod(); | |
| 3583 } else { | |
| 3584 // For instance methods we don't report a warning here because the | |
| 3585 // type checker will detect this as well and report a better error | |
| 3586 // message with the context of the containing class. | |
| 3587 } | |
| 3588 registry.registerThrowNoSuchMethod(); | |
| 3589 } | |
| 3590 if (isPotentiallyMutableTarget(target)) { | |
| 3591 registry.registerPotentialMutation(target, node); | |
| 3592 if (enclosingElement != target.enclosingElement) { | |
| 3593 registry.registerPotentialMutationInClosure(target, node); | |
| 3594 } | |
| 3595 for (Node scope in promotionScope) { | |
| 3596 registry.registerPotentialMutationIn(scope, target, node); | |
| 3597 } | |
| 3598 } | |
| 3599 } | |
| 3600 | |
| 3601 resolveArguments(node.argumentsNode); | |
| 3602 | |
| 3603 Selector selector = registry.getSelector(node); | |
| 3604 if (isComplex) { | |
| 3605 Selector getterSelector; | |
| 3606 if (selector.isSetter) { | |
| 3607 getterSelector = new Selector.getterFrom(selector); | |
| 3608 } else { | |
| 3609 assert(selector.isIndexSet); | |
| 3610 getterSelector = new Selector.index(); | |
| 3611 } | |
| 3612 registerSend(getterSelector, getter); | |
| 3613 registry.setGetterSelectorInComplexSendSet(node, getterSelector); | |
| 3614 if (node.isSuperCall) { | |
| 3615 getter = currentClass.lookupSuperByName(getterSelector.memberName); | |
| 3616 if (getter == null) { | |
| 3617 target = reportAndCreateErroneousElement( | |
| 3618 node, selector.name, MessageKind.NO_SUCH_SUPER_MEMBER, | |
| 3619 {'className': currentClass.name, 'memberName': selector.name}); | |
| 3620 registry.registerSuperNoSuchMethod(); | |
| 3621 } | |
| 3622 } | |
| 3623 registry.useElement(node.selector, getter); | |
| 3624 | |
| 3625 // Make sure we include the + and - operators if we are using | |
| 3626 // the ++ and -- ones. Also, if op= form is used, include op itself. | |
| 3627 void registerBinaryOperator(String name) { | |
| 3628 Selector binop = new Selector.binaryOperator(name); | |
| 3629 registry.registerDynamicInvocation( | |
| 3630 new UniverseSelector(binop, null)); | |
| 3631 registry.setOperatorSelectorInComplexSendSet(node, binop); | |
| 3632 } | |
| 3633 if (identical(source, '++')) { | |
| 3634 registerBinaryOperator('+'); | |
| 3635 registry.registerInstantiatedClass(compiler.intClass); | |
| 3636 } else if (identical(source, '--')) { | |
| 3637 registerBinaryOperator('-'); | |
| 3638 registry.registerInstantiatedClass(compiler.intClass); | |
| 3639 } else if (source.endsWith('=')) { | |
| 3640 registerBinaryOperator(Elements.mapToUserOperator(operatorName)); | |
| 3641 } | |
| 3642 } | |
| 3643 | |
| 3644 registerSend(selector, setter); | |
| 3645 return new ResolutionResult.forElement(registry.useElement(node, setter)); | |
| 3646 } | 3499 } |
| 3647 | 3500 |
| 3648 void registerSend(Selector selector, Element target) { | 3501 void registerSend(Selector selector, Element target) { |
| 3649 if (target == null || target.isInstanceMember) { | 3502 if (target == null || target.isInstanceMember) { |
| 3650 if (selector.isGetter) { | 3503 if (selector.isGetter) { |
| 3651 registry.registerDynamicGetter( | 3504 registry.registerDynamicGetter( |
| 3652 new UniverseSelector(selector, null)); | 3505 new UniverseSelector(selector, null)); |
| 3653 } else if (selector.isSetter) { | 3506 } else if (selector.isSetter) { |
| 3654 registry.registerDynamicSetter( | 3507 registry.registerDynamicSetter( |
| 3655 new UniverseSelector(selector, null)); | 3508 new UniverseSelector(selector, null)); |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4798 } | 4651 } |
| 4799 return const NoneResult(); | 4652 return const NoneResult(); |
| 4800 } | 4653 } |
| 4801 } | 4654 } |
| 4802 | 4655 |
| 4803 /// Looks up [name] in [scope] and unwraps the result. | 4656 /// Looks up [name] in [scope] and unwraps the result. |
| 4804 Element lookupInScope(Compiler compiler, Node node, | 4657 Element lookupInScope(Compiler compiler, Node node, |
| 4805 Scope scope, String name) { | 4658 Scope scope, String name) { |
| 4806 return Elements.unwrap(scope.lookup(name), compiler, node); | 4659 return Elements.unwrap(scope.lookup(name), compiler, node); |
| 4807 } | 4660 } |
| OLD | NEW |