Extract methods inside a class body
| 4170 | |
| 4171 | // Extract methods inside a class body |
| 4172 | static void extract_class_methods(CBMExtractCtx *ctx, TSNode class_node, const char *class_qn, |
| 4173 | const CBMLangSpec *spec) { |
| 4174 | TSNode body = find_class_body(class_node, ctx->language); |
| 4175 | if (ts_node_is_null(body)) { |
| 4176 | return; |
| 4177 | } |
| 4178 | |
| 4179 | uint32_t count = ts_node_child_count(body); |
| 4180 | for (uint32_t i = 0; i < count; i++) { |
| 4181 | TSNode child = ts_node_child(body, i); |
| 4182 | if (ts_node_is_null(child)) { |
| 4183 | continue; |
| 4184 | } |
| 4185 | |
| 4186 | if (ctx->language == CBM_LANG_OBJC && |
| 4187 | strcmp(ts_node_type(child), "implementation_definition") == 0) { |
| 4188 | extract_objc_impl_methods(ctx, child, class_qn, spec); |
| 4189 | continue; |
| 4190 | } |
| 4191 | |
| 4192 | // Squirrel wraps each class member in a member_declaration node; the |
| 4193 | // method is the inner function_declaration. Peek through the wrapper. |
| 4194 | if (ctx->language == CBM_LANG_SQUIRREL && |
| 4195 | strcmp(ts_node_type(child), "member_declaration") == 0) { |
| 4196 | TSNode inner = cbm_find_child_by_kind(child, "function_declaration"); |
| 4197 | if (!ts_node_is_null(inner)) { |
| 4198 | child = inner; |
| 4199 | } |
| 4200 | } |
| 4201 | |
| 4202 | // Python wraps @classmethod / @staticmethod / @property methods in |
| 4203 | // a decorated_definition node. Peek through it to find the inner |
| 4204 | // function_definition so we still emit a Method entry. |
| 4205 | TSNode method_node = child; |
| 4206 | if (strcmp(ts_node_type(child), "decorated_definition") == 0) { |
| 4207 | TSNode def = ts_node_child_by_field_name(child, TS_FIELD("definition")); |
| 4208 | if (ts_node_is_null(def) || !cbm_kind_in_set(def, spec->function_node_types)) { |
| 4209 | continue; |
| 4210 | } |
| 4211 | method_node = def; |
| 4212 | } |
| 4213 | |
| 4214 | // TS/JS class-field arrow functions: `handleClick = () => {...}` is a |
| 4215 | // public_field_definition whose `value` is an arrow_function (a common |
| 4216 | // React event-handler pattern). It is not in function_node_types, so it |
| 4217 | // would otherwise be dropped. Peek through to the inner arrow and take |
| 4218 | // the method name from the field's `name` child (#new_ts_class_field_arrow). |
| 4219 | if (strcmp(ts_node_type(child), "public_field_definition") == 0) { |
| 4220 | TSNode value = ts_node_child_by_field_name(child, TS_FIELD("value")); |
| 4221 | if (ts_node_is_null(value) || !cbm_kind_in_set(value, spec->function_node_types)) { |
| 4222 | continue; |
| 4223 | } |
| 4224 | TSNode fname = ts_node_child_by_field_name(child, TS_FIELD("name")); |
| 4225 | if (ts_node_is_null(fname)) { |
| 4226 | continue; |
| 4227 | } |
| 4228 | push_method_def(ctx, value, class_node, class_qn, spec, fname); |
| 4229 | continue; |
no test coverage detected