| 2371 | } |
| 2372 | |
| 2373 | static const char **extract_base_classes(CBMArena *a, TSNode node, const char *source, |
| 2374 | CBMLanguage lang) { |
| 2375 | // Languages whose heritage is not exposed via a tree-sitter field need |
| 2376 | // dedicated walkers; the generic field/keyword path mis-captures them. |
| 2377 | if (lang == CBM_LANG_TYPESCRIPT || lang == CBM_LANG_TSX) { |
| 2378 | const char **ts_result = extract_ts_bases(a, node, source); |
| 2379 | if (ts_result) { |
| 2380 | return ts_result; |
| 2381 | } |
| 2382 | } |
| 2383 | if (lang == CBM_LANG_PHP) { |
| 2384 | const char **php_result = extract_php_bases(a, node, source); |
| 2385 | if (php_result) { |
| 2386 | return php_result; |
| 2387 | } |
| 2388 | } |
| 2389 | if (lang == CBM_LANG_KOTLIN) { |
| 2390 | const char **kt_result = extract_kotlin_bases(a, node, source); |
| 2391 | if (kt_result) { |
| 2392 | return kt_result; |
| 2393 | } |
| 2394 | } |
| 2395 | // Squirrel: `class Dog extends Animal` — heritage is an `identifier` child |
| 2396 | // directly following the `extends` keyword (no field). Grab it. |
| 2397 | if (lang == CBM_LANG_SQUIRREL) { |
| 2398 | uint32_t sc = ts_node_child_count(node); |
| 2399 | bool seen_extends = false; |
| 2400 | for (uint32_t i = 0; i < sc; i++) { |
| 2401 | TSNode child = ts_node_child(node, i); |
| 2402 | const char *ck = ts_node_type(child); |
| 2403 | if (strcmp(ck, "extends") == 0) { |
| 2404 | seen_extends = true; |
| 2405 | continue; |
| 2406 | } |
| 2407 | if (seen_extends && strcmp(ck, "identifier") == 0) { |
| 2408 | char *base = cbm_node_text(a, child, source); |
| 2409 | if (base && base[0]) { |
| 2410 | const char **result = |
| 2411 | (const char **)cbm_arena_alloc(a, 2 * sizeof(const char *)); |
| 2412 | if (result) { |
| 2413 | result[0] = base; |
| 2414 | result[1] = NULL; |
| 2415 | return result; |
| 2416 | } |
| 2417 | } |
| 2418 | break; |
| 2419 | } |
| 2420 | } |
| 2421 | } |
| 2422 | if (lang == CBM_LANG_JULIA) { |
| 2423 | const char **jb = extract_julia_base_classes(a, node, source); |
| 2424 | if (jb) { |
| 2425 | return jb; |
| 2426 | } |
| 2427 | } |
| 2428 | /* F#: `inherit Base(...)` appears as a `class_inherits_decl` descendant of |
| 2429 | * the type_definition; the base type is the `simple_type` it carries. */ |
| 2430 | if (lang == CBM_LANG_FSHARP) { |
no test coverage detected