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

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

Issue 1157333003: Compute more SendStructures on ResolverVisitor. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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 part of resolution; 5 part of resolution;
6 6
7 /** 7 /**
8 * Core implementation of resolution. 8 * Core implementation of resolution.
9 * 9 *
10 * Do not subclass or instantiate this class outside this library 10 * Do not subclass or instantiate this class outside this library
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 compiler.reportError(node, kind, arguments); 180 compiler.reportError(node, kind, arguments);
181 } else { 181 } else {
182 compiler.reportWarning(node, kind, arguments); 182 compiler.reportWarning(node, kind, arguments);
183 } 183 }
184 // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass 184 // TODO(ahe): Use [allowedCategory] to synthesize a more precise subclass
185 // of [ErroneousElementX]. For example, [ErroneousFieldElementX], 185 // of [ErroneousElementX]. For example, [ErroneousFieldElementX],
186 // [ErroneousConstructorElementX], etc. 186 // [ErroneousConstructorElementX], etc.
187 return new ErroneousElementX(kind, arguments, name, enclosingElement); 187 return new ErroneousElementX(kind, arguments, name, enclosingElement);
188 } 188 }
189 189
190 /// Report a warning or error on an unresolved access in non-instance context.
191 ///
192 /// The [ErroneousElement] corresponding to the message is returned.
193 ErroneousElement reportCannotResolve(Node node, String name) {
194 assert(invariant(node, !inInstanceContext,
195 message: "ResolverVisitor.reportCannotResolve must not be called in "
196 "instance context."));
197
198 // We report an error within initializers because `this` is implicitly
199 // accessed when unqualified identifiers are not resolved. For
200 // details, see section 16.14.3 of the spec (2nd edition):
201 // An unqualified invocation `i` of the form `id(a1, ...)`
202 // ...
203 // If `i` does not occur inside a top level or static function, `i`
204 // is equivalent to `this.id(a1 , ...)`.
205 bool inInitializer =
206 enclosingElement.isGenerativeConstructor ||
207 (enclosingElement.isInstanceMember && enclosingElement.isField);
208 MessageKind kind;
209 Map arguments = {'name': name};
210 if (inInitializer) {
211 kind = MessageKind.CANNOT_RESOLVE_IN_INITIALIZER;
212 } else if (name == 'await') {
213 var functionName = enclosingElement.name;
214 if (functionName == '') {
215 kind = MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE;
216 } else {
217 kind = MessageKind.CANNOT_RESOLVE_AWAIT;
218 arguments['functionName'] = functionName;
219 }
220 } else {
221 kind = MessageKind.CANNOT_RESOLVE;
222 }
223 registry.registerThrowNoSuchMethod();
224 return reportAndCreateErroneousElement(
225 node, name, kind, arguments, isError: inInitializer);
226 }
227
190 ResolutionResult visitIdentifier(Identifier node) { 228 ResolutionResult visitIdentifier(Identifier node) {
191 if (node.isThis()) { 229 if (node.isThis()) {
192 if (!inInstanceContext) { 230 if (!inInstanceContext) {
193 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node}); 231 error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
194 } 232 }
195 return null; 233 return null;
196 } else if (node.isSuper()) { 234 } else if (node.isSuper()) {
197 if (!inInstanceContext) { 235 if (!inInstanceContext) {
198 error(node, MessageKind.NO_SUPER_IN_STATIC); 236 error(node, MessageKind.NO_SUPER_IN_STATIC);
199 } 237 }
200 if ((ElementCategory.SUPER & allowedCategory) == 0) { 238 if ((ElementCategory.SUPER & allowedCategory) == 0) {
201 error(node, MessageKind.INVALID_USE_OF_SUPER); 239 error(node, MessageKind.INVALID_USE_OF_SUPER);
202 } 240 }
203 return null; 241 return null;
204 } else { 242 } else {
205 String name = node.source; 243 String name = node.source;
206 Element element = lookupInScope(compiler, node, scope, name); 244 Element element = lookupInScope(compiler, node, scope, name);
207 if (Elements.isUnresolved(element) && name == 'dynamic') { 245 if (Elements.isUnresolved(element) && name == 'dynamic') {
208 // TODO(johnniwinther): Remove this hack when we can return more complex 246 // TODO(johnniwinther): Remove this hack when we can return more complex
209 // objects than [Element] from this method. 247 // objects than [Element] from this method.
210 element = compiler.typeClass; 248 element = compiler.typeClass;
211 // Set the type to be `dynamic` to mark that this is a type literal. 249 // Set the type to be `dynamic` to mark that this is a type literal.
212 registry.setType(node, const DynamicType()); 250 registry.setType(node, const DynamicType());
213 } 251 }
214 element = reportLookupErrorIfAny(element, node, node.source); 252 element = reportLookupErrorIfAny(element, node, name);
215 if (element == null) { 253 if (element == null) {
216 if (!inInstanceContext) { 254 if (!inInstanceContext) {
217 // We report an error within initializers because `this` is implicitly 255 element = reportCannotResolve(node, name);
218 // accessed when unqualified identifiers are not resolved. For
219 // details, see section 16.14.3 of the spec (2nd edition):
220 // An unqualified invocation `i` of the form `id(a1, ...)`
221 // ...
222 // If `i` does not occur inside a top level or static function, `i`
223 // is equivalent to `this.id(a1 , ...)`.
224 bool inInitializer = enclosingElement.isGenerativeConstructor ||
225 (enclosingElement.isInstanceMember && enclosingElement.isField);
226 MessageKind kind;
227 Map arguments = {'name': name};
228 if (inInitializer) {
229 kind = MessageKind.CANNOT_RESOLVE_IN_INITIALIZER;
230 } else if (name == 'await') {
231 var functionName = enclosingElement.name;
232 if (functionName == '') {
233 kind = MessageKind.CANNOT_RESOLVE_AWAIT_IN_CLOSURE;
234 } else {
235 kind = MessageKind.CANNOT_RESOLVE_AWAIT;
236 arguments['functionName'] = functionName;
237 }
238 } else {
239 kind = MessageKind.CANNOT_RESOLVE;
240 }
241 element = reportAndCreateErroneousElement(node, name, kind,
242 arguments, isError: inInitializer);
243 registry.registerThrowNoSuchMethod();
244 } 256 }
245 } else if (element.isErroneous) { 257 } else if (element.isErroneous) {
246 // Use the erroneous element. 258 // Use the erroneous element.
247 } else { 259 } else {
248 if ((element.kind.category & allowedCategory) == 0) { 260 if ((element.kind.category & allowedCategory) == 0) {
249 element = reportAndCreateErroneousElement( 261 element = reportAndCreateErroneousElement(
250 node, name, MessageKind.GENERIC, 262 node, name, MessageKind.GENERIC,
251 // TODO(ahe): Improve error message. Need UX input. 263 // TODO(ahe): Improve error message. Need UX input.
252 {'text': "is not an expression $element"}); 264 {'text': "is not an expression $element"});
253 } 265 }
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 } 490 }
479 491
480 ResolutionResult resolveSend(Send node) { 492 ResolutionResult resolveSend(Send node) {
481 Selector selector = resolveSelector(node, null); 493 Selector selector = resolveSelector(node, null);
482 if (node.isSuperCall) registry.registerSuperUse(node); 494 if (node.isSuperCall) registry.registerSuperUse(node);
483 495
484 if (node.receiver == null) { 496 if (node.receiver == null) {
485 // If this send is of the form "assert(expr);", then 497 // If this send is of the form "assert(expr);", then
486 // this is an assertion. 498 // this is an assertion.
487 if (selector.isAssert) { 499 if (selector.isAssert) {
488 SendStructure sendStructure = const AssertStructure(); 500 internalError(node, "Unexpected assert: $node");
489 if (selector.argumentCount != 1) {
490 error(node.selector,
491 MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT,
492 {'argumentCount': selector.argumentCount});
493 sendStructure = const InvalidAssertStructure();
494 } else if (selector.namedArgumentCount != 0) {
495 error(node.selector,
496 MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS,
497 {'argumentCount': selector.namedArgumentCount});
498 sendStructure = const InvalidAssertStructure();
499 }
500 registry.registerAssert(node);
501 registry.registerSendStructure(node, sendStructure);
502 return const AssertResult();
503 } 501 }
504 502
505 return node.selector.accept(this); 503 return node.selector.accept(this);
506 } 504 }
507 505
508 var oldCategory = allowedCategory; 506 var oldCategory = allowedCategory;
509 allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER; 507 allowedCategory |= ElementCategory.PREFIX | ElementCategory.SUPER;
510 508
511 bool oldSendIsMemberAccess = sendIsMemberAccess; 509 bool oldSendIsMemberAccess = sendIsMemberAccess;
512 int oldAllowedCategory = allowedCategory; 510 int oldAllowedCategory = allowedCategory;
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 : new Selector.call(identifier.source, library, arity, named); 700 : new Selector.call(identifier.source, library, arity, named);
703 } 701 }
704 702
705 Selector resolveSelector(Send node, Element element) { 703 Selector resolveSelector(Send node, Element element) {
706 LibraryElement library = enclosingElement.library; 704 LibraryElement library = enclosingElement.library;
707 Selector selector = computeSendSelector(node, library, element); 705 Selector selector = computeSendSelector(node, library, element);
708 if (selector != null) registry.setSelector(node, selector); 706 if (selector != null) registry.setSelector(node, selector);
709 return selector; 707 return selector;
710 } 708 }
711 709
712 void resolveArguments(NodeList list) { 710 CallStructure resolveArguments(NodeList list) {
713 if (list == null) return; 711 if (list == null) return null;
714 bool oldSendIsMemberAccess = sendIsMemberAccess; 712 bool oldSendIsMemberAccess = sendIsMemberAccess;
715 sendIsMemberAccess = false; 713 sendIsMemberAccess = false;
716 Map<String, Node> seenNamedArguments = new Map<String, Node>(); 714 Map<String, Node> seenNamedArguments = new Map<String, Node>();
715 int argumentCount = 0;
716 List<String> namedArguments = <String>[];
717 for (Link<Node> link = list.nodes; !link.isEmpty; link = link.tail) { 717 for (Link<Node> link = list.nodes; !link.isEmpty; link = link.tail) {
718 Expression argument = link.head; 718 Expression argument = link.head;
719 visit(argument); 719 visit(argument);
720 NamedArgument namedArgument = argument.asNamedArgument(); 720 NamedArgument namedArgument = argument.asNamedArgument();
721 if (namedArgument != null) { 721 if (namedArgument != null) {
722 String source = namedArgument.name.source; 722 String source = namedArgument.name.source;
723 namedArguments.add(source);
723 if (seenNamedArguments.containsKey(source)) { 724 if (seenNamedArguments.containsKey(source)) {
724 reportDuplicateDefinition( 725 reportDuplicateDefinition(
725 source, 726 source,
726 argument, 727 argument,
727 seenNamedArguments[source]); 728 seenNamedArguments[source]);
728 } else { 729 } else {
729 seenNamedArguments[source] = namedArgument; 730 seenNamedArguments[source] = namedArgument;
730 } 731 }
731 } else if (!seenNamedArguments.isEmpty) { 732 } else if (!seenNamedArguments.isEmpty) {
732 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); 733 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED);
733 } 734 }
735 argumentCount++;
734 } 736 }
735 sendIsMemberAccess = oldSendIsMemberAccess; 737 sendIsMemberAccess = oldSendIsMemberAccess;
738 return new CallStructure(argumentCount, namedArguments);
736 } 739 }
737 740
738 void registerTypeLiteralAccess(Send node, Element target) { 741 void registerTypeLiteralAccess(Send node, Element target) {
739 // Set the type of the node to [Type] to mark this send as a 742 // Set the type of the node to [Type] to mark this send as a
740 // type literal. 743 // type literal.
741 DartType type; 744 DartType type;
742 745
743 // TODO(johnniwinther): Remove this hack when we can pass more complex 746 // TODO(johnniwinther): Remove this hack when we can pass more complex
744 // information between methods than resolved elements. 747 // information between methods than resolved elements.
745 if (target == compiler.typeClass && node.receiver == null) { 748 if (target == compiler.typeClass && node.receiver == null) {
(...skipping 17 matching lines...) Expand all
763 // the element on the selector, so [analyzeConstant] can build 766 // the element on the selector, so [analyzeConstant] can build
764 // the type literal from the selector. 767 // the type literal from the selector.
765 registry.useElement(node.selector, target); 768 registry.useElement(node.selector, target);
766 } 769 }
767 analyzeConstantDeferred(node.selector, enforceConst: false); 770 analyzeConstantDeferred(node.selector, enforceConst: false);
768 } 771 }
769 } 772 }
770 } 773 }
771 774
772 /// Check that access to `super` is currently allowed. 775 /// Check that access to `super` is currently allowed.
773 bool checkSuperAccess(Node node) { 776 bool checkSuperAccess(Send node) {
774 if (!inInstanceContext) { 777 if (!inInstanceContext) {
775 compiler.reportError(node, MessageKind.NO_SUPER_AVAILABLE); 778 compiler.reportError(node, MessageKind.NO_SUPER_IN_STATIC);
779 return false;
780 }
781 if (node.isConditional) {
782 // `super?.foo` is not allowed.
783 compiler.reportError(node, MessageKind.INVALID_USE_OF_SUPER);
776 return false; 784 return false;
777 } 785 }
778 if (currentClass.supertype == null) { 786 if (currentClass.supertype == null) {
779 // This is just to guard against internal errors, so no need 787 // This is just to guard against internal errors, so no need
780 // for a real error message. 788 // for a real error message.
781 compiler.reportError(node, MessageKind.GENERIC, 789 compiler.reportError(node, MessageKind.GENERIC,
782 {'text': "Object has no superclass"}); 790 {'text': "Object has no superclass"});
783 return false; 791 return false;
784 } 792 }
785 registry.registerSuperUse(node); 793 registry.registerSuperUse(node);
786 return true; 794 return true;
787 } 795 }
788 796
797 /// Check that access to `this` is currently allowed.
798 bool checkThisAccess(Send node) {
799 if (!inInstanceContext) {
800 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE);
801 return false;
802 }
803 if (node.isConditional) {
804 // `this?.foo` is not allowed.
805 compiler.reportError(node, MessageKind.INVALID_USE_OF_THIS);
806 return false;
807 }
808 return true;
809 }
810
789 /// Compute the [AccessSemantics] corresponding to a super access of [target]. 811 /// Compute the [AccessSemantics] corresponding to a super access of [target].
790 AccessSemantics computeSuperAccess(Spannable node, Element target) { 812 AccessSemantics computeSuperAccess(Spannable node, Element target) {
791 if (target.isErroneous) { 813 if (target.isErroneous) {
792 return new StaticAccess.unresolvedSuper(target); 814 return new StaticAccess.unresolvedSuper(target);
793 } else if (target.isGetter) { 815 } else if (target.isGetter) {
794 return new StaticAccess.superGetter(target); 816 return new StaticAccess.superGetter(target);
795 } else if (target.isSetter) { 817 } else if (target.isSetter) {
796 return new StaticAccess.superSetter(target); 818 return new StaticAccess.superSetter(target);
797 } else if (target.isField) { 819 } else if (target.isField) {
798 return new StaticAccess.superField(target); 820 return new StaticAccess.superField(target);
799 } else { 821 } else {
800 assert(invariant(node, target.isFunction, 822 assert(invariant(node, target.isFunction,
801 message: "Unexpected super target '$target'.")); 823 message: "Unexpected super target '$target'."));
802 return new StaticAccess.superMethod(target); 824 return new StaticAccess.superMethod(target);
803 } 825 }
804 } 826 }
805 827
828 /// Compute the [AccessSemantics] for accessing the name of [selector] on the
829 /// super class.
830 ///
831 /// If no matching super member is found and error is reported and
832 /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName]
833 /// is provided, the [AccessSemantics] corresponding to the alternate name is
834 /// returned. For instance, the access of a super setter for an unresolved
835 /// getter:
836 ///
837 /// class Super {
838 /// set name(_) {}
839 /// }
840 /// class Sub extends Super {
841 /// foo => super.name; // Access to the setter.
842 /// }
843 ///
806 AccessSemantics computeSuperSemantics(Spannable node, 844 AccessSemantics computeSuperSemantics(Spannable node,
807 Selector selector, 845 Selector selector,
808 {Name alternateName}) { 846 {Name alternateName}) {
809 Name name = selector.memberName; 847 Name name = selector.memberName;
810 // TODO(johnniwinther): Ensure correct behavior if currentClass is a 848 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
811 // patch. 849 // patch.
812 Element target = currentClass.lookupSuperByName(name); 850 Element target = currentClass.lookupSuperByName(name);
813 // [target] may be null which means invoking noSuchMethod on super. 851 // [target] may be null which means invoking noSuchMethod on super.
814 if (target == null) { 852 if (target == null) {
815 Element error = reportAndCreateErroneousElement( 853 Element error = reportAndCreateErroneousElement(
816 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER, 854 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER,
817 {'className': currentClass.name, 'memberName': name}); 855 {'className': currentClass.name, 'memberName': name});
818 if (alternateName != null) { 856 if (alternateName != null) {
819 target = currentClass.lookupSuperByName(alternateName); 857 target = currentClass.lookupSuperByName(alternateName);
820 } 858 }
821 if (target == null) { 859 if (target == null) {
822 // If a setter wasn't resolved, use the [ErroneousElement]. 860 // If a setter wasn't resolved, use the [ErroneousElement].
823 target = error; 861 target = error;
824 } 862 }
825 // We still need to register the invocation, because we might 863 // We still need to register the invocation, because we might
826 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. 864 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn].
827 registry.registerDynamicInvocation(selector); 865 registry.registerDynamicInvocation(selector);
828 registry.registerSuperNoSuchMethod(); 866 registry.registerSuperNoSuchMethod();
829 } 867 }
830 return computeSuperAccess(node, target); 868 return computeSuperAccess(node, target);
831 } 869 }
832 870
871 /// Resolve [node] as subexpression that is _not_ the prefix of a member
872 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`.
833 ResolutionResult visitExpression(Node node) { 873 ResolutionResult visitExpression(Node node) {
834 bool oldSendIsMemberAccess = sendIsMemberAccess; 874 bool oldSendIsMemberAccess = sendIsMemberAccess;
835 sendIsMemberAccess = false; 875 sendIsMemberAccess = false;
836 ResolutionResult result = visit(node); 876 ResolutionResult result = visit(node);
837 sendIsMemberAccess = oldSendIsMemberAccess; 877 sendIsMemberAccess = oldSendIsMemberAccess;
838 return result; 878 return result;
839 } 879 }
840 880
881 /// Handle a type test expression, like `a is T` and `a is! T`.
841 ResolutionResult handleIs(Send node) { 882 ResolutionResult handleIs(Send node) {
842 Node expression = node.receiver; 883 Node expression = node.receiver;
843 visitExpression(expression); 884 visitExpression(expression);
844 885
845 // TODO(johnniwinther): Use seen type tests to avoid registration of 886 // TODO(johnniwinther): Use seen type tests to avoid registration of
846 // mutation/access to unpromoted variables. 887 // mutation/access to unpromoted variables.
847 888
848 Send notTypeNode = node.arguments.head.asSend(); 889 Send notTypeNode = node.arguments.head.asSend();
849 DartType type; 890 DartType type;
850 SendStructure sendStructure; 891 SendStructure sendStructure;
851 if (notTypeNode != null) { 892 if (notTypeNode != null) {
852 // `e is! T`. 893 // `e is! T`.
853 Node typeNode = notTypeNode.receiver; 894 Node typeNode = notTypeNode.receiver;
854 type = resolveTypeAnnotation(typeNode); 895 type = resolveTypeAnnotation(typeNode);
855 sendStructure = new IsNotStructure(type); 896 sendStructure = new IsNotStructure(type);
856 } else { 897 } else {
857 // `e is T`. 898 // `e is T`.
858 Node typeNode = node.arguments.head; 899 Node typeNode = node.arguments.head;
859 type = resolveTypeAnnotation(typeNode); 900 type = resolveTypeAnnotation(typeNode);
860 sendStructure = new IsStructure(type); 901 sendStructure = new IsStructure(type);
861 } 902 }
862 registry.registerIsCheck(type); 903 registry.registerIsCheck(type);
863 registry.registerSendStructure(node, sendStructure); 904 registry.registerSendStructure(node, sendStructure);
864 return null; 905 return null;
865 } 906 }
866 907
908 /// Handle a type cast expression, like `a as T`.
867 ResolutionResult handleAs(Send node) { 909 ResolutionResult handleAs(Send node) {
868 Node expression = node.receiver; 910 Node expression = node.receiver;
869 visitExpression(expression); 911 visitExpression(expression);
870 912
871 Node typeNode = node.arguments.head; 913 Node typeNode = node.arguments.head;
872 DartType type = resolveTypeAnnotation(typeNode); 914 DartType type = resolveTypeAnnotation(typeNode);
873 registry.registerAsCheck(type); 915 registry.registerAsCheck(type);
874 registry.registerSendStructure(node, new AsStructure(type)); 916 registry.registerSendStructure(node, new AsStructure(type));
875 return null; 917 return null;
876 } 918 }
877 919
920 /// Handle the unary expression of an unresolved unary operator [text], like
921 /// the no longer supported `+a`.
878 ResolutionResult handleUnresolvedUnary(Send node, String text) { 922 ResolutionResult handleUnresolvedUnary(Send node, String text) {
879 Node expression = node.receiver; 923 Node expression = node.receiver;
880 if (node.isSuperCall) { 924 if (node.isSuperCall) {
881 checkSuperAccess(node); 925 checkSuperAccess(node);
882 } else { 926 } else {
883 visitExpression(expression); 927 visitExpression(expression);
884 } 928 }
885 929
886 registry.registerSendStructure(node, const InvalidUnaryStructure()); 930 registry.registerSendStructure(node, const InvalidUnaryStructure());
887 return null; 931 return null;
888 } 932 }
889 933
934 /// Handle the unary expression of a user definable unary [operator], like
935 /// `-a`, and `-super`.
890 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) { 936 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
891 Node expression = node.receiver; 937 Node expression = node.receiver;
892 Selector selector = operator.selector; 938 Selector selector = operator.selector;
893 // TODO(johnniwinther): Remove this when all information goes through the 939 // TODO(johnniwinther): Remove this when all information goes through the
894 // [SendStructure]. 940 // [SendStructure].
895 registry.setSelector(node, selector); 941 registry.setSelector(node, selector);
896 942
897 AccessSemantics semantics; 943 AccessSemantics semantics;
898 if (node.isSuperCall) { 944 if (node.isSuperCall) {
899 if (checkSuperAccess(node)) { 945 if (checkSuperAccess(node)) {
(...skipping 14 matching lines...) Expand all
914 } 960 }
915 if (semantics != null) { 961 if (semantics != null) {
916 // TODO(johnniwinther): Support invalid super access as an 962 // TODO(johnniwinther): Support invalid super access as an
917 // [AccessSemantics]. 963 // [AccessSemantics].
918 registry.registerSendStructure(node, 964 registry.registerSendStructure(node,
919 new UnaryStructure(semantics, operator)); 965 new UnaryStructure(semantics, operator));
920 } 966 }
921 return null; 967 return null;
922 } 968 }
923 969
970 /// Handle a not expression, like `!a`.
924 ResolutionResult handleNot(Send node, UnaryOperator operator) { 971 ResolutionResult handleNot(Send node, UnaryOperator operator) {
925 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT)); 972 assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));
926 973
927 Node expression = node.receiver; 974 Node expression = node.receiver;
928 visitExpression(expression); 975 visitExpression(expression);
929 registry.registerSendStructure(node, 976 registry.registerSendStructure(node,
930 new NotStructure(new DynamicAccess.dynamicProperty(expression))); 977 new NotStructure(new DynamicAccess.dynamicProperty(expression)));
931 return null; 978 return null;
932 } 979 }
933 980
981 /// Handle a logical and expression, like `a && b`.
934 ResolutionResult handleLogicalAnd(Send node) { 982 ResolutionResult handleLogicalAnd(Send node) {
935 Node left = node.receiver; 983 Node left = node.receiver;
936 Node right = node.arguments.head; 984 Node right = node.arguments.head;
937 doInPromotionScope(left, () => visitExpression(left)); 985 doInPromotionScope(left, () => visitExpression(left));
938 doInPromotionScope(right, () => visitExpression(right)); 986 doInPromotionScope(right, () => visitExpression(right));
939 registry.registerSendStructure(node, const LogicalAndStructure()); 987 registry.registerSendStructure(node, const LogicalAndStructure());
940 return null; 988 return null;
941 } 989 }
942 990
991 /// Handle a logical or expression, like `a || b`.
943 ResolutionResult handleLogicalOr(Send node) { 992 ResolutionResult handleLogicalOr(Send node) {
944 Node left = node.receiver; 993 Node left = node.receiver;
945 Node right = node.arguments.head; 994 Node right = node.arguments.head;
946 visitExpression(left); 995 visitExpression(left);
947 visitExpression(right); 996 visitExpression(right);
948 registry.registerSendStructure(node, const LogicalOrStructure()); 997 registry.registerSendStructure(node, const LogicalOrStructure());
949 return null; 998 return null;
950 } 999 }
951 1000
1001 /// Handle an if-null expression, like `a ?? b`.
952 ResolutionResult handleIfNull(Send node) { 1002 ResolutionResult handleIfNull(Send node) {
953 Node left = node.receiver; 1003 Node left = node.receiver;
954 Node right = node.arguments.head; 1004 Node right = node.arguments.head;
955 visitExpression(left); 1005 visitExpression(left);
956 visitExpression(right); 1006 visitExpression(right);
957 registry.registerSendStructure(node, const IfNullStructure()); 1007 registry.registerSendStructure(node, const IfNullStructure());
958 return null; 1008 return null;
959 } 1009 }
960 1010
1011 /// Handle the binary expression of an unresolved binary operator [text], like
1012 /// the no longer supported `a === b`.
961 ResolutionResult handleUnresolvedBinary(Send node, String text) { 1013 ResolutionResult handleUnresolvedBinary(Send node, String text) {
962 Node left = node.receiver; 1014 Node left = node.receiver;
963 Node right = node.arguments.head; 1015 Node right = node.arguments.head;
964 if (node.isSuperCall) { 1016 if (node.isSuperCall) {
965 checkSuperAccess(node); 1017 checkSuperAccess(node);
966 } else { 1018 } else {
967 visitExpression(left); 1019 visitExpression(left);
968 } 1020 }
969 visitExpression(right); 1021 visitExpression(right);
970 registry.registerSendStructure(node, const InvalidBinaryStructure()); 1022 registry.registerSendStructure(node, const InvalidBinaryStructure());
971 return null; 1023 return null;
972 } 1024 }
973 1025
1026 /// Handle the binary expression of a user definable binary [operator], like
1027 /// `a + b`, `super + b`, `a == b` and `a != b`.
974 ResolutionResult handleUserDefinableBinary(Send node, 1028 ResolutionResult handleUserDefinableBinary(Send node,
975 BinaryOperator operator) { 1029 BinaryOperator operator) {
976 Node left = node.receiver; 1030 Node left = node.receiver;
977 Node right = node.arguments.head; 1031 Node right = node.arguments.head;
978 AccessSemantics semantics; 1032 AccessSemantics semantics;
979 Selector selector; 1033 Selector selector;
980 if (operator.kind == BinaryOperatorKind.INDEX) { 1034 if (operator.kind == BinaryOperatorKind.INDEX) {
981 selector = new Selector.index(); 1035 selector = new Selector.index();
982 } else { 1036 } else {
983 selector = new Selector.binaryOperator(operator.selectorName); 1037 selector = new Selector.binaryOperator(operator.selectorName);
984 } 1038 }
985 // TODO(johnniwinther): Remove this when all information goes through the 1039 // TODO(johnniwinther): Remove this when all information goes through the
986 // [SendStructure]. 1040 // [SendStructure].
987 registry.setSelector(node, selector); 1041 registry.setSelector(node, selector);
988 1042
989 if (node.isSuperCall) { 1043 if (node.isSuperCall) {
990 if (checkSuperAccess(node)) { 1044 if (checkSuperAccess(node)) {
991 semantics = computeSuperSemantics(node, selector); 1045 semantics = computeSuperSemantics(node, selector);
992 // TODO(johnniwinther): Add information to [AccessSemantics] about 1046 // TODO(johnniwinther): Add information to [AccessSemantics] about
993 // whether it is erroneous. 1047 // whether it is erroneous.
994 if (semantics.kind == AccessKind.SUPER_METHOD) { 1048 if (semantics.kind == AccessKind.SUPER_METHOD) {
995 registry.registerStaticUse(semantics.element.declaration); 1049 registry.registerStaticUse(semantics.element.declaration);
996 } 1050 }
997 // TODO(johnniwinther): Remove this when all information goes through 1051 // TODO(johnniwinther): Remove this when all information goes through
998 // the [SendStructure]. 1052 // the [SendStructure].
999 registry.useElement(node, semantics.element); 1053 registry.useElement(node, semantics.element);
1000
1001 } 1054 }
1002 } else { 1055 } else {
1003 visitExpression(left); 1056 visitExpression(left);
1004 registry.registerDynamicInvocation(selector); 1057 registry.registerDynamicInvocation(selector);
1005 semantics = new DynamicAccess.dynamicProperty(left); 1058 semantics = new DynamicAccess.dynamicProperty(left);
1006 } 1059 }
1007 visitExpression(right); 1060 visitExpression(right);
1008 1061
1009 if (semantics != null) { 1062 if (semantics != null) {
1010 // TODO(johnniwinther): Support invalid super access as an 1063 // TODO(johnniwinther): Support invalid super access as an
(...skipping 30 matching lines...) Expand all
1041 case BinaryOperatorKind.LOGICAL_OR: 1094 case BinaryOperatorKind.LOGICAL_OR:
1042 case BinaryOperatorKind.IF_NULL: 1095 case BinaryOperatorKind.IF_NULL:
1043 internalError(node, "Unexpected binary operator '${operator}'."); 1096 internalError(node, "Unexpected binary operator '${operator}'.");
1044 break; 1097 break;
1045 } 1098 }
1046 registry.registerSendStructure(node, sendStructure); 1099 registry.registerSendStructure(node, sendStructure);
1047 } 1100 }
1048 return null; 1101 return null;
1049 } 1102 }
1050 1103
1104 /// Handle an invocation of an expression, like `(){}()` or `(foo)()`.
1105 ResolutionResult handleExpressionInvoke(Send node) {
1106 assert(invariant(node, node.isCall,
1107 message: "Unexpected expression: $node"));
1108 Node expression = node.selector;
1109 visitExpression(expression);
1110 CallStructure callStructure = resolveArguments(node.argumentsNode);
1111 Selector selector = callStructure.callSelector;
1112 // TODO(johnniwinther): Remove this when all information goes through the
karlklose 2015/05/29 11:12:14 Maybe extract setSelector/registerDynamicInvocatio
Johnni Winther 2015/05/29 12:47:54 The two are not always paired :(
1113 // [SendStructure].
1114 registry.setSelector(node, selector);
1115 registry.registerDynamicInvocation(selector);
1116 registry.registerSendStructure(node,
1117 new InvokeStructure(new AccessSemantics.expression(), selector));
1118 return null;
1119 }
1120
1121 /// Handle a, possibly invalid, assertion, like `assert(cond)` or `assert()`.
1122 ResolutionResult handleAssert(Send node) {
1123 assert(invariant(node, node.isCall,
1124 message: "Unexpected assert: $node"));
1125 // If this send is of the form "assert(expr);", then
1126 // this is an assertion.
1127
1128 CallStructure callStructure = resolveArguments(node.argumentsNode);
1129 SendStructure sendStructure = const AssertStructure();
1130 if (callStructure.argumentCount != 1) {
1131 compiler.reportError(
1132 node.selector,
1133 MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT,
1134 {'argumentCount': callStructure.argumentCount});
1135 sendStructure = const InvalidAssertStructure();
1136 } else if (callStructure.namedArgumentCount != 0) {
1137 compiler.reportError(
1138 node.selector,
1139 MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS,
1140 {'argumentCount': callStructure.namedArgumentCount});
1141 sendStructure = const InvalidAssertStructure();
1142 }
1143 registry.registerAssert(node);
1144 registry.registerSendStructure(node, sendStructure);
1145 return const AssertResult();
1146 }
1147
1148 /// Handle access of a property of [name] on `this`, like `this.name` and
1149 /// `this.name()`, or `name` and `name()` in instance context.
1150 ResolutionResult handleThisPropertyAccess(Send node, Name name) {
1151 AccessSemantics accessSemantics = new AccessSemantics.thisProperty();
1152 SendStructure sendStructure;
1153 Selector selector;
1154 if (node.isCall) {
1155 CallStructure callStructure = resolveArguments(node.argumentsNode);
1156 selector = new Selector(SelectorKind.CALL, name, callStructure);
1157 registry.registerDynamicInvocation(selector);
1158 sendStructure = new InvokeStructure(accessSemantics, selector);
1159 } else {
1160 assert(invariant(node, node.isPropertyAccess));
1161 selector = new Selector(
1162 SelectorKind.GETTER, name, CallStructure.NO_ARGS);
1163 registry.registerDynamicGetter(selector);
1164 sendStructure = new GetStructure(accessSemantics, selector);
1165 }
1166 registry.registerSendStructure(node, sendStructure);
1167 // TODO(johnniwinther): Remove this when all information goes through
1168 // the [SendStructure].
1169 registry.setSelector(node, selector);
1170 return null;
1171 }
1172
1173 /// Handle access on `this`, like `this()` and `this` when it is parsed as a
1174 /// [Send] node.
1175 ResolutionResult handleThisAccess(Send node) {
1176 AccessSemantics accessSemantics = new AccessSemantics.thisAccess();
1177 if (node.isCall) {
1178 CallStructure callStructure = resolveArguments(node.argumentsNode);
1179 Selector selector = callStructure.callSelector;
1180 // Handle invalid this access as an [AccessSemantics].
1181 if (checkThisAccess(node)) {
1182 registry.registerDynamicInvocation(selector);
1183 registry.registerSendStructure(node,
1184 new InvokeStructure(accessSemantics, selector));
1185 }
1186 // TODO(johnniwinther): Remove this when all information goes through
1187 // the [SendStructure].
1188 registry.setSelector(node, selector);
1189 } else {
1190 // TODO(johnniwinther): Handle get of `this` when it is a [Send] node.
1191 internalError(node, "Unexpected node '$node'.");
1192 }
1193 return null;
1194 }
1195
1196 /// Handle access of a super property, like `super.foo` and `super.foo()`.
1197 ResolutionResult handleSuperPropertyAccess(Send node, Name name) {
1198 Element target;
1199 Selector selector;
1200 CallStructure callStructure = CallStructure.NO_ARGS;
1201 if (node.isCall) {
1202 callStructure = resolveArguments(node.argumentsNode);
1203 selector = new Selector(SelectorKind.CALL, name, callStructure);
1204 } else {
1205 selector = new Selector(SelectorKind.GETTER, name, callStructure);
1206 }
1207 if (checkSuperAccess(node)) {
1208 AccessSemantics semantics = computeSuperSemantics(
1209 node, selector, alternateName: name.setter);
1210 if (node.isCall) {
1211 bool isIncompatibleInvoke = false;
1212 switch (semantics.kind) {
1213 case AccessKind.SUPER_METHOD:
1214 MethodElementX superMethod = semantics.element;
1215 superMethod.computeSignature(compiler);
1216 if (!callStructure.signatureApplies(superMethod)) {
1217 registry.registerThrowNoSuchMethod();
1218 registry.registerDynamicInvocation(selector);
1219 registry.registerSuperNoSuchMethod();
1220 isIncompatibleInvoke = true;
1221 } else {
1222 registry.registerStaticInvocation(semantics.element);
1223 }
1224 break;
1225 case AccessKind.SUPER_FIELD:
1226 case AccessKind.SUPER_GETTER:
1227 registry.registerStaticUse(semantics.element);
1228 selector = callStructure.callSelector;
1229 registry.registerDynamicInvocation(selector);
1230 break;
1231 case AccessKind.SUPER_SETTER:
1232 case AccessKind.UNRESOLVED_SUPER:
1233 // NoSuchMethod registered in [computeSuperSemantics].
1234 break;
1235 default:
1236 internalError(node, "Unexpected super property access $semantics.");
1237 break;
1238 }
1239 registry.registerSendStructure(node,
1240 isIncompatibleInvoke
1241 ? new IncompatibleInvokeStructure(semantics, selector)
1242 : new InvokeStructure(semantics, selector));
1243 } else {
1244 switch (semantics.kind) {
1245 case AccessKind.SUPER_METHOD:
1246 // TODO(johnniwinther): Method this should be registered as a
1247 // closurization.
1248 registry.registerStaticUse(semantics.element);
1249 break;
1250 case AccessKind.SUPER_FIELD:
1251 case AccessKind.SUPER_GETTER:
1252 registry.registerStaticUse(semantics.element);
1253 break;
1254 case AccessKind.SUPER_SETTER:
1255 case AccessKind.UNRESOLVED_SUPER:
1256 // NoSuchMethod registered in [computeSuperSemantics].
1257 break;
1258 default:
1259 internalError(node, "Unexpected super property access $semantics.");
1260 break;
1261 }
1262 registry.registerSendStructure(node,
1263 new GetStructure(semantics, selector));
1264 }
1265 target = semantics.element;
1266 }
1267 if (node.isConditional) {
karlklose 2015/05/29 11:12:14 Should this be an internalError?
Johnni Winther 2015/05/29 12:47:54 Removed.
1268
1269 }
1270 // TODO(johnniwinther): Remove these when all information goes through
1271 // the [SendStructure].
1272 registry.useElement(node, target);
1273 registry.setSelector(node, selector);
1274 return null;
1275 }
1276
1277 /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`,
1278 /// `a + b`, and `~a`.
1279 ResolutionResult handleOperatorSend(Send node) {
1280 String operatorText = node.selector.asOperator().source;
1281 if (operatorText == 'is') {
1282 return handleIs(node);
1283 } else if (operatorText == 'as') {
1284 return handleAs(node);
1285 } else if (node.arguments.isEmpty) {
1286 UnaryOperator operator = UnaryOperator.parse(operatorText);
1287 if (operator == null) {
1288 return handleUnresolvedUnary(node, operatorText);
1289 } else {
1290 switch (operator.kind) {
1291 case UnaryOperatorKind.NOT:
1292 return handleNot(node, operator);
1293 case UnaryOperatorKind.COMPLEMENT:
1294 case UnaryOperatorKind.NEGATE:
1295 assert(invariant(node, operator.isUserDefinable,
1296 message: "Unexpected unary operator '${operator}'."));
1297 return handleUserDefinableUnary(node, operator);
1298 }
1299 return handleUserDefinableUnary(node, operator);
1300 }
1301 } else {
1302 BinaryOperator operator = BinaryOperator.parse(operatorText);
1303 if (operator == null) {
1304 return handleUnresolvedBinary(node, operatorText);
1305 } else {
1306 switch (operator.kind) {
1307 case BinaryOperatorKind.LOGICAL_AND:
1308 return handleLogicalAnd(node);
1309 case BinaryOperatorKind.LOGICAL_OR:
1310 return handleLogicalOr(node);
1311 case BinaryOperatorKind.IF_NULL:
1312 return handleIfNull(node);
1313 case BinaryOperatorKind.EQ:
1314 case BinaryOperatorKind.NOT_EQ:
1315 case BinaryOperatorKind.INDEX:
1316 case BinaryOperatorKind.ADD:
1317 case BinaryOperatorKind.SUB:
1318 case BinaryOperatorKind.MUL:
1319 case BinaryOperatorKind.DIV:
1320 case BinaryOperatorKind.IDIV:
1321 case BinaryOperatorKind.MOD:
1322 case BinaryOperatorKind.SHL:
1323 case BinaryOperatorKind.SHR:
1324 case BinaryOperatorKind.GTEQ:
1325 case BinaryOperatorKind.GT:
1326 case BinaryOperatorKind.LTEQ:
1327 case BinaryOperatorKind.LT:
1328 case BinaryOperatorKind.AND:
1329 case BinaryOperatorKind.OR:
1330 case BinaryOperatorKind.XOR:
1331 return handleUserDefinableBinary(node, operator);
1332 }
1333 }
1334 }
1335 }
1336
1337 /// Handle a qualified [Send], that is where the receiver is non-null, like
1338 /// `a.b`, `a.b()`, `this.a()` and `super.a()`.
1339 ResolutionResult handleQualifiedSend(Send node) {
1340 Identifier selector = node.selector.asIdentifier();
1341 Name name = new Name(selector.source, enclosingElement.library);
1342 if (node.isSuperCall) {
1343 return handleSuperPropertyAccess(node, name);
1344 } else if (node.receiver.isThis()) {
1345 return handleThisPropertyAccess(node, name);
1346 }
1347 // TODO(johnniwinther): Handle remaining qualified sends.
1348 return oldVisitSend(node);
1349 }
1350
1351 /// Handle access unresolved access to [name] in a non-instance context.
1352 ResolutionResult handleUnresolvedAccess(
1353 Send node, Name name, Element element) {
1354 // TODO(johnniwinther): Support unresolved top level access as an
1355 // [AccessSemantics].
1356 AccessSemantics accessSemantics = new StaticAccess.unresolved(element);
1357 SendStructure sendStructure;
1358 Selector selector;
1359 if (node.isCall) {
1360 CallStructure callStructure = resolveArguments(node.argumentsNode);
1361 selector = new Selector(SelectorKind.CALL, name, callStructure);
1362 registry.registerDynamicInvocation(selector);
1363 sendStructure = new InvokeStructure(accessSemantics, selector);
1364 } else {
1365 assert(invariant(node, node.isPropertyAccess));
1366 selector = new Selector(
1367 SelectorKind.GETTER, name, CallStructure.NO_ARGS);
1368 registry.registerDynamicGetter(selector);
1369 sendStructure = new GetStructure(accessSemantics, selector);
1370 }
1371 // TODO(johnniwinther): Remove this when all information goes through
1372 // the [SendStructure].
1373 registry.setSelector(node, selector);
1374 registry.useElement(node, element);
1375 registry.registerSendStructure(node, sendStructure);
1376 return null;
1377 }
1378
1379 /// Handle an unqualified [Send], that is where the receiver is null, like
karlklose 2015/05/29 11:12:14 Make clear that the receiver Node is null, not the
Johnni Winther 2015/05/29 12:47:54 Good call!
1380 /// `a`, `a()`, `this()`, `assert()`, and `(){}()`.
1381 ResolutionResult handleUnqualifiedSend(Send node) {
1382 Identifier selector = node.selector.asIdentifier();
1383 if (selector == null) {
1384 // `(){}()` and `(foo)()`.
1385 return handleExpressionInvoke(node);
1386 }
1387 String text = selector.source;
1388 if (text == 'assert') {
1389 // `assert()`.
1390 return handleAssert(node);
1391 } else if (text == 'this') {
1392 // `this()`.
1393 return handleThisAccess(node);
1394 } else if (text == 'dynamic') {
1395 // `dynamic` || `dynamic()`.
1396 // TODO(johnniwinther): Handle dynamic type literal access.
1397 return oldVisitSend(node);
1398 }
1399 // `name` or `name()`
1400 Name name = new Name(text, enclosingElement.library);
1401 Element element = lookupInScope(compiler, node, scope, text);
1402 if (element == null) {
1403 if (inInstanceContext) {
1404 // Implicitly `this.name`.
1405 return handleThisPropertyAccess(node, name);
1406 } else {
1407 // Create [ErroneousElement] for unresolved access.
1408 ErroneousElement error = reportCannotResolve(node, text);
1409 return handleUnresolvedAccess(node, name, error);
1410 }
1411 }
1412 return oldVisitSend(node);
1413 }
1414
1051 ResolutionResult visitSend(Send node) { 1415 ResolutionResult visitSend(Send node) {
1052 if (node.isOperator) { 1416 if (node.isOperator) {
1053 String operatorText = node.selector.asOperator().source; 1417 return handleOperatorSend(node);
1054 if (operatorText == 'is') { 1418 } else if (node.receiver != null) {
1055 return handleIs(node); 1419 return handleQualifiedSend(node);
1056 } else if (operatorText == 'as') { 1420 } else {
1057 return handleAs(node); 1421 return handleUnqualifiedSend(node);
1058 } else if (node.arguments.isEmpty) { 1422 }
1059 UnaryOperator operator = UnaryOperator.parse(operatorText); 1423 return oldVisitSend(node);
1060 if (operator == null) { 1424 }
1061 return handleUnresolvedUnary(node, operatorText); 1425
1062 } else { 1426 ResolutionResult oldVisitSend(Send node) {
1063 switch (operator.kind) {
1064 case UnaryOperatorKind.NOT:
1065 return handleNot(node, operator);
1066 case UnaryOperatorKind.COMPLEMENT:
1067 case UnaryOperatorKind.NEGATE:
1068 assert(invariant(node, operator.isUserDefinable,
1069 message: "Unexpected unary operator '${operator}'."));
1070 return handleUserDefinableUnary(node, operator);
1071 }
1072 return handleUserDefinableUnary(node, operator);
1073 }
1074 } else {
1075 BinaryOperator operator = BinaryOperator.parse(operatorText);
1076 if (operator == null) {
1077 return handleUnresolvedBinary(node, operatorText);
1078 } else {
1079 switch (operator.kind) {
1080 case BinaryOperatorKind.LOGICAL_AND:
1081 return handleLogicalAnd(node);
1082 case BinaryOperatorKind.LOGICAL_OR:
1083 return handleLogicalOr(node);
1084 case BinaryOperatorKind.IF_NULL:
1085 return handleIfNull(node);
1086 case BinaryOperatorKind.EQ:
1087 case BinaryOperatorKind.NOT_EQ:
1088 case BinaryOperatorKind.INDEX:
1089 case BinaryOperatorKind.ADD:
1090 case BinaryOperatorKind.SUB:
1091 case BinaryOperatorKind.MUL:
1092 case BinaryOperatorKind.DIV:
1093 case BinaryOperatorKind.IDIV:
1094 case BinaryOperatorKind.MOD:
1095 case BinaryOperatorKind.SHL:
1096 case BinaryOperatorKind.SHR:
1097 case BinaryOperatorKind.GTEQ:
1098 case BinaryOperatorKind.GT:
1099 case BinaryOperatorKind.LTEQ:
1100 case BinaryOperatorKind.LT:
1101 case BinaryOperatorKind.AND:
1102 case BinaryOperatorKind.OR:
1103 case BinaryOperatorKind.XOR:
1104 return handleUserDefinableBinary(node, operator);
1105 }
1106 }
1107 }
1108 }
1109
1110 bool oldSendIsMemberAccess = sendIsMemberAccess; 1427 bool oldSendIsMemberAccess = sendIsMemberAccess;
1111 sendIsMemberAccess = node.isPropertyAccess || node.isCall; 1428 sendIsMemberAccess = node.isPropertyAccess || node.isCall;
1112 1429
1113 ResolutionResult result = resolveSend(node); 1430 ResolutionResult result = resolveSend(node);
1114 sendIsMemberAccess = oldSendIsMemberAccess; 1431 sendIsMemberAccess = oldSendIsMemberAccess;
1115 1432
1116 Element target = result != null ? result.element : null; 1433 Element target = result != null ? result.element : null;
1117 1434
1118 if (target != null 1435 if (target != null
1119 && target == compiler.mirrorSystemGetNameFunction 1436 && target == compiler.mirrorSystemGetNameFunction
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1183 // class or typedef literal. We do not need to register this call as a 1500 // class or typedef literal. We do not need to register this call as a
1184 // dynamic invocation, because we statically know what the target is. 1501 // dynamic invocation, because we statically know what the target is.
1185 } else { 1502 } else {
1186 if (target is FunctionElement) { 1503 if (target is FunctionElement) {
1187 FunctionElement function = target; 1504 FunctionElement function = target;
1188 function.computeSignature(compiler); 1505 function.computeSignature(compiler);
1189 } 1506 }
1190 if (!selector.applies(target, compiler.world)) { 1507 if (!selector.applies(target, compiler.world)) {
1191 registry.registerThrowNoSuchMethod(); 1508 registry.registerThrowNoSuchMethod();
1192 if (node.isSuperCall) { 1509 if (node.isSuperCall) {
1193 // Similar to what we do when we can't find super via selector 1510 internalError(node, "Unexpected super call $node");
1194 // in [resolveSend] above, we still need to register the invocation,
1195 // because we might call [:super.noSuchMethod:] which calls
1196 // [JSInvocationMirror._invokeOn].
1197 registry.registerDynamicInvocation(selector);
1198 registry.registerSuperNoSuchMethod();
1199 } 1511 }
1200 } 1512 }
1201 } 1513 }
1202 1514
1203 if (target != null && target.isForeign(compiler.backend)) { 1515 if (target != null && target.isForeign(compiler.backend)) {
1204 if (selector.name == 'JS') { 1516 if (selector.name == 'JS') {
1205 registry.registerJsCall(node, this); 1517 registry.registerJsCall(node, this);
1206 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { 1518 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') {
1207 registry.registerJsEmbeddedGlobalCall(node, this); 1519 registry.registerJsEmbeddedGlobalCall(node, this);
1208 } else if (selector.name == 'JS_BUILTIN') { 1520 } else if (selector.name == 'JS_BUILTIN') {
(...skipping 13 matching lines...) Expand all
1222 registry.useElement(node, target); 1534 registry.useElement(node, target);
1223 registerSend(selector, target); 1535 registerSend(selector, target);
1224 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { 1536 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
1225 registry.registerGetOfStaticFunction(target.declaration); 1537 registry.registerGetOfStaticFunction(target.declaration);
1226 } 1538 }
1227 return node.isPropertyAccess ? new ElementResult(target) : null; 1539 return node.isPropertyAccess ? new ElementResult(target) : null;
1228 } 1540 }
1229 1541
1230 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. 1542 /// Callback for native enqueuer to parse a type. Returns [:null:] on error.
1231 DartType resolveTypeFromString(Node node, String typeName) { 1543 DartType resolveTypeFromString(Node node, String typeName) {
1232 Element element = lookupInScope(compiler, node, 1544 Element element = lookupInScope(compiler, node, scope, typeName);
1233 scope, typeName);
1234 if (element == null) return null; 1545 if (element == null) return null;
1235 if (element is! ClassElement) return null; 1546 if (element is! ClassElement) return null;
1236 ClassElement cls = element; 1547 ClassElement cls = element;
1237 cls.ensureResolved(compiler); 1548 cls.ensureResolved(compiler);
1238 return cls.computeType(compiler); 1549 return cls.computeType(compiler);
1239 } 1550 }
1240 1551
1241 ResolutionResult visitSendSet(SendSet node) { 1552 ResolutionResult visitSendSet(SendSet node) {
1242 bool oldSendIsMemberAccess = sendIsMemberAccess; 1553 bool oldSendIsMemberAccess = sendIsMemberAccess;
1243 sendIsMemberAccess = node.isPropertyAccess || node.isCall; 1554 sendIsMemberAccess = node.isPropertyAccess || node.isCall;
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after
2331 visitTypedef(Typedef node) { 2642 visitTypedef(Typedef node) {
2332 internalError(node, 'typedef'); 2643 internalError(node, 'typedef');
2333 } 2644 }
2334 } 2645 }
2335 2646
2336 /// Looks up [name] in [scope] and unwraps the result. 2647 /// Looks up [name] in [scope] and unwraps the result.
2337 Element lookupInScope(Compiler compiler, Node node, 2648 Element lookupInScope(Compiler compiler, Node node,
2338 Scope scope, String name) { 2649 Scope scope, String name) {
2339 return Elements.unwrap(scope.lookup(name), compiler, node); 2650 return Elements.unwrap(scope.lookup(name), compiler, node);
2340 } 2651 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698