OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |