Extract methods inside a class body
| 4751 | |
| 4752 | // Extract methods inside a class body |
| 4753 | static void extract_class_methods(CBMExtractCtx *ctx, TSNode class_node, const char *class_qn, |
| 4754 | const CBMLangSpec *spec) { |
| 4755 | TSNode body = find_class_member_body(class_node, ctx->language); |
| 4756 | if (ts_node_is_null(body)) { |
| 4757 | return; |
| 4758 | } |
| 4759 | |
| 4760 | uint32_t count = ts_node_child_count(body); |
| 4761 | for (uint32_t i = 0; i < count; i++) { |
| 4762 | TSNode child = ts_node_child(body, i); |
| 4763 | if (ts_node_is_null(child)) { |
| 4764 | continue; |
| 4765 | } |
| 4766 | |
| 4767 | if (ctx->language == CBM_LANG_OBJC && |
| 4768 | strcmp(ts_node_type(child), "implementation_definition") == 0) { |
| 4769 | extract_objc_impl_methods(ctx, child, class_qn, spec); |
| 4770 | continue; |
| 4771 | } |
| 4772 | |
| 4773 | // Squirrel wraps each class member in a member_declaration node; the |
| 4774 | // method is the inner function_declaration. Peek through the wrapper. |
| 4775 | if (ctx->language == CBM_LANG_SQUIRREL && |
| 4776 | strcmp(ts_node_type(child), "member_declaration") == 0) { |
| 4777 | TSNode inner = cbm_find_child_by_kind(child, "function_declaration"); |
| 4778 | if (!ts_node_is_null(inner)) { |
| 4779 | child = inner; |
| 4780 | } |
| 4781 | } |
| 4782 | |
| 4783 | // Python wraps @classmethod / @staticmethod / @property methods in |
| 4784 | // a decorated_definition node. Peek through it to find the inner |
| 4785 | // function_definition so we still emit a Method entry. |
| 4786 | TSNode method_node = child; |
| 4787 | if (strcmp(ts_node_type(child), "decorated_definition") == 0) { |
| 4788 | TSNode def = ts_node_child_by_field_name(child, TS_FIELD("definition")); |
| 4789 | if (ts_node_is_null(def) || !cbm_kind_in_set(def, spec->function_node_types)) { |
| 4790 | continue; |
| 4791 | } |
| 4792 | method_node = def; |
| 4793 | } |
| 4794 | |
| 4795 | // TS/JS class-field arrow functions: `handleClick = () => {...}` is a |
| 4796 | // public_field_definition whose `value` is an arrow_function (a common |
| 4797 | // React event-handler pattern). It is not in function_node_types, so it |
| 4798 | // would otherwise be dropped. Peek through to the inner arrow and take |
| 4799 | // the method name from the field's `name` child (#new_ts_class_field_arrow). |
| 4800 | if (strcmp(ts_node_type(child), "public_field_definition") == 0) { |
| 4801 | TSNode value = ts_node_child_by_field_name(child, TS_FIELD("value")); |
| 4802 | if (ts_node_is_null(value) || !cbm_kind_in_set(value, spec->function_node_types)) { |
| 4803 | continue; |
| 4804 | } |
| 4805 | TSNode fname = ts_node_child_by_field_name(child, TS_FIELD("name")); |
| 4806 | if (ts_node_is_null(fname)) { |
| 4807 | continue; |
| 4808 | } |
| 4809 | push_method_def(ctx, value, class_node, class_qn, spec, fname); |
| 4810 | continue; |
no test coverage detected