| 1338 | } |
| 1339 | |
| 1340 | static void cs_process_foreach(CSLSPContext *ctx, TSNode node) { |
| 1341 | /* foreach_statement: type, identifier, expression. */ |
| 1342 | TSNode tnode = ts_node_child_by_field_name(node, "type", 4); |
| 1343 | TSNode nnode = ts_node_child_by_field_name(node, "left", 4); |
| 1344 | if (ts_node_is_null(nnode)) nnode = cs_child_named_kind(node, "identifier"); |
| 1345 | TSNode iter = ts_node_child_by_field_name(node, "right", 5); |
| 1346 | if (ts_node_is_null(iter)) { |
| 1347 | /* Fallback: look for an expression-shaped child after the type. */ |
| 1348 | uint32_t nc = ts_node_child_count(node); |
| 1349 | bool past_id = false; |
| 1350 | for (uint32_t i = 0; i < nc; i++) { |
| 1351 | TSNode c = ts_node_child(node, i); |
| 1352 | if (ts_node_is_null(c) || !ts_node_is_named(c)) continue; |
| 1353 | const char *k = ts_node_type(c); |
| 1354 | if (strcmp(k, "identifier") == 0 && !past_id) { past_id = true; continue; } |
| 1355 | if (past_id) { |
| 1356 | if (strcmp(k, "block") == 0) break; |
| 1357 | iter = c; |
| 1358 | break; |
| 1359 | } |
| 1360 | } |
| 1361 | } |
| 1362 | if (ts_node_is_null(nnode)) return; |
| 1363 | char *vname = cs_node_text(ctx, nnode); |
| 1364 | if (!vname) return; |
| 1365 | |
| 1366 | const CBMType *element_t = cbm_type_unknown(); |
| 1367 | if (!ts_node_is_null(iter)) { |
| 1368 | const CBMType *iter_t = cs_eval_expr_type(ctx, iter); |
| 1369 | if (iter_t && iter_t->kind == CBM_TYPE_TEMPLATE) { |
| 1370 | const CBMType *const *args = iter_t->data.template_type.template_args; |
| 1371 | if (args && args[0]) element_t = args[0]; |
| 1372 | } |
| 1373 | } |
| 1374 | if (!ts_node_is_null(tnode)) { |
| 1375 | const CBMType *declared = cs_parse_type_node(ctx, tnode); |
| 1376 | char *tt = cs_node_text(ctx, tnode); |
| 1377 | bool is_var = (tt && (strcmp(tt, "var") == 0)); |
| 1378 | if (!is_var && declared && declared->kind != CBM_TYPE_UNKNOWN) element_t = declared; |
| 1379 | } |
| 1380 | cbm_scope_bind(ctx->current_scope, vname, element_t); |
| 1381 | } |
| 1382 | |
| 1383 | static void cs_process_using_statement(CSLSPContext *ctx, TSNode node) { |
| 1384 | /* `using (var x = expr) { ... }` — bind x. */ |
no test coverage detected