| 1553 | } |
| 1554 | |
| 1555 | static void process_catch(PHPLSPContext *ctx, TSNode node) { |
| 1556 | /* Bind $e to the caught exception type. */ |
| 1557 | TSNode type_list; |
| 1558 | memset(&type_list, 0, sizeof(type_list)); |
| 1559 | TSNode var_node; |
| 1560 | memset(&var_node, 0, sizeof(var_node)); |
| 1561 | uint32_t nc = ts_node_child_count(node); |
| 1562 | for (uint32_t i = 0; i < nc; i++) { |
| 1563 | TSNode c = ts_node_child(node, i); |
| 1564 | if (ts_node_is_null(c) || !ts_node_is_named(c)) |
| 1565 | continue; |
| 1566 | const char *k = ts_node_type(c); |
| 1567 | if (strcmp(k, "type_list") == 0) |
| 1568 | type_list = c; |
| 1569 | if (strcmp(k, "variable_name") == 0) |
| 1570 | var_node = c; |
| 1571 | } |
| 1572 | if (ts_node_is_null(var_node)) |
| 1573 | return; |
| 1574 | char *vt = php_node_text(ctx, var_node); |
| 1575 | if (!vt) |
| 1576 | return; |
| 1577 | const char *vname = (vt[0] == '$') ? vt + 1 : vt; |
| 1578 | const CBMType *exc_type = cbm_type_unknown(); |
| 1579 | if (!ts_node_is_null(type_list)) { |
| 1580 | uint32_t tnc = ts_node_child_count(type_list); |
| 1581 | for (uint32_t i = 0; i < tnc; i++) { |
| 1582 | TSNode tc = ts_node_child(type_list, i); |
| 1583 | if (ts_node_is_null(tc) || !ts_node_is_named(tc)) |
| 1584 | continue; |
| 1585 | exc_type = php_parse_type_node(ctx, tc); |
| 1586 | break; |
| 1587 | } |
| 1588 | } |
| 1589 | cbm_scope_bind(ctx->current_scope, vname, exc_type); |
| 1590 | } |
| 1591 | |
| 1592 | /* ── call resolution ────────────────────────────────────────────── */ |
| 1593 |
no test coverage detected