| 553 | } |
| 554 | |
| 555 | static void handle_string_refs(CBMExtractCtx *ctx, TSNode node, const WalkState *state) { |
| 556 | const char *kind = ts_node_type(node); |
| 557 | if (!is_string_node(kind)) { |
| 558 | return; |
| 559 | } |
| 560 | |
| 561 | /* Extract string content */ |
| 562 | char *text = cbm_node_text(ctx->arena, node, ctx->source); |
| 563 | if (!text || !text[0]) { |
| 564 | return; |
| 565 | } |
| 566 | |
| 567 | /* Strip quotes if present */ |
| 568 | int len = (int)strlen(text); |
| 569 | const char *content = text; |
| 570 | if (len >= CBM_QUOTE_PAIR && (text[0] == '"' || text[0] == '\'')) { |
| 571 | content = text + SKIP_ONE; |
| 572 | len -= PAIR_LEN; |
| 573 | if (len <= 0) { |
| 574 | return; |
| 575 | } |
| 576 | } |
| 577 | |
| 578 | /* Classify */ |
| 579 | int kind_val = cbm_classify_string(content, len); |
| 580 | if (kind_val < 0) { |
| 581 | return; |
| 582 | } |
| 583 | |
| 584 | /* Build null-terminated content string in arena */ |
| 585 | char *val = cbm_arena_strndup(ctx->arena, content, (size_t)len); |
| 586 | if (!val) { |
| 587 | return; |
| 588 | } |
| 589 | |
| 590 | CBMStringRef ref = { |
| 591 | .value = val, |
| 592 | .enclosing_func_qn = state->enclosing_func_qn ? state->enclosing_func_qn : ctx->module_qn, |
| 593 | .kind = (CBMStringRefKind)kind_val, |
| 594 | }; |
| 595 | cbm_stringref_push(&ctx->result->string_refs, ctx->arena, ref); |
| 596 | } |
| 597 | |
| 598 | // --- YAML nested field extraction (D2) --- |
| 599 |
no test coverage detected