| 1422 | } |
| 1423 | |
| 1424 | static void process_enhanced_for(JavaLSPContext *ctx, TSNode node) { |
| 1425 | TSNode type_node = ts_node_child_by_field_name(node, "type", 4); |
| 1426 | TSNode name_node = ts_node_child_by_field_name(node, "name", 4); |
| 1427 | TSNode value_node = ts_node_child_by_field_name(node, "value", 5); |
| 1428 | char *vname = ts_node_is_null(name_node) ? NULL : java_node_text(ctx, name_node); |
| 1429 | if (!vname) |
| 1430 | return; |
| 1431 | |
| 1432 | /* `var x : xs` — explicit-var inference. tree-sitter exposes "var" as a |
| 1433 | * type_identifier whose text is exactly "var". */ |
| 1434 | bool is_var = false; |
| 1435 | if (!ts_node_is_null(type_node) && strcmp(ts_node_type(type_node), "type_identifier") == 0) { |
| 1436 | char *tt = java_node_text(ctx, type_node); |
| 1437 | if (tt && strcmp(tt, "var") == 0) |
| 1438 | is_var = true; |
| 1439 | } |
| 1440 | |
| 1441 | const CBMType *t = (is_var || ts_node_is_null(type_node)) |
| 1442 | ? cbm_type_unknown() |
| 1443 | : java_parse_type_node(ctx, type_node); |
| 1444 | |
| 1445 | /* When type is `var` or unparseable, infer from the iterable. */ |
| 1446 | if (cbm_type_is_unknown(t) && !ts_node_is_null(value_node)) { |
| 1447 | const CBMType *iter_t = java_eval_expr_type(ctx, value_node); |
| 1448 | if (iter_t && iter_t->kind == CBM_TYPE_SLICE) { |
| 1449 | t = iter_t->data.slice.elem; |
| 1450 | } else if (iter_t && iter_t->kind == CBM_TYPE_TEMPLATE && |
| 1451 | iter_t->data.template_type.arg_count > 0 && |
| 1452 | iter_t->data.template_type.template_args[0]) { |
| 1453 | t = iter_t->data.template_type.template_args[0]; |
| 1454 | } |
| 1455 | } |
| 1456 | cbm_scope_bind(ctx->current_scope, vname, t ? t : cbm_type_unknown()); |
| 1457 | } |
| 1458 | |
| 1459 | static void process_block(JavaLSPContext *ctx, TSNode node) { |
| 1460 | CBMScope *saved = ctx->current_scope; |
no test coverage detected