| 1599 | } |
| 1600 | |
| 1601 | static const char *lexical_binding_key(CBMExtractCtx *ctx, WalkState *state, const char *name) { |
| 1602 | if (!ctx || !name) { |
| 1603 | return name; |
| 1604 | } |
| 1605 | /* Preserve language namespaces: Perl sigils and Vim prefixes distinguish |
| 1606 | * different variables. Tcl's grammar is asymmetric (`name` versus |
| 1607 | * `$name`), so unwrap only that language-defined reference sigil. */ |
| 1608 | if (ctx->language == CBM_LANG_TCL && name[0] == '$') { |
| 1609 | name++; |
| 1610 | } |
| 1611 | if (!lexical_identifier_case_insensitive(ctx->language)) { |
| 1612 | return name; |
| 1613 | } |
| 1614 | size_t n = strlen(name); |
| 1615 | char *folded = (char *)cbm_arena_alloc(ctx->arena, n + 1U); |
| 1616 | if (!folded) { |
| 1617 | if (state) { |
| 1618 | state->lexical_binding_tracking_failed = true; |
| 1619 | } |
| 1620 | return NULL; |
| 1621 | } |
| 1622 | for (size_t i = 0; i < n; i++) { |
| 1623 | folded[i] = (char)tolower((unsigned char)name[i]); |
| 1624 | } |
| 1625 | folded[n] = '\0'; |
| 1626 | return folded; |
| 1627 | } |
| 1628 | |
| 1629 | static void stamp_usage_site(CBMExtractCtx *ctx, CBMUsage *usage, TSNode node, const char *name, |
| 1630 | WalkState *state) { |
no test coverage detected