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 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 /// Check that access to `this` is currently allowed. | 797 /// Check that access to `this` is currently allowed. |
798 bool checkThisAccess(Send node) { | 798 bool checkThisAccess(Send node) { |
799 if (!inInstanceContext) { | 799 if (!inInstanceContext) { |
800 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE); | 800 compiler.reportError(node, MessageKind.NO_THIS_AVAILABLE); |
801 return false; | 801 return false; |
802 } | 802 } |
803 return true; | 803 return true; |
804 } | 804 } |
805 | 805 |
806 /// Compute the [AccessSemantics] corresponding to a super access of [target]. | 806 /// Compute the [AccessSemantics] corresponding to a super access of [target]. |
807 AccessSemantics computeSuperAccessSemantics(Spannable node, Element target) { | 807 AccessSemantics computeSuperAccess(Spannable node, Element target) { |
808 if (target.isErroneous) { | 808 if (target.isErroneous) { |
809 return new StaticAccess.unresolvedSuper(target); | 809 return new StaticAccess.unresolvedSuper(target); |
810 } else if (target.isGetter) { | 810 } else if (target.isGetter) { |
811 return new StaticAccess.superGetter(target); | 811 return new StaticAccess.superGetter(target); |
812 } else if (target.isSetter) { | 812 } else if (target.isSetter) { |
813 return new StaticAccess.superSetter(target); | 813 return new StaticAccess.superSetter(target); |
814 } else if (target.isField) { | 814 } else if (target.isField) { |
815 if (target.isFinal) { | 815 return new StaticAccess.superField(target); |
816 return new StaticAccess.superFinalField(target); | |
817 } else { | |
818 return new StaticAccess.superField(target); | |
819 } | |
820 } else { | 816 } else { |
821 assert(invariant(node, target.isFunction, | 817 assert(invariant(node, target.isFunction, |
822 message: "Unexpected super target '$target'.")); | 818 message: "Unexpected super target '$target'.")); |
823 return new StaticAccess.superMethod(target); | 819 return new StaticAccess.superMethod(target); |
824 } | 820 } |
825 } | 821 } |
826 | 822 |
827 /// Compute the [AccessSemantics] corresponding to a local access of [target]. | |
828 AccessSemantics computeLocalAccessSemantics(Spannable node, | |
829 LocalElement target) { | |
830 if (target.isParameter) { | |
831 if (target.isFinal || target.isConst) { | |
832 return new StaticAccess.finalParameter(target); | |
833 } else { | |
834 return new StaticAccess.parameter(target); | |
835 } | |
836 } else if (target.isVariable) { | |
837 if (target.isFinal || target.isConst) { | |
838 return new StaticAccess.finalLocalVariable(target); | |
839 } else { | |
840 return new StaticAccess.localVariable(target); | |
841 } | |
842 } else { | |
843 assert(invariant(node, target.isFunction, | |
844 message: "Unexpected local target '$target'.")); | |
845 return new StaticAccess.localFunction(target); | |
846 } | |
847 } | |
848 | |
849 /// Compute the [AccessSemantics] corresponding to a static or toplevel access | |
850 /// of [target]. | |
851 AccessSemantics computeStaticOrTopLevelAccessSemantics( | |
852 Spannable node, | |
853 Element target) { | |
854 | |
855 target = target.declaration; | |
856 if (target.isErroneous) { | |
857 // This handles elements with parser errors. | |
858 // TODO(johnniwinther): Elements with parse error should not set | |
859 // [isErroneous] to `true`. | |
860 return new StaticAccess.unresolved(target); | |
861 } | |
862 if (target.isStatic) { | |
863 if (target.isGetter) { | |
864 return new StaticAccess.staticGetter(target); | |
865 } else if (target.isSetter) { | |
866 return new StaticAccess.staticSetter(target); | |
867 } else if (target.isField) { | |
868 if (target.isFinal || target.isConst) { | |
869 return new StaticAccess.finalStaticField(target); | |
870 } else { | |
871 return new StaticAccess.staticField(target); | |
872 } | |
873 } else { | |
874 assert(invariant(node, target.isFunction, | |
875 message: "Unexpected static target '$target'.")); | |
876 return new StaticAccess.staticMethod(target); | |
877 } | |
878 } else { | |
879 assert(invariant(node, target.isTopLevel, | |
880 message: "Unexpected statically resolved target '$target'.")); | |
881 if (target.isGetter) { | |
882 return new StaticAccess.topLevelGetter(target); | |
883 } else if (target.isSetter) { | |
884 return new StaticAccess.topLevelSetter(target); | |
885 } else if (target.isField) { | |
886 if (target.isFinal) { | |
887 return new StaticAccess.finalTopLevelField(target); | |
888 } else { | |
889 return new StaticAccess.topLevelField(target); | |
890 } | |
891 } else { | |
892 assert(invariant(node, target.isFunction, | |
893 message: "Unexpected top level target '$target'.")); | |
894 return new StaticAccess.topLevelMethod(target); | |
895 } | |
896 } | |
897 } | |
898 | |
899 /// Compute the [AccessSemantics] for accessing the name of [selector] on the | 823 /// Compute the [AccessSemantics] for accessing the name of [selector] on the |
900 /// super class. | 824 /// super class. |
901 /// | 825 /// |
902 /// If no matching super member is found and error is reported and | 826 /// If no matching super member is found and error is reported and |
903 /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName] | 827 /// `noSuchMethod` on `super` is registered. Furthermore, if [alternateName] |
904 /// is provided, the [AccessSemantics] corresponding to the alternate name is | 828 /// is provided, the [AccessSemantics] corresponding to the alternate name is |
905 /// returned. For instance, the access of a super setter for an unresolved | 829 /// returned. For instance, the access of a super setter for an unresolved |
906 /// getter: | 830 /// getter: |
907 /// | 831 /// |
908 /// class Super { | 832 /// class Super { |
909 /// set name(_) {} | 833 /// set name(_) {} |
910 /// } | 834 /// } |
911 /// class Sub extends Super { | 835 /// class Sub extends Super { |
912 /// foo => super.name; // Access to the setter. | 836 /// foo => super.name; // Access to the setter. |
913 /// } | 837 /// } |
914 /// | 838 /// |
915 AccessSemantics computeSuperAccessSemanticsForSelector( | 839 AccessSemantics computeSuperSemantics(Spannable node, |
916 Spannable node, | 840 Selector selector, |
917 Selector selector, | 841 {Name alternateName}) { |
918 {Name alternateName}) { | |
919 | |
920 Name name = selector.memberName; | 842 Name name = selector.memberName; |
921 // TODO(johnniwinther): Ensure correct behavior if currentClass is a | 843 // TODO(johnniwinther): Ensure correct behavior if currentClass is a |
922 // patch. | 844 // patch. |
923 Element target = currentClass.lookupSuperByName(name); | 845 Element target = currentClass.lookupSuperByName(name); |
924 // [target] may be null which means invoking noSuchMethod on super. | 846 // [target] may be null which means invoking noSuchMethod on super. |
925 if (target == null) { | 847 if (target == null) { |
926 Element error = reportAndCreateErroneousElement( | 848 Element error = reportAndCreateErroneousElement( |
927 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER, | 849 node, name.text, MessageKind.NO_SUCH_SUPER_MEMBER, |
928 {'className': currentClass.name, 'memberName': name}); | 850 {'className': currentClass.name, 'memberName': name}); |
929 if (alternateName != null) { | 851 if (alternateName != null) { |
930 target = currentClass.lookupSuperByName(alternateName); | 852 target = currentClass.lookupSuperByName(alternateName); |
931 } | 853 } |
932 if (target == null) { | 854 if (target == null) { |
933 // If a setter wasn't resolved, use the [ErroneousElement]. | 855 // If a setter wasn't resolved, use the [ErroneousElement]. |
934 target = error; | 856 target = error; |
935 } | 857 } |
936 // We still need to register the invocation, because we might | 858 // We still need to register the invocation, because we might |
937 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. | 859 // call [:super.noSuchMethod:] which calls [JSInvocationMirror._invokeOn]. |
938 registry.registerDynamicInvocation(selector); | 860 registry.registerDynamicInvocation(selector); |
939 registry.registerSuperNoSuchMethod(); | 861 registry.registerSuperNoSuchMethod(); |
940 } | 862 } |
941 return computeSuperAccessSemantics(node, target); | 863 return computeSuperAccess(node, target); |
942 } | 864 } |
943 | 865 |
944 /// Resolve [node] as subexpression that is _not_ the prefix of a member | 866 /// Resolve [node] as subexpression that is _not_ the prefix of a member |
945 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. | 867 /// access. For instance `a` in `a + b`, as opposed to `a` in `a.b`. |
946 ResolutionResult visitExpression(Node node) { | 868 ResolutionResult visitExpression(Node node) { |
947 bool oldSendIsMemberAccess = sendIsMemberAccess; | 869 bool oldSendIsMemberAccess = sendIsMemberAccess; |
948 sendIsMemberAccess = false; | 870 sendIsMemberAccess = false; |
949 ResolutionResult result = visit(node); | 871 ResolutionResult result = visit(node); |
950 sendIsMemberAccess = oldSendIsMemberAccess; | 872 sendIsMemberAccess = oldSendIsMemberAccess; |
951 return result; | 873 return result; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) { | 931 ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) { |
1010 Node expression = node.receiver; | 932 Node expression = node.receiver; |
1011 Selector selector = operator.selector; | 933 Selector selector = operator.selector; |
1012 // TODO(johnniwinther): Remove this when all information goes through the | 934 // TODO(johnniwinther): Remove this when all information goes through the |
1013 // [SendStructure]. | 935 // [SendStructure]. |
1014 registry.setSelector(node, selector); | 936 registry.setSelector(node, selector); |
1015 | 937 |
1016 AccessSemantics semantics; | 938 AccessSemantics semantics; |
1017 if (node.isSuperCall) { | 939 if (node.isSuperCall) { |
1018 if (checkSuperAccess(node)) { | 940 if (checkSuperAccess(node)) { |
1019 semantics = computeSuperAccessSemanticsForSelector(node, selector); | 941 semantics = computeSuperSemantics(node, selector); |
1020 // TODO(johnniwinther): Add information to [AccessSemantics] about | 942 // TODO(johnniwinther): Add information to [AccessSemantics] about |
1021 // whether it is erroneous. | 943 // whether it is erroneous. |
1022 if (semantics.kind == AccessKind.SUPER_METHOD) { | 944 if (semantics.kind == AccessKind.SUPER_METHOD) { |
1023 registry.registerStaticUse(semantics.element.declaration); | 945 registry.registerStaticUse(semantics.element.declaration); |
1024 } | 946 } |
1025 // TODO(johnniwinther): Remove this when all information goes through | 947 // TODO(johnniwinther): Remove this when all information goes through |
1026 // the [SendStructure]. | 948 // the [SendStructure]. |
1027 registry.useElement(node, semantics.element); | 949 registry.useElement(node, semantics.element); |
1028 } | 950 } |
1029 } else { | 951 } else { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 selector = new Selector.index(); | 1030 selector = new Selector.index(); |
1109 } else { | 1031 } else { |
1110 selector = new Selector.binaryOperator(operator.selectorName); | 1032 selector = new Selector.binaryOperator(operator.selectorName); |
1111 } | 1033 } |
1112 // TODO(johnniwinther): Remove this when all information goes through the | 1034 // TODO(johnniwinther): Remove this when all information goes through the |
1113 // [SendStructure]. | 1035 // [SendStructure]. |
1114 registry.setSelector(node, selector); | 1036 registry.setSelector(node, selector); |
1115 | 1037 |
1116 if (node.isSuperCall) { | 1038 if (node.isSuperCall) { |
1117 if (checkSuperAccess(node)) { | 1039 if (checkSuperAccess(node)) { |
1118 semantics = computeSuperAccessSemanticsForSelector(node, selector); | 1040 semantics = computeSuperSemantics(node, selector); |
1119 // TODO(johnniwinther): Add information to [AccessSemantics] about | 1041 // TODO(johnniwinther): Add information to [AccessSemantics] about |
1120 // whether it is erroneous. | 1042 // whether it is erroneous. |
1121 if (semantics.kind == AccessKind.SUPER_METHOD) { | 1043 if (semantics.kind == AccessKind.SUPER_METHOD) { |
1122 registry.registerStaticUse(semantics.element.declaration); | 1044 registry.registerStaticUse(semantics.element.declaration); |
1123 } | 1045 } |
1124 // TODO(johnniwinther): Remove this when all information goes through | 1046 // TODO(johnniwinther): Remove this when all information goes through |
1125 // the [SendStructure]. | 1047 // the [SendStructure]. |
1126 registry.useElement(node, semantics.element); | 1048 registry.useElement(node, semantics.element); |
1127 } | 1049 } |
1128 } else { | 1050 } else { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 Element target; | 1194 Element target; |
1273 Selector selector; | 1195 Selector selector; |
1274 CallStructure callStructure = CallStructure.NO_ARGS; | 1196 CallStructure callStructure = CallStructure.NO_ARGS; |
1275 if (node.isCall) { | 1197 if (node.isCall) { |
1276 callStructure = resolveArguments(node.argumentsNode); | 1198 callStructure = resolveArguments(node.argumentsNode); |
1277 selector = new Selector(SelectorKind.CALL, name, callStructure); | 1199 selector = new Selector(SelectorKind.CALL, name, callStructure); |
1278 } else { | 1200 } else { |
1279 selector = new Selector(SelectorKind.GETTER, name, callStructure); | 1201 selector = new Selector(SelectorKind.GETTER, name, callStructure); |
1280 } | 1202 } |
1281 if (checkSuperAccess(node)) { | 1203 if (checkSuperAccess(node)) { |
1282 AccessSemantics semantics = computeSuperAccessSemanticsForSelector( | 1204 AccessSemantics semantics = computeSuperSemantics( |
1283 node, selector, alternateName: name.setter); | 1205 node, selector, alternateName: name.setter); |
1284 if (node.isCall) { | 1206 if (node.isCall) { |
1285 bool isIncompatibleInvoke = false; | 1207 bool isIncompatibleInvoke = false; |
1286 switch (semantics.kind) { | 1208 switch (semantics.kind) { |
1287 case AccessKind.SUPER_METHOD: | 1209 case AccessKind.SUPER_METHOD: |
1288 MethodElementX superMethod = semantics.element; | 1210 MethodElementX superMethod = semantics.element; |
1289 superMethod.computeSignature(compiler); | 1211 superMethod.computeSignature(compiler); |
1290 if (!callStructure.signatureApplies(superMethod)) { | 1212 if (!callStructure.signatureApplies(superMethod)) { |
1291 registry.registerThrowNoSuchMethod(); | 1213 registry.registerThrowNoSuchMethod(); |
1292 registry.registerDynamicInvocation(selector); | 1214 registry.registerDynamicInvocation(selector); |
1293 registry.registerSuperNoSuchMethod(); | 1215 registry.registerSuperNoSuchMethod(); |
1294 isIncompatibleInvoke = true; | 1216 isIncompatibleInvoke = true; |
1295 } else { | 1217 } else { |
1296 registry.registerStaticInvocation(semantics.element); | 1218 registry.registerStaticInvocation(semantics.element); |
1297 } | 1219 } |
1298 break; | 1220 break; |
1299 case AccessKind.SUPER_FIELD: | 1221 case AccessKind.SUPER_FIELD: |
1300 case AccessKind.SUPER_FINAL_FIELD: | |
1301 case AccessKind.SUPER_GETTER: | 1222 case AccessKind.SUPER_GETTER: |
1302 registry.registerStaticUse(semantics.element); | 1223 registry.registerStaticUse(semantics.element); |
1303 selector = callStructure.callSelector; | 1224 selector = callStructure.callSelector; |
1304 registry.registerDynamicInvocation(selector); | 1225 registry.registerDynamicInvocation(selector); |
1305 break; | 1226 break; |
1306 case AccessKind.SUPER_SETTER: | 1227 case AccessKind.SUPER_SETTER: |
1307 case AccessKind.UNRESOLVED_SUPER: | 1228 case AccessKind.UNRESOLVED_SUPER: |
1308 // NoSuchMethod registered in [computeSuperSemantics]. | 1229 // NoSuchMethod registered in [computeSuperSemantics]. |
1309 break; | 1230 break; |
1310 default: | 1231 default: |
1311 internalError(node, "Unexpected super property access $semantics."); | 1232 internalError(node, "Unexpected super property access $semantics."); |
1312 break; | 1233 break; |
1313 } | 1234 } |
1314 registry.registerSendStructure(node, | 1235 registry.registerSendStructure(node, |
1315 isIncompatibleInvoke | 1236 isIncompatibleInvoke |
1316 ? new IncompatibleInvokeStructure(semantics, selector) | 1237 ? new IncompatibleInvokeStructure(semantics, selector) |
1317 : new InvokeStructure(semantics, selector)); | 1238 : new InvokeStructure(semantics, selector)); |
1318 } else { | 1239 } else { |
1319 switch (semantics.kind) { | 1240 switch (semantics.kind) { |
1320 case AccessKind.SUPER_METHOD: | 1241 case AccessKind.SUPER_METHOD: |
1321 // TODO(johnniwinther): Method this should be registered as a | 1242 // TODO(johnniwinther): Method this should be registered as a |
1322 // closurization. | 1243 // closurization. |
1323 registry.registerStaticUse(semantics.element); | 1244 registry.registerStaticUse(semantics.element); |
1324 break; | 1245 break; |
1325 case AccessKind.SUPER_FIELD: | 1246 case AccessKind.SUPER_FIELD: |
1326 case AccessKind.SUPER_FINAL_FIELD: | |
1327 case AccessKind.SUPER_GETTER: | 1247 case AccessKind.SUPER_GETTER: |
1328 registry.registerStaticUse(semantics.element); | 1248 registry.registerStaticUse(semantics.element); |
1329 break; | 1249 break; |
1330 case AccessKind.SUPER_SETTER: | 1250 case AccessKind.SUPER_SETTER: |
1331 case AccessKind.UNRESOLVED_SUPER: | 1251 case AccessKind.UNRESOLVED_SUPER: |
1332 // NoSuchMethod registered in [computeSuperSemantics]. | 1252 // NoSuchMethod registered in [computeSuperSemantics]. |
1333 break; | 1253 break; |
1334 default: | 1254 default: |
1335 internalError(node, "Unexpected super property access $semantics."); | 1255 internalError(node, "Unexpected super property access $semantics."); |
1336 break; | 1256 break; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1426 // TODO(johnniwinther): Handle remaining qualified sends. | 1346 // TODO(johnniwinther): Handle remaining qualified sends. |
1427 return oldVisitSend(node); | 1347 return oldVisitSend(node); |
1428 } | 1348 } |
1429 | 1349 |
1430 /// Handle access unresolved access to [name] in a non-instance context. | 1350 /// Handle access unresolved access to [name] in a non-instance context. |
1431 ResolutionResult handleUnresolvedAccess( | 1351 ResolutionResult handleUnresolvedAccess( |
1432 Send node, Name name, Element element) { | 1352 Send node, Name name, Element element) { |
1433 // TODO(johnniwinther): Support unresolved top level access as an | 1353 // TODO(johnniwinther): Support unresolved top level access as an |
1434 // [AccessSemantics]. | 1354 // [AccessSemantics]. |
1435 AccessSemantics accessSemantics = new StaticAccess.unresolved(element); | 1355 AccessSemantics accessSemantics = new StaticAccess.unresolved(element); |
1436 return handleErroneousAccess(node, name, element, accessSemantics); | |
1437 } | |
1438 | |
1439 /// Handle erroneous access of [element] of the given [accessSemantics]. | |
1440 ResolutionResult handleErroneousAccess( | |
1441 Send node, Name name, Element element, AccessSemantics accessSemantics) { | |
1442 SendStructure sendStructure; | 1356 SendStructure sendStructure; |
1443 Selector selector; | 1357 Selector selector; |
1444 if (node.isCall) { | 1358 if (node.isCall) { |
1445 CallStructure callStructure = resolveArguments(node.argumentsNode); | 1359 CallStructure callStructure = resolveArguments(node.argumentsNode); |
1446 selector = new Selector(SelectorKind.CALL, name, callStructure); | 1360 selector = new Selector(SelectorKind.CALL, name, callStructure); |
1447 registry.registerDynamicInvocation(selector); | 1361 registry.registerDynamicInvocation(selector); |
1448 sendStructure = new InvokeStructure(accessSemantics, selector); | 1362 sendStructure = new InvokeStructure(accessSemantics, selector); |
1449 } else { | 1363 } else { |
1450 assert(invariant(node, node.isPropertyAccess)); | 1364 assert(invariant(node, node.isPropertyAccess)); |
1451 selector = new Selector( | 1365 selector = new Selector( |
1452 SelectorKind.GETTER, name, CallStructure.NO_ARGS); | 1366 SelectorKind.GETTER, name, CallStructure.NO_ARGS); |
1453 registry.registerDynamicGetter(selector); | 1367 registry.registerDynamicGetter(selector); |
1454 sendStructure = new GetStructure(accessSemantics, selector); | 1368 sendStructure = new GetStructure(accessSemantics, selector); |
1455 } | 1369 } |
1456 // TODO(johnniwinther): Remove this when all information goes through | 1370 // TODO(johnniwinther): Remove this when all information goes through |
1457 // the [SendStructure]. | 1371 // the [SendStructure]. |
1458 registry.setSelector(node, selector); | 1372 registry.setSelector(node, selector); |
1459 registry.useElement(node, element); | 1373 registry.useElement(node, element); |
1460 registry.registerSendStructure(node, sendStructure); | 1374 registry.registerSendStructure(node, sendStructure); |
1461 return null; | 1375 return null; |
1462 } | 1376 } |
1463 | 1377 |
1464 /// Handle access to an ambiguous element, that is, a name imported twice. | |
1465 ResolutionResult handleAmbiguousSend( | |
1466 Send node, | |
1467 Name name, | |
1468 AmbiguousElement element) { | |
1469 | |
1470 compiler.reportError( | |
1471 node, element.messageKind, element.messageArguments); | |
1472 element.diagnose(enclosingElement, compiler); | |
1473 | |
1474 ErroneousElement error = new ErroneousElementX( | |
1475 element.messageKind, | |
1476 element.messageArguments, | |
1477 name.text, | |
1478 enclosingElement); | |
1479 | |
1480 // TODO(johnniwinther): Support ambiguous access as an [AccessSemantics]. | |
1481 AccessSemantics accessSemantics = new StaticAccess.unresolved(error); | |
1482 return handleErroneousAccess(node, name, error, accessSemantics); | |
1483 } | |
1484 | |
1485 /// Handle access of an instance [member] from a non-instance context. | |
1486 ResolutionResult handleStaticInstanceSend( | |
1487 Send node, Name name, MemberElement member) { | |
1488 compiler.reportError( | |
1489 node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': member.name}); | |
1490 ErroneousElement error = new ErroneousElementX( | |
1491 MessageKind.NO_INSTANCE_AVAILABLE, | |
1492 {'name': name}, | |
1493 name.text, | |
1494 enclosingElement); | |
1495 | |
1496 // TODO(johnniwinther): Support static instance access as an | |
1497 // [AccessSemantics]. | |
1498 AccessSemantics accessSemantics = new StaticAccess.unresolved(error); | |
1499 return handleErroneousAccess(node, name, error, accessSemantics); | |
1500 } | |
1501 | |
1502 /// Handle access of a parameter, local variable or local function. | |
1503 ResolutionResult handleLocalAccess(Send node, Name name, Element element) { | |
1504 AccessSemantics semantics = computeLocalAccessSemantics(node, element); | |
1505 Selector selector; | |
1506 CallStructure callStructure = CallStructure.NO_ARGS; | |
1507 if (node.isCall) { | |
1508 callStructure = resolveArguments(node.argumentsNode); | |
1509 selector = new Selector(SelectorKind.CALL, name, callStructure); | |
1510 } else { | |
1511 selector = new Selector(SelectorKind.GETTER, name, callStructure); | |
1512 } | |
1513 if (node.isCall) { | |
1514 bool isIncompatibleInvoke = false; | |
1515 switch (semantics.kind) { | |
1516 case AccessKind.LOCAL_FUNCTION: | |
1517 LocalFunctionElementX function = semantics.element; | |
1518 function.computeSignature(compiler); | |
1519 if (!callStructure.signatureApplies(function)) { | |
1520 registry.registerThrowNoSuchMethod(); | |
1521 registry.registerDynamicInvocation(selector); | |
1522 isIncompatibleInvoke = true; | |
1523 } | |
1524 break; | |
1525 case AccessKind.PARAMETER: | |
1526 case AccessKind.FINAL_PARAMETER: | |
1527 case AccessKind.LOCAL_VARIABLE: | |
1528 case AccessKind.FINAL_LOCAL_VARIABLE: | |
1529 selector = callStructure.callSelector; | |
1530 registry.registerDynamicInvocation(selector); | |
1531 break; | |
1532 default: | |
1533 internalError(node, | |
1534 "Unexpected local access $semantics."); | |
1535 break; | |
1536 } | |
1537 registry.registerSendStructure(node, | |
1538 isIncompatibleInvoke | |
1539 ? new IncompatibleInvokeStructure(semantics, selector) | |
1540 : new InvokeStructure(semantics, selector)); | |
1541 } else { | |
1542 registry.registerSendStructure(node, | |
1543 new GetStructure(semantics, selector)); | |
1544 } | |
1545 | |
1546 // TODO(johnniwinther): Remove these when all information goes through | |
1547 // the [SendStructure]. | |
1548 registry.useElement(node, element); | |
1549 registry.setSelector(node, selector); | |
1550 | |
1551 registerPotentialAccessInClosure(node, element); | |
1552 | |
1553 return node.isPropertyAccess ? new ElementResult(element) : null; | |
1554 } | |
1555 | |
1556 /// Handle access of a static or top level [element]. | |
1557 ResolutionResult handleStaticOrTopLevelAccess( | |
1558 Send node, Name name, Element element) { | |
1559 | |
1560 if (element.isAbstractField) { | |
1561 AbstractFieldElement abstractField = element; | |
1562 if (abstractField.getter != null) { | |
1563 element = abstractField.getter; | |
1564 } else { | |
1565 element = abstractField.setter; | |
1566 } | |
1567 } | |
1568 | |
1569 Selector selector; | |
1570 CallStructure callStructure = CallStructure.NO_ARGS; | |
1571 if (node.isCall) { | |
1572 callStructure = resolveArguments(node.argumentsNode); | |
1573 selector = new Selector(SelectorKind.CALL, name, callStructure); | |
1574 } else { | |
1575 selector = new Selector(SelectorKind.GETTER, name, callStructure); | |
1576 } | |
1577 AccessSemantics semantics = | |
1578 computeStaticOrTopLevelAccessSemantics(node, element); | |
1579 if (node.isCall) { | |
1580 bool isIncompatibleInvoke = false; | |
1581 switch (semantics.kind) { | |
1582 case AccessKind.STATIC_METHOD: | |
1583 case AccessKind.TOPLEVEL_METHOD: | |
1584 MethodElementX method = semantics.element; | |
1585 method.computeSignature(compiler); | |
1586 if (!callStructure.signatureApplies(method)) { | |
1587 registry.registerThrowNoSuchMethod(); | |
1588 registry.registerDynamicInvocation(selector); | |
1589 isIncompatibleInvoke = true; | |
1590 } else { | |
1591 registry.registerStaticUse(semantics.element); | |
1592 handleForeignCall(node, semantics.element, selector); | |
1593 } | |
1594 break; | |
1595 case AccessKind.STATIC_FIELD: | |
1596 case AccessKind.FINAL_STATIC_FIELD: | |
1597 case AccessKind.STATIC_GETTER: | |
1598 case AccessKind.TOPLEVEL_FIELD: | |
1599 case AccessKind.FINAL_TOPLEVEL_FIELD: | |
1600 case AccessKind.TOPLEVEL_GETTER: | |
1601 registry.registerStaticUse(semantics.element); | |
1602 selector = callStructure.callSelector; | |
1603 registry.registerDynamicInvocation(selector); | |
1604 break; | |
1605 case AccessKind.STATIC_SETTER: | |
1606 case AccessKind.TOPLEVEL_SETTER: | |
1607 case AccessKind.UNRESOLVED: | |
1608 registry.registerThrowNoSuchMethod(); | |
1609 element = reportAndCreateErroneousElement( | |
1610 node.selector, name.text, | |
1611 MessageKind.CANNOT_RESOLVE_GETTER, const {}); | |
1612 break; | |
1613 default: | |
1614 internalError(node, | |
1615 "Unexpected statically resolved access $semantics."); | |
1616 break; | |
1617 } | |
1618 registry.registerSendStructure(node, | |
1619 isIncompatibleInvoke | |
1620 ? new IncompatibleInvokeStructure(semantics, selector) | |
1621 : new InvokeStructure(semantics, selector)); | |
1622 } else { | |
1623 switch (semantics.kind) { | |
1624 case AccessKind.STATIC_METHOD: | |
1625 case AccessKind.TOPLEVEL_METHOD: | |
1626 // TODO(johnniwinther): Method this should be registered as a | |
1627 // closurization. | |
1628 registry.registerStaticUse(semantics.element); | |
1629 registry.registerGetOfStaticFunction(semantics.element); | |
1630 break; | |
1631 case AccessKind.STATIC_FIELD: | |
1632 case AccessKind.FINAL_STATIC_FIELD: | |
1633 case AccessKind.STATIC_GETTER: | |
1634 case AccessKind.TOPLEVEL_FIELD: | |
1635 case AccessKind.FINAL_TOPLEVEL_FIELD: | |
1636 case AccessKind.TOPLEVEL_GETTER: | |
1637 registry.registerStaticUse(semantics.element); | |
1638 break; | |
1639 case AccessKind.STATIC_SETTER: | |
1640 case AccessKind.TOPLEVEL_SETTER: | |
1641 case AccessKind.UNRESOLVED: | |
1642 registry.registerThrowNoSuchMethod(); | |
1643 element = reportAndCreateErroneousElement( | |
1644 node.selector, name.text, | |
1645 MessageKind.CANNOT_RESOLVE_GETTER, const {}); | |
1646 break; | |
1647 default: | |
1648 internalError(node, | |
1649 "Unexpected statically resolved access $semantics."); | |
1650 break; | |
1651 } | |
1652 registry.registerSendStructure(node, | |
1653 new GetStructure(semantics, selector)); | |
1654 } | |
1655 | |
1656 // TODO(johnniwinther): Remove these when all information goes through | |
1657 // the [SendStructure]. | |
1658 registry.useElement(node, element); | |
1659 registry.setSelector(node, selector); | |
1660 | |
1661 return node.isPropertyAccess ? new ElementResult(element) : null; | |
1662 } | |
1663 | |
1664 /// Handle access to resolved [element]. | |
1665 ResolutionResult handleResolvedSend(Send node, Name name, Element element) { | |
1666 if (element.isAmbiguous) { | |
1667 return handleAmbiguousSend(node, name, element); | |
1668 } | |
1669 if (element.isErroneous) { | |
1670 // This handles elements with parser errors. | |
1671 // TODO(johnniwinther): Elements with parse error should not set | |
1672 // [isErroneous] to `true`. | |
1673 assert(invariant(node, element is! ErroneousElement, | |
1674 message: "Unexpected erroneous element $element.")); | |
1675 return handleErroneousAccess(node, name, element, | |
1676 new StaticAccess.unresolved(element)); | |
1677 } | |
1678 if (element.isInstanceMember) { | |
1679 if (inInstanceContext) { | |
1680 // TODO(johnniwinther): Maybe use the found [element]. | |
1681 return handleThisPropertyAccess(node, name); | |
1682 } else { | |
1683 return handleStaticInstanceSend(node, name, element); | |
1684 } | |
1685 } | |
1686 if (element.isClass || element.isTypedef) { | |
1687 return oldVisitSend(node); | |
1688 } else if (element.isTypeVariable) { | |
1689 return oldVisitSend(node); | |
1690 } else if (element.isPrefix) { | |
1691 return oldVisitSend(node); | |
1692 } else if (element.isLocal) { | |
1693 return handleLocalAccess(node, name, element); | |
1694 } else if (element.isStatic || element.isTopLevel) { | |
1695 return handleStaticOrTopLevelAccess(node, name, element); | |
1696 } | |
1697 return internalError(node, "Unexpected resolved send: $element"); | |
1698 } | |
1699 | |
1700 /// Handle an unqualified [Send], that is where the `node.receiver` is null, | 1378 /// Handle an unqualified [Send], that is where the `node.receiver` is null, |
1701 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. | 1379 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. |
1702 ResolutionResult handleUnqualifiedSend(Send node) { | 1380 ResolutionResult handleUnqualifiedSend(Send node) { |
1703 Identifier selector = node.selector.asIdentifier(); | 1381 Identifier selector = node.selector.asIdentifier(); |
1704 if (selector == null) { | 1382 if (selector == null) { |
1705 // `(){}()` and `(foo)()`. | 1383 // `(){}()` and `(foo)()`. |
1706 return handleExpressionInvoke(node); | 1384 return handleExpressionInvoke(node); |
1707 } | 1385 } |
1708 String text = selector.source; | 1386 String text = selector.source; |
1709 if (text == 'assert') { | 1387 if (text == 'assert') { |
(...skipping 12 matching lines...) Expand all Loading... |
1722 Element element = lookupInScope(compiler, node, scope, text); | 1400 Element element = lookupInScope(compiler, node, scope, text); |
1723 if (element == null) { | 1401 if (element == null) { |
1724 if (inInstanceContext) { | 1402 if (inInstanceContext) { |
1725 // Implicitly `this.name`. | 1403 // Implicitly `this.name`. |
1726 return handleThisPropertyAccess(node, name); | 1404 return handleThisPropertyAccess(node, name); |
1727 } else { | 1405 } else { |
1728 // Create [ErroneousElement] for unresolved access. | 1406 // Create [ErroneousElement] for unresolved access. |
1729 ErroneousElement error = reportCannotResolve(node, text); | 1407 ErroneousElement error = reportCannotResolve(node, text); |
1730 return handleUnresolvedAccess(node, name, error); | 1408 return handleUnresolvedAccess(node, name, error); |
1731 } | 1409 } |
1732 } else { | |
1733 return handleResolvedSend(node, name, element); | |
1734 } | 1410 } |
| 1411 return oldVisitSend(node); |
1735 } | 1412 } |
1736 | 1413 |
1737 ResolutionResult visitSend(Send node) { | 1414 ResolutionResult visitSend(Send node) { |
1738 if (node.isOperator) { | 1415 if (node.isOperator) { |
1739 // `a && b`, `a + b`, `-a`, or `a is T`. | |
1740 return handleOperatorSend(node); | 1416 return handleOperatorSend(node); |
1741 } else if (node.receiver != null) { | 1417 } else if (node.receiver != null) { |
1742 // `a.b`. | |
1743 return handleQualifiedSend(node); | 1418 return handleQualifiedSend(node); |
1744 } else { | 1419 } else { |
1745 // `a`. | |
1746 return handleUnqualifiedSend(node); | 1420 return handleUnqualifiedSend(node); |
1747 } | 1421 } |
1748 } | 1422 return oldVisitSend(node); |
1749 | |
1750 /// Regigster read access of [target] inside a closure. | |
1751 void registerPotentialAccessInClosure(Send node, Element target) { | |
1752 if (isPotentiallyMutableTarget(target)) { | |
1753 if (enclosingElement != target.enclosingElement) { | |
1754 for (Node scope in promotionScope) { | |
1755 registry.setAccessedByClosureIn(scope, target, node); | |
1756 } | |
1757 } | |
1758 } | |
1759 } | 1423 } |
1760 | 1424 |
1761 ResolutionResult oldVisitSend(Send node) { | 1425 ResolutionResult oldVisitSend(Send node) { |
1762 bool oldSendIsMemberAccess = sendIsMemberAccess; | 1426 bool oldSendIsMemberAccess = sendIsMemberAccess; |
1763 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | 1427 sendIsMemberAccess = node.isPropertyAccess || node.isCall; |
1764 | 1428 |
1765 ResolutionResult result = resolveSend(node); | 1429 ResolutionResult result = resolveSend(node); |
1766 sendIsMemberAccess = oldSendIsMemberAccess; | 1430 sendIsMemberAccess = oldSendIsMemberAccess; |
1767 | 1431 |
1768 Element target = result != null ? result.element : null; | 1432 Element target = result != null ? result.element : null; |
(...skipping 27 matching lines...) Expand all Loading... |
1796 compiler.reportError(node, | 1460 compiler.reportError(node, |
1797 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | 1461 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
1798 {'typeVariableName': node.selector}); | 1462 {'typeVariableName': node.selector}); |
1799 } | 1463 } |
1800 registry.registerClassUsingVariableExpression(cls); | 1464 registry.registerClassUsingVariableExpression(cls); |
1801 registry.registerTypeVariableExpression(); | 1465 registry.registerTypeVariableExpression(); |
1802 registerTypeLiteralAccess(node, target); | 1466 registerTypeLiteralAccess(node, target); |
1803 } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) { | 1467 } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) { |
1804 registerTypeLiteralAccess(node, target); | 1468 registerTypeLiteralAccess(node, target); |
1805 } | 1469 } |
1806 registerPotentialAccessInClosure(node, target); | 1470 if (isPotentiallyMutableTarget(target)) { |
| 1471 if (enclosingElement != target.enclosingElement) { |
| 1472 for (Node scope in promotionScope) { |
| 1473 registry.setAccessedByClosureIn(scope, target, node); |
| 1474 } |
| 1475 } |
| 1476 } |
1807 } | 1477 } |
1808 | 1478 |
1809 bool resolvedArguments = false; | 1479 bool resolvedArguments = false; |
1810 resolveArguments(node.argumentsNode); | 1480 resolveArguments(node.argumentsNode); |
1811 | 1481 |
1812 // If the selector is null, it means that we will not be generating | 1482 // If the selector is null, it means that we will not be generating |
1813 // code for this as a send. | 1483 // code for this as a send. |
1814 Selector selector = registry.getSelector(node); | 1484 Selector selector = registry.getSelector(node); |
1815 if (selector == null) return null; | 1485 if (selector == null) return null; |
1816 | 1486 |
(...skipping 17 matching lines...) Expand all Loading... |
1834 function.computeSignature(compiler); | 1504 function.computeSignature(compiler); |
1835 } | 1505 } |
1836 if (!selector.applies(target, compiler.world)) { | 1506 if (!selector.applies(target, compiler.world)) { |
1837 registry.registerThrowNoSuchMethod(); | 1507 registry.registerThrowNoSuchMethod(); |
1838 if (node.isSuperCall) { | 1508 if (node.isSuperCall) { |
1839 internalError(node, "Unexpected super call $node"); | 1509 internalError(node, "Unexpected super call $node"); |
1840 } | 1510 } |
1841 } | 1511 } |
1842 } | 1512 } |
1843 | 1513 |
1844 handleForeignCall(node, target, selector); | 1514 if (target != null && compiler.backend.isForeign(target)) { |
| 1515 if (selector.name == 'JS') { |
| 1516 registry.registerJsCall(node, this); |
| 1517 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { |
| 1518 registry.registerJsEmbeddedGlobalCall(node, this); |
| 1519 } else if (selector.name == 'JS_BUILTIN') { |
| 1520 registry.registerJsBuiltinCall(node, this); |
| 1521 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { |
| 1522 if (!node.argumentsNode.isEmpty) { |
| 1523 Node argument = node.argumentsNode.nodes.head; |
| 1524 if (argumentsToJsInterceptorConstant == null) { |
| 1525 argumentsToJsInterceptorConstant = new Set<Node>(); |
| 1526 } |
| 1527 argumentsToJsInterceptorConstant.add(argument); |
| 1528 } |
| 1529 } |
| 1530 } |
1845 } | 1531 } |
1846 | 1532 |
1847 registry.useElement(node, target); | 1533 registry.useElement(node, target); |
1848 registerSend(selector, target); | 1534 registerSend(selector, target); |
1849 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { | 1535 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { |
1850 registry.registerGetOfStaticFunction(target.declaration); | 1536 registry.registerGetOfStaticFunction(target.declaration); |
1851 } | 1537 } |
1852 return node.isPropertyAccess ? new ElementResult(target) : null; | 1538 return node.isPropertyAccess ? new ElementResult(target) : null; |
1853 } | 1539 } |
1854 | 1540 |
1855 // TODO(johnniwinther): Move this to the backend resolution callbacks. | |
1856 void handleForeignCall(Send node, Element target, Selector selector) { | |
1857 if (target != null && compiler.backend.isForeign(target)) { | |
1858 if (selector.name == 'JS') { | |
1859 registry.registerJsCall(node, this); | |
1860 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { | |
1861 registry.registerJsEmbeddedGlobalCall(node, this); | |
1862 } else if (selector.name == 'JS_BUILTIN') { | |
1863 registry.registerJsBuiltinCall(node, this); | |
1864 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { | |
1865 if (!node.argumentsNode.isEmpty) { | |
1866 Node argument = node.argumentsNode.nodes.head; | |
1867 if (argumentsToJsInterceptorConstant == null) { | |
1868 argumentsToJsInterceptorConstant = new Set<Node>(); | |
1869 } | |
1870 argumentsToJsInterceptorConstant.add(argument); | |
1871 } | |
1872 } | |
1873 } | |
1874 } | |
1875 | |
1876 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. | 1541 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. |
1877 DartType resolveTypeFromString(Node node, String typeName) { | 1542 DartType resolveTypeFromString(Node node, String typeName) { |
1878 Element element = lookupInScope(compiler, node, scope, typeName); | 1543 Element element = lookupInScope(compiler, node, scope, typeName); |
1879 if (element == null) return null; | 1544 if (element == null) return null; |
1880 if (element is! ClassElement) return null; | 1545 if (element is! ClassElement) return null; |
1881 ClassElement cls = element; | 1546 ClassElement cls = element; |
1882 cls.ensureResolved(compiler); | 1547 cls.ensureResolved(compiler); |
1883 return cls.computeType(compiler); | 1548 return cls.computeType(compiler); |
1884 } | 1549 } |
1885 | 1550 |
(...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2977 visitTypedef(Typedef node) { | 2642 visitTypedef(Typedef node) { |
2978 internalError(node, 'typedef'); | 2643 internalError(node, 'typedef'); |
2979 } | 2644 } |
2980 } | 2645 } |
2981 | 2646 |
2982 /// Looks up [name] in [scope] and unwraps the result. | 2647 /// Looks up [name] in [scope] and unwraps the result. |
2983 Element lookupInScope(Compiler compiler, Node node, | 2648 Element lookupInScope(Compiler compiler, Node node, |
2984 Scope scope, String name) { | 2649 Scope scope, String name) { |
2985 return Elements.unwrap(scope.lookup(name), compiler, node); | 2650 return Elements.unwrap(scope.lookup(name), compiler, node); |
2986 } | 2651 } |
OLD | NEW |