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 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
806 /// Check that access to `this` is currently allowed. | 806 /// Check that access to `this` is currently allowed. |
807 bool checkThisAccess(Send node) { | 807 bool checkThisAccess(Send node) { |
808 if (!inInstanceContext) { | 808 if (!inInstanceContext) { |
809 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE); | 809 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE); |
810 return false; | 810 return false; |
811 } | 811 } |
812 return true; | 812 return true; |
813 } | 813 } |
814 | 814 |
815 /// Compute the [AccessSemantics] corresponding to a super access of [target]. | 815 /// Compute the [AccessSemantics] corresponding to a super access of [target]. |
816 AccessSemantics computeSuperAccess(Spannable node, Element target) { | 816 AccessSemantics computeSuperAccessSemantics(Spannable node, Element target) { |
817 if (target.isErroneous) { | 817 if (target.isErroneous) { |
818 return new StaticAccess.unresolvedSuper(target); | 818 return new StaticAccess.unresolvedSuper(target); |
819 } else if (target.isGetter) { | 819 } else if (target.isGetter) { |
820 return new StaticAccess.superGetter(target); | 820 return new StaticAccess.superGetter(target); |
821 } else if (target.isSetter) { | 821 } else if (target.isSetter) { |
822 return new StaticAccess.superSetter(target); | 822 return new StaticAccess.superSetter(target); |
823 } else if (target.isField) { | 823 } else if (target.isField) { |
824 return new StaticAccess.superField(target); | 824 if (target.isFinal) { |
| 825 return new StaticAccess.superFinalField(target); |
| 826 } else { |
| 827 return new StaticAccess.superField(target); |
| 828 } |
825 } else { | 829 } else { |
826 assert(invariant(node, target.isFunction, | 830 assert(invariant(node, target.isFunction, |
827 message: "Unexpected super target '$target'.")); | 831 message: "Unexpected super target '$target'.")); |
828 return new StaticAccess.superMethod(target); | 832 return new StaticAccess.superMethod(target); |
829 } | 833 } |
830 } | 834 } |
831 | 835 |
| 836 /// Compute the [AccessSemantics] corresponding to a local access of [target]. |
| 837 AccessSemantics computeLocalAccessSemantics(Spannable node, |
| 838 LocalElement target) { |
| 839 if (target.isParameter) { |
| 840 if (target.isFinal || target.isConst) { |
| 841 return new StaticAccess.finalParameter(target); |
| 842 } else { |
| 843 return new StaticAccess.parameter(target); |
| 844 } |
| 845 } else if (target.isVariable) { |
| 846 if (target.isFinal || target.isConst) { |
| 847 return new StaticAccess.finalLocalVariable(target); |
| 848 } else { |
| 849 return new StaticAccess.localVariable(target); |
| 850 } |
| 851 } else { |
| 852 assert(invariant(node, target.isFunction, |
| 853 message: "Unexpected local target '$target'.")); |
| 854 return new StaticAccess.localFunction(target); |
| 855 } |
| 856 } |
| 857 |
| 858 /// Compute the [AccessSemantics] corresponding to a static or toplevel access |
| 859 /// of [target]. |
| 860 AccessSemantics computeStaticOrTopLevelAccessSemantics( |
| 861 Spannable node, |
| 862 Element target) { |
| 863 |
| 864 target = target.declaration; |
| 865 if (target.isErroneous) { |
| 866 // This handles elements with parser errors. |
| 867 // TODO(johnniwinther): Elements with parse error should not set |
| 868 // [isErroneous] to `true`. |
| 869 return new StaticAccess.unresolved(target); |
| 870 } |
| 871 if (target.isStatic) { |
| 872 if (target.isGetter) { |
| 873 return new StaticAccess.staticGetter(target); |
| 874 } else if (target.isSetter) { |
| 875 return new StaticAccess.staticSetter(target); |
| 876 } else if (target.isField) { |
| 877 if (target.isFinal || target.isConst) { |
| 878 return new StaticAccess.finalStaticField(target); |
| 879 } else { |
| 880 return new StaticAccess.staticField(target); |
| 881 } |
| 882 } else { |
| 883 assert(invariant(node, target.isFunction, |
| 884 message: "Unexpected static target '$target'.")); |
| 885 return new StaticAccess.staticMethod(target); |
| 886 } |
| 887 } else { |
| 888 assert(invariant(node, target.isTopLevel, |
| 889 message: "Unexpected statically resolved target '$target'.")); |
| 890 if (target.isGetter) { |
| 891 return new StaticAccess.topLevelGetter(target); |
| 892 } else if (target.isSetter) { |
| 893 return new StaticAccess.topLevelSetter(target); |
| 894 } else if (target.isField) { |
| 895 if (target.isFinal) { |
| 896 return new StaticAccess.finalTopLevelField(target); |
| 897 } else { |
| 898 return new StaticAccess.topLevelField(target); |
| 899 } |
| 900 } else { |
| 901 assert(invariant(node, target.isFunction, |
| 902 message: "Unexpected top level target '$target'.")); |
| 903 return new StaticAccess.topLevelMethod(target); |
| 904 } |
| 905 } |
| 906 } |
| 907 |
832 /// Compute the [AccessSemantics] for accessing the name of [selector] on the | 908 /// Compute the [AccessSemantics] for accessing the name of [selector] on the |
833 /// super class. | 909 /// super class. |
834 /// | 910 /// |
835 /// If no matching super member is found and error is reported and | 911 /// If no matching super member is found and error is reported and |
836 /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName] | 912 /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName] |
837 /// is provided, the [AccessSemantics] corresponding to the alternate name is | 913 /// is provided, the [AccessSemantics] corresponding to the alternate name is |
838 /// returned. For instance, the access of a super setter for an unresolved | 914 /// returned. For instance, the access of a super setter for an unresolved |
839 /// getter: | 915 /// getter: |
840 /// | 916 /// |
841 /// class Super { | 917 /// class Super { |
842 /// set name(_) {} | 918 /// set name(_) {} |
843 /// } | 919 /// } |
844 /// class Sub extends Super { | 920 /// class Sub extends Super { |
845 /// foo => super.name; // Access to the setter. | 921 /// foo => super.name; // Access to the setter. |
846 /// } | 922 /// } |
847 /// | 923 /// |
848 AccessSemantics computeSuperSemantics(Spannable node, | 924 AccessSemantics computeSuperAccessSemanticsForSelector( |
849 Selector selector, | 925 Spannable node, |
850 {Name alternateName}) { | 926 Selector selector, |
| 927 {Name alternateName}) { |
| 928 |
851 Name name = selector.memberName; | 929 Name name = selector.memberName; |
852 // TODO(johnniwinther): Ensure correct behavior if currentClass is a | 930 // TODO(johnniwinther): Ensure correct behavior if currentClass is a |
853 // patch. | 931 // patch. |
854 Element target = currentClass.lookupSuperByName(name); | 932 Element target = currentClass.lookupSuperByName(name); |
855 // [target] may be null which means invoking noSuchMethod on super. | 933 // [target] may be null which means invoking noSuchMethod on super. |
856 if (target == null) { | 934 if (target == null) { |
857 Element error = reportAndCreateErroneousElement( | 935 Element error = reportAndCreateErroneousElement( |
858 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER, | 936 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER, |
859 {'className': currentClass.name, 'memberName': name}); | 937 {'className': currentClass.name, 'memberName': name}); |
860 if (alternateName != null) { | 938 if (alternateName != null) { |
861 target = currentClass.lookupSuperByName(alternateName); | 939 target = currentClass.lookupSuperByName(alternateName); |
862 } | 940 } |
863 if (target == null) { | 941 if (target == null) { |
864 // If a setter wasn't resolved, use the [ErroneousElement]. | 942 // If a setter wasn't resolved, use the [ErroneousElement]. |
865 target = error; | 943 target = error; |
866 } | 944 } |
867 // We still need to register the invocation, because we might | 945 // We still need to register the invocation, because we might |
868 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. | 946 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. |
869 registry.registerDynamicInvocation(selector); | 947 registry.registerDynamicInvocation(selector); |
870 registry.registerSuperNoSuchMethod(); | 948 registry.registerSuperNoSuchMethod(); |
871 } | 949 } |
872 return computeSuperAccess(node, target); | 950 return computeSuperAccessSemantics(node, target); |
873 } | 951 } |
874 | 952 |
875 /// Resolve [node] as subexpression that is _not_ the prefix of a member | 953 /// Resolve [node] as subexpression that is _not_ the prefix of a member |
876 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. | 954 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. |
877 ResolutionResult visitExpression(Node node) { | 955 ResolutionResult visitExpression(Node node) { |
878 bool oldSendIsMemberAccess = sendIsMemberAccess; | 956 bool oldSendIsMemberAccess = sendIsMemberAccess; |
879 sendIsMemberAccess = false; | 957 sendIsMemberAccess = false; |
880 ResolutionResult result = visit(node); | 958 ResolutionResult result = visit(node); |
881 sendIsMemberAccess = oldSendIsMemberAccess; | 959 sendIsMemberAccess = oldSendIsMemberAccess; |
882 return result; | 960 return result; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
941 ResolutionResult result = const NoneResult(); | 1019 ResolutionResult result = const NoneResult(); |
942 Node expression = node.receiver; | 1020 Node expression = node.receiver; |
943 Selector selector = operator.selector; | 1021 Selector selector = operator.selector; |
944 // TODO(johnniwinther): Remove this when all information goes through the | 1022 // TODO(johnniwinther): Remove this when all information goes through the |
945 // [SendStructure]. | 1023 // [SendStructure]. |
946 registry.setSelector(node, selector); | 1024 registry.setSelector(node, selector); |
947 | 1025 |
948 AccessSemantics semantics; | 1026 AccessSemantics semantics; |
949 if (node.isSuperCall) { | 1027 if (node.isSuperCall) { |
950 if (checkSuperAccess(node)) { | 1028 if (checkSuperAccess(node)) { |
951 semantics = computeSuperSemantics(node, selector); | 1029 semantics = computeSuperAccessSemanticsForSelector(node, selector); |
952 // TODO(johnniwinther): Add information to [AccessSemantics] about | 1030 // TODO(johnniwinther): Add information to [AccessSemantics] about |
953 // whether it is erroneous. | 1031 // whether it is erroneous. |
954 if (semantics.kind == AccessKind.SUPER_METHOD) { | 1032 if (semantics.kind == AccessKind.SUPER_METHOD) { |
955 registry.registerStaticUse(semantics.element.declaration); | 1033 registry.registerStaticUse(semantics.element.declaration); |
956 } | 1034 } |
957 // TODO(johnniwinther): Remove this when all information goes through | 1035 // TODO(johnniwinther): Remove this when all information goes through |
958 // the [SendStructure]. | 1036 // the [SendStructure]. |
959 registry.useElement(node, semantics.element); | 1037 registry.useElement(node, semantics.element); |
960 } | 1038 } |
961 } else { | 1039 } else { |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 selector = new Selector.index(); | 1193 selector = new Selector.index(); |
1116 } else { | 1194 } else { |
1117 selector = new Selector.binaryOperator(operator.selectorName); | 1195 selector = new Selector.binaryOperator(operator.selectorName); |
1118 } | 1196 } |
1119 // TODO(johnniwinther): Remove this when all information goes through the | 1197 // TODO(johnniwinther): Remove this when all information goes through the |
1120 // [SendStructure]. | 1198 // [SendStructure]. |
1121 registry.setSelector(node, selector); | 1199 registry.setSelector(node, selector); |
1122 | 1200 |
1123 if (node.isSuperCall) { | 1201 if (node.isSuperCall) { |
1124 if (checkSuperAccess(node)) { | 1202 if (checkSuperAccess(node)) { |
1125 semantics = computeSuperSemantics(node, selector); | 1203 semantics = computeSuperAccessSemanticsForSelector(node, selector); |
1126 // TODO(johnniwinther): Add information to [AccessSemantics] about | 1204 // TODO(johnniwinther): Add information to [AccessSemantics] about |
1127 // whether it is erroneous. | 1205 // whether it is erroneous. |
1128 if (semantics.kind == AccessKind.SUPER_METHOD) { | 1206 if (semantics.kind == AccessKind.SUPER_METHOD) { |
1129 registry.registerStaticUse(semantics.element.declaration); | 1207 registry.registerStaticUse(semantics.element.declaration); |
1130 } | 1208 } |
1131 // TODO(johnniwinther): Remove this when all information goes through | 1209 // TODO(johnniwinther): Remove this when all information goes through |
1132 // the [SendStructure]. | 1210 // the [SendStructure]. |
1133 registry.useElement(node, semantics.element); | 1211 registry.useElement(node, semantics.element); |
1134 } | 1212 } |
1135 visitExpression(right); | 1213 visitExpression(right); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 Element target; | 1433 Element target; |
1356 Selector selector; | 1434 Selector selector; |
1357 CallStructure callStructure = CallStructure.NO_ARGS; | 1435 CallStructure callStructure = CallStructure.NO_ARGS; |
1358 if (node.isCall) { | 1436 if (node.isCall) { |
1359 callStructure = resolveArguments(node.argumentsNode); | 1437 callStructure = resolveArguments(node.argumentsNode); |
1360 selector = new Selector(SelectorKind.CALL, name, callStructure); | 1438 selector = new Selector(SelectorKind.CALL, name, callStructure); |
1361 } else { | 1439 } else { |
1362 selector = new Selector(SelectorKind.GETTER, name, callStructure); | 1440 selector = new Selector(SelectorKind.GETTER, name, callStructure); |
1363 } | 1441 } |
1364 if (checkSuperAccess(node)) { | 1442 if (checkSuperAccess(node)) { |
1365 AccessSemantics semantics = computeSuperSemantics( | 1443 AccessSemantics semantics = computeSuperAccessSemanticsForSelector( |
1366 node, selector, alternateName: name.setter); | 1444 node, selector, alternateName: name.setter); |
1367 if (node.isCall) { | 1445 if (node.isCall) { |
1368 bool isIncompatibleInvoke = false; | 1446 bool isIncompatibleInvoke = false; |
1369 switch (semantics.kind) { | 1447 switch (semantics.kind) { |
1370 case AccessKind.SUPER_METHOD: | 1448 case AccessKind.SUPER_METHOD: |
1371 MethodElementX superMethod = semantics.element; | 1449 MethodElementX superMethod = semantics.element; |
1372 superMethod.computeSignature(compiler); | 1450 superMethod.computeSignature(compiler); |
1373 if (!callStructure.signatureApplies(superMethod)) { | 1451 if (!callStructure.signatureApplies(superMethod)) { |
1374 registry.registerThrowNoSuchMethod(); | 1452 registry.registerThrowNoSuchMethod(); |
1375 registry.registerDynamicInvocation(selector); | 1453 registry.registerDynamicInvocation(selector); |
1376 registry.registerSuperNoSuchMethod(); | 1454 registry.registerSuperNoSuchMethod(); |
1377 isIncompatibleInvoke = true; | 1455 isIncompatibleInvoke = true; |
1378 } else { | 1456 } else { |
1379 registry.registerStaticInvocation(semantics.element); | 1457 registry.registerStaticInvocation(semantics.element); |
1380 } | 1458 } |
1381 break; | 1459 break; |
1382 case AccessKind.SUPER_FIELD: | 1460 case AccessKind.SUPER_FIELD: |
| 1461 case AccessKind.SUPER_FINAL_FIELD: |
1383 case AccessKind.SUPER_GETTER: | 1462 case AccessKind.SUPER_GETTER: |
1384 registry.registerStaticUse(semantics.element); | 1463 registry.registerStaticUse(semantics.element); |
1385 selector = callStructure.callSelector; | 1464 selector = callStructure.callSelector; |
1386 registry.registerDynamicInvocation(selector); | 1465 registry.registerDynamicInvocation(selector); |
1387 break; | 1466 break; |
1388 case AccessKind.SUPER_SETTER: | 1467 case AccessKind.SUPER_SETTER: |
1389 case AccessKind.UNRESOLVED_SUPER: | 1468 case AccessKind.UNRESOLVED_SUPER: |
1390 // NoSuchMethod registered in [computeSuperSemantics]. | 1469 // NoSuchMethod registered in [computeSuperSemantics]. |
1391 break; | 1470 break; |
1392 default: | 1471 default: |
1393 internalError(node, "Unexpected super property access $semantics."); | 1472 internalError(node, "Unexpected super property access $semantics."); |
1394 break; | 1473 break; |
1395 } | 1474 } |
1396 registry.registerSendStructure(node, | 1475 registry.registerSendStructure(node, |
1397 isIncompatibleInvoke | 1476 isIncompatibleInvoke |
1398 ? new IncompatibleInvokeStructure(semantics, selector) | 1477 ? new IncompatibleInvokeStructure(semantics, selector) |
1399 : new InvokeStructure(semantics, selector)); | 1478 : new InvokeStructure(semantics, selector)); |
1400 } else { | 1479 } else { |
1401 switch (semantics.kind) { | 1480 switch (semantics.kind) { |
1402 case AccessKind.SUPER_METHOD: | 1481 case AccessKind.SUPER_METHOD: |
1403 // TODO(johnniwinther): Method this should be registered as a | 1482 // TODO(johnniwinther): Method this should be registered as a |
1404 // closurization. | 1483 // closurization. |
1405 registry.registerStaticUse(semantics.element); | 1484 registry.registerStaticUse(semantics.element); |
1406 break; | 1485 break; |
1407 case AccessKind.SUPER_FIELD: | 1486 case AccessKind.SUPER_FIELD: |
| 1487 case AccessKind.SUPER_FINAL_FIELD: |
1408 case AccessKind.SUPER_GETTER: | 1488 case AccessKind.SUPER_GETTER: |
1409 registry.registerStaticUse(semantics.element); | 1489 registry.registerStaticUse(semantics.element); |
1410 break; | 1490 break; |
1411 case AccessKind.SUPER_SETTER: | 1491 case AccessKind.SUPER_SETTER: |
1412 case AccessKind.UNRESOLVED_SUPER: | 1492 case AccessKind.UNRESOLVED_SUPER: |
1413 // NoSuchMethod registered in [computeSuperSemantics]. | 1493 // NoSuchMethod registered in [computeSuperSemantics]. |
1414 break; | 1494 break; |
1415 default: | 1495 default: |
1416 internalError(node, "Unexpected super property access $semantics."); | 1496 internalError(node, "Unexpected super property access $semantics."); |
1417 break; | 1497 break; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1507 // TODO(johnniwinther): Handle remaining qualified sends. | 1587 // TODO(johnniwinther): Handle remaining qualified sends. |
1508 return oldVisitSend(node); | 1588 return oldVisitSend(node); |
1509 } | 1589 } |
1510 | 1590 |
1511 /// Handle access unresolved access to [name] in a non-instance context. | 1591 /// Handle access unresolved access to [name] in a non-instance context. |
1512 ResolutionResult handleUnresolvedAccess( | 1592 ResolutionResult handleUnresolvedAccess( |
1513 Send node, Name name, Element element) { | 1593 Send node, Name name, Element element) { |
1514 // TODO(johnniwinther): Support unresolved top level access as an | 1594 // TODO(johnniwinther): Support unresolved top level access as an |
1515 // [AccessSemantics]. | 1595 // [AccessSemantics]. |
1516 AccessSemantics accessSemantics = new StaticAccess.unresolved(element); | 1596 AccessSemantics accessSemantics = new StaticAccess.unresolved(element); |
| 1597 return handleErroneousAccess(node, name, element, accessSemantics); |
| 1598 } |
| 1599 |
| 1600 /// Handle erroneous access of [element] of the given [accessSemantics]. |
| 1601 ResolutionResult handleErroneousAccess( |
| 1602 Send node, Name name, Element element, AccessSemantics accessSemantics) { |
1517 SendStructure sendStructure; | 1603 SendStructure sendStructure; |
1518 Selector selector; | 1604 Selector selector; |
1519 if (node.isCall) { | 1605 if (node.isCall) { |
1520 CallStructure callStructure = resolveArguments(node.argumentsNode); | 1606 CallStructure callStructure = resolveArguments(node.argumentsNode); |
1521 selector = new Selector(SelectorKind.CALL, name, callStructure); | 1607 selector = new Selector(SelectorKind.CALL, name, callStructure); |
1522 registry.registerDynamicInvocation(selector); | 1608 registry.registerDynamicInvocation(selector); |
1523 sendStructure = new InvokeStructure(accessSemantics, selector); | 1609 sendStructure = new InvokeStructure(accessSemantics, selector); |
1524 } else { | 1610 } else { |
1525 assert(invariant(node, node.isPropertyAccess)); | 1611 assert(invariant(node, node.isPropertyAccess)); |
1526 selector = new Selector( | 1612 selector = new Selector( |
1527 SelectorKind.GETTER, name, CallStructure.NO_ARGS); | 1613 SelectorKind.GETTER, name, CallStructure.NO_ARGS); |
1528 registry.registerDynamicGetter(selector); | 1614 registry.registerDynamicGetter(selector); |
1529 sendStructure = new GetStructure(accessSemantics, selector); | 1615 sendStructure = new GetStructure(accessSemantics, selector); |
1530 } | 1616 } |
1531 // TODO(johnniwinther): Remove this when all information goes through | 1617 // TODO(johnniwinther): Remove this when all information goes through |
1532 // the [SendStructure]. | 1618 // the [SendStructure]. |
1533 registry.setSelector(node, selector); | 1619 registry.setSelector(node, selector); |
1534 registry.useElement(node, element); | 1620 registry.useElement(node, element); |
1535 registry.registerSendStructure(node, sendStructure); | 1621 registry.registerSendStructure(node, sendStructure); |
1536 return const NoneResult(); | 1622 return const NoneResult(); |
1537 } | 1623 } |
1538 | 1624 |
| 1625 /// Handle access to an ambiguous element, that is, a name imported twice. |
| 1626 ResolutionResult handleAmbiguousSend( |
| 1627 Send node, |
| 1628 Name name, |
| 1629 AmbiguousElement element) { |
| 1630 |
| 1631 compiler.reportError( |
| 1632 node, element.messageKind, element.messageArguments); |
| 1633 element.diagnose(enclosingElement, compiler); |
| 1634 |
| 1635 ErroneousElement error = new ErroneousElementX( |
| 1636 element.messageKind, |
| 1637 element.messageArguments, |
| 1638 name.text, |
| 1639 enclosingElement); |
| 1640 |
| 1641 // TODO(johnniwinther): Support ambiguous access as an [AccessSemantics]. |
| 1642 AccessSemantics accessSemantics = new StaticAccess.unresolved(error); |
| 1643 return handleErroneousAccess(node, name, error, accessSemantics); |
| 1644 } |
| 1645 |
| 1646 /// Handle access of an instance [member] from a non-instance context. |
| 1647 ResolutionResult handleStaticInstanceSend( |
| 1648 Send node, Name name, MemberElement member) { |
| 1649 compiler.reportError( |
| 1650 node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': member.name}); |
| 1651 ErroneousElement error = new ErroneousElementX( |
| 1652 MessageKind.NO_INSTANCE_AVAILABLE, |
| 1653 {'name': name}, |
| 1654 name.text, |
| 1655 enclosingElement); |
| 1656 |
| 1657 // TODO(johnniwinther): Support static instance access as an |
| 1658 // [AccessSemantics]. |
| 1659 AccessSemantics accessSemantics = new StaticAccess.unresolved(error); |
| 1660 return handleErroneousAccess(node, name, error, accessSemantics); |
| 1661 } |
| 1662 |
| 1663 /// Handle access of a parameter, local variable or local function. |
| 1664 ResolutionResult handleLocalAccess(Send node, Name name, Element element) { |
| 1665 AccessSemantics semantics = computeLocalAccessSemantics(node, element); |
| 1666 Selector selector; |
| 1667 CallStructure callStructure = CallStructure.NO_ARGS; |
| 1668 if (node.isCall) { |
| 1669 callStructure = resolveArguments(node.argumentsNode); |
| 1670 selector = new Selector(SelectorKind.CALL, name, callStructure); |
| 1671 } else { |
| 1672 selector = new Selector(SelectorKind.GETTER, name, callStructure); |
| 1673 } |
| 1674 if (node.isCall) { |
| 1675 bool isIncompatibleInvoke = false; |
| 1676 switch (semantics.kind) { |
| 1677 case AccessKind.LOCAL_FUNCTION: |
| 1678 LocalFunctionElementX function = semantics.element; |
| 1679 function.computeSignature(compiler); |
| 1680 if (!callStructure.signatureApplies(function)) { |
| 1681 registry.registerThrowNoSuchMethod(); |
| 1682 registry.registerDynamicInvocation(selector); |
| 1683 isIncompatibleInvoke = true; |
| 1684 } |
| 1685 break; |
| 1686 case AccessKind.PARAMETER: |
| 1687 case AccessKind.FINAL_PARAMETER: |
| 1688 case AccessKind.LOCAL_VARIABLE: |
| 1689 case AccessKind.FINAL_LOCAL_VARIABLE: |
| 1690 selector = callStructure.callSelector; |
| 1691 registry.registerDynamicInvocation(selector); |
| 1692 break; |
| 1693 default: |
| 1694 internalError(node, |
| 1695 "Unexpected local access $semantics."); |
| 1696 break; |
| 1697 } |
| 1698 registry.registerSendStructure(node, |
| 1699 isIncompatibleInvoke |
| 1700 ? new IncompatibleInvokeStructure(semantics, selector) |
| 1701 : new InvokeStructure(semantics, selector)); |
| 1702 } else { |
| 1703 registry.registerSendStructure(node, |
| 1704 new GetStructure(semantics, selector)); |
| 1705 } |
| 1706 |
| 1707 // TODO(johnniwinther): Remove these when all information goes through |
| 1708 // the [SendStructure]. |
| 1709 registry.useElement(node, element); |
| 1710 registry.setSelector(node, selector); |
| 1711 |
| 1712 registerPotentialAccessInClosure(node, element); |
| 1713 |
| 1714 return node.isPropertyAccess |
| 1715 ? new ElementResult(element) : const NoneResult(); |
| 1716 } |
| 1717 |
| 1718 /// Handle access of a static or top level [element]. |
| 1719 ResolutionResult handleStaticOrTopLevelAccess( |
| 1720 Send node, Name name, Element element) { |
| 1721 |
| 1722 if (element.isAbstractField) { |
| 1723 AbstractFieldElement abstractField = element; |
| 1724 if (abstractField.getter != null) { |
| 1725 element = abstractField.getter; |
| 1726 } else { |
| 1727 element = abstractField.setter; |
| 1728 } |
| 1729 } |
| 1730 // TODO(johnniwinther): Needed to provoke a parsing and with it discovery |
| 1731 // of parse errors to make [element] erroneous. Fix this! |
| 1732 element.computeType(compiler); |
| 1733 |
| 1734 Selector selector; |
| 1735 CallStructure callStructure = CallStructure.NO_ARGS; |
| 1736 if (node.isCall) { |
| 1737 callStructure = resolveArguments(node.argumentsNode); |
| 1738 selector = new Selector(SelectorKind.CALL, name, callStructure); |
| 1739 } else { |
| 1740 selector = new Selector(SelectorKind.GETTER, name, callStructure); |
| 1741 } |
| 1742 AccessSemantics semantics = |
| 1743 computeStaticOrTopLevelAccessSemantics(node, element); |
| 1744 if (node.isCall) { |
| 1745 bool isIncompatibleInvoke = false; |
| 1746 switch (semantics.kind) { |
| 1747 case AccessKind.STATIC_METHOD: |
| 1748 case AccessKind.TOPLEVEL_METHOD: |
| 1749 MethodElementX method = semantics.element; |
| 1750 method.computeSignature(compiler); |
| 1751 if (!callStructure.signatureApplies(method)) { |
| 1752 registry.registerThrowNoSuchMethod(); |
| 1753 registry.registerDynamicInvocation(selector); |
| 1754 isIncompatibleInvoke = true; |
| 1755 } else { |
| 1756 registry.registerStaticUse(semantics.element); |
| 1757 handleForeignCall(node, semantics.element, selector); |
| 1758 } |
| 1759 break; |
| 1760 case AccessKind.STATIC_FIELD: |
| 1761 case AccessKind.FINAL_STATIC_FIELD: |
| 1762 case AccessKind.STATIC_GETTER: |
| 1763 case AccessKind.TOPLEVEL_FIELD: |
| 1764 case AccessKind.FINAL_TOPLEVEL_FIELD: |
| 1765 case AccessKind.TOPLEVEL_GETTER: |
| 1766 registry.registerStaticUse(semantics.element); |
| 1767 selector = callStructure.callSelector; |
| 1768 registry.registerDynamicInvocation(selector); |
| 1769 break; |
| 1770 case AccessKind.STATIC_SETTER: |
| 1771 case AccessKind.TOPLEVEL_SETTER: |
| 1772 case AccessKind.UNRESOLVED: |
| 1773 registry.registerThrowNoSuchMethod(); |
| 1774 element = reportAndCreateErroneousElement( |
| 1775 node.selector, name.text, |
| 1776 MessageKind.CANNOT_RESOLVE_GETTER, const {}); |
| 1777 break; |
| 1778 default: |
| 1779 internalError(node, |
| 1780 "Unexpected statically resolved access $semantics."); |
| 1781 break; |
| 1782 } |
| 1783 registry.registerSendStructure(node, |
| 1784 isIncompatibleInvoke |
| 1785 ? new IncompatibleInvokeStructure(semantics, selector) |
| 1786 : new InvokeStructure(semantics, selector)); |
| 1787 } else { |
| 1788 switch (semantics.kind) { |
| 1789 case AccessKind.STATIC_METHOD: |
| 1790 case AccessKind.TOPLEVEL_METHOD: |
| 1791 // TODO(johnniwinther): Method this should be registered as a |
| 1792 // closurization. |
| 1793 registry.registerStaticUse(semantics.element); |
| 1794 registry.registerGetOfStaticFunction(semantics.element); |
| 1795 break; |
| 1796 case AccessKind.STATIC_FIELD: |
| 1797 case AccessKind.FINAL_STATIC_FIELD: |
| 1798 case AccessKind.STATIC_GETTER: |
| 1799 case AccessKind.TOPLEVEL_FIELD: |
| 1800 case AccessKind.FINAL_TOPLEVEL_FIELD: |
| 1801 case AccessKind.TOPLEVEL_GETTER: |
| 1802 registry.registerStaticUse(semantics.element); |
| 1803 break; |
| 1804 case AccessKind.STATIC_SETTER: |
| 1805 case AccessKind.TOPLEVEL_SETTER: |
| 1806 case AccessKind.UNRESOLVED: |
| 1807 registry.registerThrowNoSuchMethod(); |
| 1808 element = reportAndCreateErroneousElement( |
| 1809 node.selector, name.text, |
| 1810 MessageKind.CANNOT_RESOLVE_GETTER, const {}); |
| 1811 break; |
| 1812 default: |
| 1813 internalError(node, |
| 1814 "Unexpected statically resolved access $semantics."); |
| 1815 break; |
| 1816 } |
| 1817 registry.registerSendStructure(node, |
| 1818 new GetStructure(semantics, selector)); |
| 1819 } |
| 1820 |
| 1821 // TODO(johnniwinther): Remove these when all information goes through |
| 1822 // the [SendStructure]. |
| 1823 registry.useElement(node, element); |
| 1824 registry.setSelector(node, selector); |
| 1825 |
| 1826 return node.isPropertyAccess |
| 1827 ? new ElementResult(element) : const NoneResult(); |
| 1828 } |
| 1829 |
| 1830 /// Handle access to resolved [element]. |
| 1831 ResolutionResult handleResolvedSend(Send node, Name name, Element element) { |
| 1832 if (element.isAmbiguous) { |
| 1833 return handleAmbiguousSend(node, name, element); |
| 1834 } |
| 1835 if (element.isErroneous) { |
| 1836 // This handles elements with parser errors. |
| 1837 // TODO(johnniwinther): Elements with parse error should not set |
| 1838 // [isErroneous] to `true`. |
| 1839 assert(invariant(node, element is! ErroneousElement, |
| 1840 message: "Unexpected erroneous element $element.")); |
| 1841 return handleErroneousAccess(node, name, element, |
| 1842 new StaticAccess.unresolved(element)); |
| 1843 } |
| 1844 if (element.isInstanceMember) { |
| 1845 if (inInstanceContext) { |
| 1846 // TODO(johnniwinther): Maybe use the found [element]. |
| 1847 return handleThisPropertyAccess(node, name); |
| 1848 } else { |
| 1849 return handleStaticInstanceSend(node, name, element); |
| 1850 } |
| 1851 } |
| 1852 if (element.isClass || element.isTypedef) { |
| 1853 return oldVisitSend(node); |
| 1854 } else if (element.isTypeVariable) { |
| 1855 return oldVisitSend(node); |
| 1856 } else if (element.isPrefix) { |
| 1857 return oldVisitSend(node); |
| 1858 } else if (element.isLocal) { |
| 1859 return handleLocalAccess(node, name, element); |
| 1860 } else if (element.isStatic || element.isTopLevel) { |
| 1861 return handleStaticOrTopLevelAccess(node, name, element); |
| 1862 } |
| 1863 return internalError(node, "Unexpected resolved send: $element"); |
| 1864 } |
| 1865 |
1539 /// Handle an unqualified [Send], that is where the `node.receiver` is null, | 1866 /// Handle an unqualified [Send], that is where the `node.receiver` is null, |
1540 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. | 1867 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. |
1541 ResolutionResult handleUnqualifiedSend(Send node) { | 1868 ResolutionResult handleUnqualifiedSend(Send node) { |
1542 Identifier selector = node.selector.asIdentifier(); | 1869 Identifier selector = node.selector.asIdentifier(); |
1543 if (selector == null) { | 1870 if (selector == null) { |
1544 // `(){}()` and `(foo)()`. | 1871 // `(){}()` and `(foo)()`. |
1545 return handleExpressionInvoke(node); | 1872 return handleExpressionInvoke(node); |
1546 } | 1873 } |
1547 String text = selector.source; | 1874 String text = selector.source; |
1548 if (text == 'assert') { | 1875 if (text == 'assert') { |
(...skipping 12 matching lines...) Expand all Loading... |
1561 Element element = lookupInScope(compiler, node, scope, text); | 1888 Element element = lookupInScope(compiler, node, scope, text); |
1562 if (element == null) { | 1889 if (element == null) { |
1563 if (inInstanceContext) { | 1890 if (inInstanceContext) { |
1564 // Implicitly `this.name`. | 1891 // Implicitly `this.name`. |
1565 return handleThisPropertyAccess(node, name); | 1892 return handleThisPropertyAccess(node, name); |
1566 } else { | 1893 } else { |
1567 // Create [ErroneousElement] for unresolved access. | 1894 // Create [ErroneousElement] for unresolved access. |
1568 ErroneousElement error = reportCannotResolve(node, text); | 1895 ErroneousElement error = reportCannotResolve(node, text); |
1569 return handleUnresolvedAccess(node, name, error); | 1896 return handleUnresolvedAccess(node, name, error); |
1570 } | 1897 } |
| 1898 } else { |
| 1899 return handleResolvedSend(node, name, element); |
1571 } | 1900 } |
1572 return oldVisitSend(node); | |
1573 } | 1901 } |
1574 | 1902 |
1575 ResolutionResult visitSend(Send node) { | 1903 ResolutionResult visitSend(Send node) { |
1576 if (node.isOperator) { | 1904 if (node.isOperator) { |
| 1905 // `a && b`, `a + b`, `-a`, or `a is T`. |
1577 return handleOperatorSend(node); | 1906 return handleOperatorSend(node); |
1578 } else if (node.receiver != null) { | 1907 } else if (node.receiver != null) { |
| 1908 // `a.b`. |
1579 return handleQualifiedSend(node); | 1909 return handleQualifiedSend(node); |
1580 } else { | 1910 } else { |
| 1911 // `a`. |
1581 return handleUnqualifiedSend(node); | 1912 return handleUnqualifiedSend(node); |
1582 } | 1913 } |
1583 return oldVisitSend(node); | 1914 } |
| 1915 |
| 1916 /// Regigster read access of [target] inside a closure. |
| 1917 void registerPotentialAccessInClosure(Send node, Element target) { |
| 1918 if (isPotentiallyMutableTarget(target)) { |
| 1919 if (enclosingElement != target.enclosingElement) { |
| 1920 for (Node scope in promotionScope) { |
| 1921 registry.setAccessedByClosureIn(scope, target, node); |
| 1922 } |
| 1923 } |
| 1924 } |
1584 } | 1925 } |
1585 | 1926 |
1586 ResolutionResult oldVisitSend(Send node) { | 1927 ResolutionResult oldVisitSend(Send node) { |
1587 bool oldSendIsMemberAccess = sendIsMemberAccess; | 1928 bool oldSendIsMemberAccess = sendIsMemberAccess; |
1588 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | 1929 sendIsMemberAccess = node.isPropertyAccess || node.isCall; |
1589 | 1930 |
1590 ResolutionResult result = resolveSend(node); | 1931 ResolutionResult result = resolveSend(node); |
1591 sendIsMemberAccess = oldSendIsMemberAccess; | 1932 sendIsMemberAccess = oldSendIsMemberAccess; |
1592 | 1933 |
1593 Element target = result.element; | 1934 Element target = result.element; |
(...skipping 27 matching lines...) Expand all Loading... |
1621 compiler.reportError(node, | 1962 compiler.reportError(node, |
1622 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | 1963 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
1623 {'typeVariableName': node.selector}); | 1964 {'typeVariableName': node.selector}); |
1624 } | 1965 } |
1625 registry.registerClassUsingVariableExpression(cls); | 1966 registry.registerClassUsingVariableExpression(cls); |
1626 registry.registerTypeVariableExpression(); | 1967 registry.registerTypeVariableExpression(); |
1627 registerTypeLiteralAccess(node, target); | 1968 registerTypeLiteralAccess(node, target); |
1628 } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) { | 1969 } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) { |
1629 registerTypeLiteralAccess(node, target); | 1970 registerTypeLiteralAccess(node, target); |
1630 } | 1971 } |
1631 if (isPotentiallyMutableTarget(target)) { | 1972 registerPotentialAccessInClosure(node, target); |
1632 if (enclosingElement != target.enclosingElement) { | |
1633 for (Node scope in promotionScope) { | |
1634 registry.setAccessedByClosureIn(scope, target, node); | |
1635 } | |
1636 } | |
1637 } | |
1638 } | 1973 } |
1639 | 1974 |
1640 bool resolvedArguments = false; | 1975 bool resolvedArguments = false; |
1641 resolveArguments(node.argumentsNode); | 1976 resolveArguments(node.argumentsNode); |
1642 | 1977 |
1643 // If the selector is null, it means that we will not be generating | 1978 // If the selector is null, it means that we will not be generating |
1644 // code for this as a send. | 1979 // code for this as a send. |
1645 Selector selector = registry.getSelector(node); | 1980 Selector selector = registry.getSelector(node); |
1646 if (selector == null) return const NoneResult(); | 1981 if (selector == null) return const NoneResult(); |
1647 | 1982 |
(...skipping 17 matching lines...) Expand all Loading... |
1665 function.computeSignature(compiler); | 2000 function.computeSignature(compiler); |
1666 } | 2001 } |
1667 if (!selector.applies(target, compiler.world)) { | 2002 if (!selector.applies(target, compiler.world)) { |
1668 registry.registerThrowNoSuchMethod(); | 2003 registry.registerThrowNoSuchMethod(); |
1669 if (node.isSuperCall) { | 2004 if (node.isSuperCall) { |
1670 internalError(node, "Unexpected super call $node"); | 2005 internalError(node, "Unexpected super call $node"); |
1671 } | 2006 } |
1672 } | 2007 } |
1673 } | 2008 } |
1674 | 2009 |
1675 if (target != null && compiler.backend.isForeign(target)) { | 2010 handleForeignCall(node, target, selector); |
1676 if (selector.name == 'JS') { | |
1677 registry.registerJsCall(node, this); | |
1678 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { | |
1679 registry.registerJsEmbeddedGlobalCall(node, this); | |
1680 } else if (selector.name == 'JS_BUILTIN') { | |
1681 registry.registerJsBuiltinCall(node, this); | |
1682 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { | |
1683 if (!node.argumentsNode.isEmpty) { | |
1684 Node argument = node.argumentsNode.nodes.head; | |
1685 if (argumentsToJsInterceptorConstant == null) { | |
1686 argumentsToJsInterceptorConstant = new Set<Node>(); | |
1687 } | |
1688 argumentsToJsInterceptorConstant.add(argument); | |
1689 } | |
1690 } | |
1691 } | |
1692 } | 2011 } |
1693 | 2012 |
1694 registry.useElement(node, target); | 2013 registry.useElement(node, target); |
1695 registerSend(selector, target); | 2014 registerSend(selector, target); |
1696 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { | 2015 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { |
1697 registry.registerGetOfStaticFunction(target.declaration); | 2016 registry.registerGetOfStaticFunction(target.declaration); |
1698 } | 2017 } |
1699 return node.isPropertyAccess | 2018 return node.isPropertyAccess |
1700 ? new ResolutionResult.forElement(target) : const NoneResult(); | 2019 ? new ResolutionResult.forElement(target) : const NoneResult(); |
1701 } | 2020 } |
1702 | 2021 |
| 2022 // TODO(johnniwinther): Move this to the backend resolution callbacks. |
| 2023 void handleForeignCall(Send node, Element target, Selector selector) { |
| 2024 if (target != null && compiler.backend.isForeign(target)) { |
| 2025 if (selector.name == 'JS') { |
| 2026 registry.registerJsCall(node, this); |
| 2027 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { |
| 2028 registry.registerJsEmbeddedGlobalCall(node, this); |
| 2029 } else if (selector.name == 'JS_BUILTIN') { |
| 2030 registry.registerJsBuiltinCall(node, this); |
| 2031 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { |
| 2032 if (!node.argumentsNode.isEmpty) { |
| 2033 Node argument = node.argumentsNode.nodes.head; |
| 2034 if (argumentsToJsInterceptorConstant == null) { |
| 2035 argumentsToJsInterceptorConstant = new Set<Node>(); |
| 2036 } |
| 2037 argumentsToJsInterceptorConstant.add(argument); |
| 2038 } |
| 2039 } |
| 2040 } |
| 2041 } |
| 2042 |
1703 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. | 2043 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. |
1704 DartType resolveTypeFromString(Node node, String typeName) { | 2044 DartType resolveTypeFromString(Node node, String typeName) { |
1705 Element element = lookupInScope(compiler, node, scope, typeName); | 2045 Element element = lookupInScope(compiler, node, scope, typeName); |
1706 if (element == null) return null; | 2046 if (element == null) return null; |
1707 if (element is! ClassElement) return null; | 2047 if (element is! ClassElement) return null; |
1708 ClassElement cls = element; | 2048 ClassElement cls = element; |
1709 cls.ensureResolved(compiler); | 2049 cls.ensureResolved(compiler); |
1710 return cls.computeType(compiler); | 2050 return cls.computeType(compiler); |
1711 } | 2051 } |
1712 | 2052 |
(...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2925 } | 3265 } |
2926 return const NoneResult(); | 3266 return const NoneResult(); |
2927 } | 3267 } |
2928 } | 3268 } |
2929 | 3269 |
2930 /// Looks up [name] in [scope] and unwraps the result. | 3270 /// Looks up [name] in [scope] and unwraps the result. |
2931 Element lookupInScope(Compiler compiler, Node node, | 3271 Element lookupInScope(Compiler compiler, Node node, |
2932 Scope scope, String name) { | 3272 Scope scope, String name) { |
2933 return Elements.unwrap(scope.lookup(name), compiler, node); | 3273 return Elements.unwrap(scope.lookup(name), compiler, node); |
2934 } | 3274 } |
OLD | NEW |