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

Side by Side Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1293953006: Refactor qualified send sets. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698