| 3494 | } |
| 3495 | |
| 3496 | static void extract_class_def(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec *spec) { |
| 3497 | CBMArena *a = ctx->arena; |
| 3498 | const char *kind = ts_node_type(node); |
| 3499 | |
| 3500 | if (extract_config_class_def(ctx, node, kind)) { |
| 3501 | return; |
| 3502 | } |
| 3503 | |
| 3504 | TSNode name_node = ts_node_child_by_field_name(node, TS_FIELD("name")); |
| 3505 | // ObjC: class name is first identifier child |
| 3506 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_OBJC) { |
| 3507 | name_node = cbm_find_child_by_kind(node, "identifier"); |
| 3508 | } |
| 3509 | // Swift and newer tree-sitter-kotlin: class/object name is a type_identifier |
| 3510 | // child (no "name" field). |
| 3511 | if (ts_node_is_null(name_node) && |
| 3512 | (ctx->language == CBM_LANG_SWIFT || ctx->language == CBM_LANG_KOTLIN)) { |
| 3513 | name_node = cbm_find_child_by_kind(node, "type_identifier"); |
| 3514 | } |
| 3515 | // Protobuf: service_name / message_name / enum_name children |
| 3516 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_PROTOBUF) { |
| 3517 | name_node = cbm_find_child_by_kind(node, "service_name"); |
| 3518 | if (ts_node_is_null(name_node)) { |
| 3519 | name_node = cbm_find_child_by_kind(node, "message_name"); |
| 3520 | } |
| 3521 | if (ts_node_is_null(name_node)) { |
| 3522 | name_node = cbm_find_child_by_kind(node, "enum_name"); |
| 3523 | } |
| 3524 | } |
| 3525 | // Thrift / Smithy / Pony / PKL (no `name` field): class-type defs carry the |
| 3526 | // name on a plain `identifier` child (PKL `clazz` -> `(identifier) (classBody)`). |
| 3527 | if (ts_node_is_null(name_node) && |
| 3528 | (ctx->language == CBM_LANG_THRIFT || ctx->language == CBM_LANG_SMITHY || |
| 3529 | ctx->language == CBM_LANG_PONY || ctx->language == CBM_LANG_PKL)) { |
| 3530 | name_node = cbm_find_child_by_kind(node, "identifier"); |
| 3531 | } |
| 3532 | // F#: type_definition wraps an `anon_type_defn` (or similar) whose |
| 3533 | // `type_name` child carries the type name on its own `type_name` field. |
| 3534 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_FSHARP) { |
| 3535 | TSNode tn = find_first_descendant_by_kind(node, "type_name", CBM_DESCENDANT_MAX_DEPTH); |
| 3536 | if (!ts_node_is_null(tn)) { |
| 3537 | TSNode id = ts_node_child_by_field_name(tn, "type_name", 9); |
| 3538 | if (ts_node_is_null(id)) { |
| 3539 | id = cbm_find_child_by_kind(tn, "identifier"); |
| 3540 | } |
| 3541 | if (!ts_node_is_null(id)) { |
| 3542 | name_node = id; |
| 3543 | } |
| 3544 | } |
| 3545 | } |
| 3546 | // D: class/struct/interface/union/enum _declaration nodes carry the name on |
| 3547 | // a plain `identifier` child (no `name` field). |
| 3548 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_DLANG) { |
| 3549 | name_node = cbm_find_child_by_kind(node, "identifier"); |
| 3550 | } |
| 3551 | // PowerShell: class_statement / enum_statement have no `name` field; the |
| 3552 | // name is the FIRST `simple_name` child (`class Dog : Animal { ... }`). |
| 3553 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_POWERSHELL) { |
no test coverage detected