| 1411 | } |
| 1412 | |
| 1413 | static void process_catch(PHPLSPContext *ctx, TSNode node) { |
| 1414 | /* Bind $e to the caught exception type. */ |
| 1415 | TSNode type_list; |
| 1416 | memset(&type_list, 0, sizeof(type_list)); |
| 1417 | TSNode var_node; |
| 1418 | memset(&var_node, 0, sizeof(var_node)); |
| 1419 | uint32_t nc = ts_node_child_count(node); |
| 1420 | for (uint32_t i = 0; i < nc; i++) { |
| 1421 | TSNode c = ts_node_child(node, i); |
| 1422 | if (ts_node_is_null(c) || !ts_node_is_named(c)) |
| 1423 | continue; |
| 1424 | const char *k = ts_node_type(c); |
| 1425 | if (strcmp(k, "type_list") == 0) |
| 1426 | type_list = c; |
| 1427 | if (strcmp(k, "variable_name") == 0) |
| 1428 | var_node = c; |
| 1429 | } |
| 1430 | if (ts_node_is_null(var_node)) |
| 1431 | return; |
| 1432 | char *vt = php_node_text(ctx, var_node); |
| 1433 | if (!vt) |
| 1434 | return; |
| 1435 | const char *vname = (vt[0] == '$') ? vt + 1 : vt; |
| 1436 | const CBMType *exc_type = cbm_type_unknown(); |
| 1437 | if (!ts_node_is_null(type_list)) { |
| 1438 | uint32_t tnc = ts_node_child_count(type_list); |
| 1439 | for (uint32_t i = 0; i < tnc; i++) { |
| 1440 | TSNode tc = ts_node_child(type_list, i); |
| 1441 | if (ts_node_is_null(tc) || !ts_node_is_named(tc)) |
| 1442 | continue; |
| 1443 | exc_type = php_parse_type_node(ctx, tc); |
| 1444 | break; |
| 1445 | } |
| 1446 | } |
| 1447 | cbm_scope_bind(ctx->current_scope, vname, exc_type); |
| 1448 | } |
| 1449 | |
| 1450 | /* ── call resolution ────────────────────────────────────────────── */ |
| 1451 |
no test coverage detected