| 1638 | } |
| 1639 | |
| 1640 | static void cs_process_local_decl(CSLSPContext *ctx, TSNode node) { |
| 1641 | /* local_declaration_statement -> variable_declaration */ |
| 1642 | TSNode vd = cs_child_named_kind(node, "variable_declaration"); |
| 1643 | if (ts_node_is_null(vd)) |
| 1644 | return; |
| 1645 | TSNode tnode = ts_node_child_by_field_name(vd, "type", 4); |
| 1646 | if (ts_node_is_null(tnode)) |
| 1647 | tnode = cs_first_named_child(vd); |
| 1648 | /* For each declarator, bind the variable to (rhs_type or declared type). */ |
| 1649 | uint32_t nc = ts_node_child_count(vd); |
| 1650 | bool is_var = false; |
| 1651 | if (!ts_node_is_null(tnode)) { |
| 1652 | char *tt = cs_node_text(ctx, tnode); |
| 1653 | if (tt && (strcmp(tt, "var") == 0 || strcmp(ts_node_type(tnode), "implicit_type") == 0)) { |
| 1654 | is_var = true; |
| 1655 | } |
| 1656 | } |
| 1657 | const CBMType *declared_type = |
| 1658 | ts_node_is_null(tnode) ? cbm_type_unknown() : cs_parse_type_node(ctx, tnode); |
| 1659 | for (uint32_t i = 0; i < nc; i++) { |
| 1660 | TSNode c = ts_node_child(vd, i); |
| 1661 | if (ts_node_is_null(c) || !ts_node_is_named(c)) |
| 1662 | continue; |
| 1663 | const char *k = ts_node_type(c); |
| 1664 | if (strcmp(k, "variable_declarator") != 0) |
| 1665 | continue; |
| 1666 | TSNode nm = cs_child_named_kind(c, "identifier"); |
| 1667 | if (ts_node_is_null(nm)) { |
| 1668 | nm = ts_node_child_by_field_name(c, "name", 4); |
| 1669 | } |
| 1670 | if (ts_node_is_null(nm)) |
| 1671 | continue; |
| 1672 | char *vname = cs_node_text(ctx, nm); |
| 1673 | if (!vname) |
| 1674 | continue; |
| 1675 | /* Find initializer (= rhs). variable_declarator children depend on |
| 1676 | * the grammar: tree-sitter-c-sharp emits `_identifier_or_global` |
| 1677 | * (the name) + optional `=` token + value-expression; the value |
| 1678 | * may also be wrapped in equals_value_clause in some grammar |
| 1679 | * variants. Try the field-name path first, then fall back to |
| 1680 | * walking named children for any expression after the identifier. */ |
| 1681 | TSNode init = ts_node_child_by_field_name(c, "value", 5); |
| 1682 | TSNode rhs_node; |
| 1683 | memset(&rhs_node, 0, sizeof(rhs_node)); |
| 1684 | const CBMType *rhs_t = NULL; |
| 1685 | if (!ts_node_is_null(init)) { |
| 1686 | if (strcmp(ts_node_type(init), "equals_value_clause") == 0) { |
| 1687 | TSNode rhs = cs_first_named_child(init); |
| 1688 | if (!ts_node_is_null(rhs)) { |
| 1689 | rhs_node = rhs; |
| 1690 | rhs_t = cs_eval_expr_type(ctx, rhs); |
| 1691 | } |
| 1692 | } else { |
| 1693 | rhs_node = init; |
| 1694 | rhs_t = cs_eval_expr_type(ctx, init); |
| 1695 | } |
| 1696 | } |
| 1697 | if (!rhs_t || rhs_t->kind == CBM_TYPE_UNKNOWN) { |
no test coverage detected