Walk the whole tree once and collect `const IDENT = "value"` bindings so * later passes can resolve bare-identifier channel arguments. Only scalar * string literals are tracked — template literals and expressions are left * unresolved. This is a flat lookup; scope boundaries are ignored (a single * const table per file is sufficient for the common Socket.IO pattern). */
| 100 | * unresolved. This is a flat lookup; scope boundaries are ignored (a single |
| 101 | * const table per file is sufficient for the common Socket.IO pattern). */ |
| 102 | static void scan_string_consts_js(CBMExtractCtx *ctx, chan_const_table_t *tbl) { |
| 103 | TSNodeStack stack; |
| 104 | ts_nstack_init(&stack, ctx->arena, CHAN_STACK_CAP); |
| 105 | ts_nstack_push(&stack, ctx->arena, ctx->root); |
| 106 | |
| 107 | while (stack.count > 0 && tbl->count < CHAN_CONST_CAP) { |
| 108 | TSNode node = ts_nstack_pop(&stack); |
| 109 | const char *kind = ts_node_type(node); |
| 110 | |
| 111 | if (strcmp(kind, "variable_declarator") == 0) { |
| 112 | TSNode name_node = ts_node_child_by_field_name(node, TS_FIELD("name")); |
| 113 | TSNode value_node = ts_node_child_by_field_name(node, TS_FIELD("value")); |
| 114 | if (!ts_node_is_null(name_node) && !ts_node_is_null(value_node)) { |
| 115 | const char *nk = ts_node_type(name_node); |
| 116 | const char *vk = ts_node_type(value_node); |
| 117 | if (strcmp(nk, "identifier") == 0 && |
| 118 | (strcmp(vk, "string") == 0 || strcmp(vk, "string_literal") == 0)) { |
| 119 | char *name_text = cbm_node_text(ctx->arena, name_node, ctx->source); |
| 120 | char *value_text = cbm_node_text(ctx->arena, value_node, ctx->source); |
| 121 | const char *unq = unquote_string(ctx->arena, value_text); |
| 122 | if (name_text && unq) { |
| 123 | tbl->items[tbl->count].name = name_text; |
| 124 | tbl->items[tbl->count].value = unq; |
| 125 | tbl->count++; |
| 126 | } |
| 127 | } |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | ts_nstack_push_children(&stack, ctx->arena, node); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | /* Python constant resolution: NAME = "value" (assignment node). */ |
| 136 | static void scan_string_consts_python(CBMExtractCtx *ctx, chan_const_table_t *tbl) { |
no test coverage detected