| 4759 | // ============================================================================ |
| 4760 | |
| 4761 | static void c_process_function(CLSPContext *ctx, TSNode func_node) { |
| 4762 | TSNode decl = ts_node_child_by_field_name(func_node, "declarator", 10); |
| 4763 | if (ts_node_is_null(decl)) |
| 4764 | return; |
| 4765 | |
| 4766 | // Extract function name from declarator chain |
| 4767 | char *func_name = NULL; |
| 4768 | const char *saved_class_qn = ctx->enclosing_class_qn; |
| 4769 | const char *saved_func_qn = ctx->enclosing_func_qn; |
| 4770 | TSNode params_node = (TSNode){0}; |
| 4771 | |
| 4772 | // Navigate declarator to find name and parameters |
| 4773 | TSNode cur = decl; |
| 4774 | for (int depth = 0; depth < 10 && !ts_node_is_null(cur); depth++) { |
| 4775 | const char *dk = ts_node_type(cur); |
| 4776 | |
| 4777 | if (strcmp(dk, "function_declarator") == 0) { |
| 4778 | TSNode fdecl = ts_node_child_by_field_name(cur, "declarator", 10); |
| 4779 | params_node = ts_node_child_by_field_name(cur, "parameters", 10); |
| 4780 | cur = fdecl; |
| 4781 | continue; |
| 4782 | } |
| 4783 | if (strcmp(dk, "pointer_declarator") == 0 || strcmp(dk, "reference_declarator") == 0) { |
| 4784 | if (ts_node_named_child_count(cur) > 0) |
| 4785 | cur = ts_node_named_child(cur, ts_node_named_child_count(cur) - 1); |
| 4786 | else |
| 4787 | break; |
| 4788 | continue; |
| 4789 | } |
| 4790 | if (strcmp(dk, "qualified_identifier") == 0 || strcmp(dk, "scoped_identifier") == 0) { |
| 4791 | func_name = c_node_text(ctx, cur); |
| 4792 | // Check if this is a method (has Class:: prefix) |
| 4793 | TSNode scope_node = ts_node_child_by_field_name(cur, "scope", 5); |
| 4794 | if (!ts_node_is_null(scope_node)) { |
| 4795 | char *scope_text = c_node_text(ctx, scope_node); |
| 4796 | if (scope_text) { |
| 4797 | const char *scope_qn = c_build_qn(ctx, scope_text); |
| 4798 | // Try as a type for enclosing class |
| 4799 | const CBMRegisteredType *rt = cbm_registry_lookup_type(ctx->registry, scope_qn); |
| 4800 | if (rt) { |
| 4801 | ctx->enclosing_class_qn = scope_qn; |
| 4802 | } else if (ctx->module_qn) { |
| 4803 | const char *fqn = |
| 4804 | cbm_arena_sprintf(ctx->arena, "%s.%s", ctx->module_qn, scope_qn); |
| 4805 | rt = cbm_registry_lookup_type(ctx->registry, fqn); |
| 4806 | if (rt) |
| 4807 | ctx->enclosing_class_qn = fqn; |
| 4808 | } |
| 4809 | } |
| 4810 | } |
| 4811 | break; |
| 4812 | } |
| 4813 | if (strcmp(dk, "identifier") == 0) { |
| 4814 | func_name = c_node_text(ctx, cur); |
| 4815 | break; |
| 4816 | } |
| 4817 | if (strcmp(dk, "field_identifier") == 0) { |
| 4818 | func_name = c_node_text(ctx, cur); |
no test coverage detected