| 4017 | } |
| 4018 | |
| 4019 | static void extract_class_def(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec *spec) { |
| 4020 | CBMArena *a = ctx->arena; |
| 4021 | const char *kind = ts_node_type(node); |
| 4022 | |
| 4023 | if (extract_config_class_def(ctx, node, kind)) { |
| 4024 | return; |
| 4025 | } |
| 4026 | |
| 4027 | TSNode name_node = ts_node_child_by_field_name(node, TS_FIELD("name")); |
| 4028 | // ObjC: class name is first identifier child |
| 4029 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_OBJC) { |
| 4030 | name_node = cbm_find_child_by_kind(node, "identifier"); |
| 4031 | } |
| 4032 | // ObjectScript UDL: class name is a `class_name` child (no "name" field). |
| 4033 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_OBJECTSCRIPT_UDL) { |
| 4034 | name_node = cbm_find_child_by_kind(node, "class_name"); |
| 4035 | } |
| 4036 | // Swift and newer tree-sitter-kotlin: class/object name is a type_identifier |
| 4037 | // child (no "name" field). |
| 4038 | if (ts_node_is_null(name_node) && |
| 4039 | (ctx->language == CBM_LANG_SWIFT || ctx->language == CBM_LANG_KOTLIN)) { |
| 4040 | name_node = cbm_find_child_by_kind(node, "type_identifier"); |
| 4041 | } |
| 4042 | // Protobuf: service_name / message_name / enum_name children |
| 4043 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_PROTOBUF) { |
| 4044 | name_node = cbm_find_child_by_kind(node, "service_name"); |
| 4045 | if (ts_node_is_null(name_node)) { |
| 4046 | name_node = cbm_find_child_by_kind(node, "message_name"); |
| 4047 | } |
| 4048 | if (ts_node_is_null(name_node)) { |
| 4049 | name_node = cbm_find_child_by_kind(node, "enum_name"); |
| 4050 | } |
| 4051 | } |
| 4052 | // Thrift / Smithy / Pony / PKL (no `name` field): class-type defs carry the |
| 4053 | // name on a plain `identifier` child (PKL `clazz` -> `(identifier) (classBody)`). |
| 4054 | if (ts_node_is_null(name_node) && |
| 4055 | (ctx->language == CBM_LANG_THRIFT || ctx->language == CBM_LANG_SMITHY || |
| 4056 | ctx->language == CBM_LANG_PONY || ctx->language == CBM_LANG_PKL)) { |
| 4057 | name_node = cbm_find_child_by_kind(node, "identifier"); |
| 4058 | } |
| 4059 | // F#: type_definition wraps an `anon_type_defn` (or similar) whose |
| 4060 | // `type_name` child carries the type name on its own `type_name` field. |
| 4061 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_FSHARP) { |
| 4062 | TSNode tn = find_first_descendant_by_kind(node, "type_name", CBM_DESCENDANT_MAX_DEPTH); |
| 4063 | if (!ts_node_is_null(tn)) { |
| 4064 | TSNode id = ts_node_child_by_field_name(tn, "type_name", 9); |
| 4065 | if (ts_node_is_null(id)) { |
| 4066 | id = cbm_find_child_by_kind(tn, "identifier"); |
| 4067 | } |
| 4068 | if (!ts_node_is_null(id)) { |
| 4069 | name_node = id; |
| 4070 | } |
| 4071 | } |
| 4072 | } |
| 4073 | // D: class/struct/interface/union/enum _declaration nodes carry the name on |
| 4074 | // a plain `identifier` child (no `name` field). |
| 4075 | if (ts_node_is_null(name_node) && ctx->language == CBM_LANG_DLANG) { |
| 4076 | name_node = cbm_find_child_by_kind(node, "identifier"); |
no test coverage detected