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