| 4299 | // ============================================================================ |
| 4300 | |
| 4301 | static void c_process_function(CLSPContext *ctx, TSNode func_node) { |
| 4302 | TSNode decl = ts_node_child_by_field_name(func_node, "declarator", 10); |
| 4303 | if (ts_node_is_null(decl)) |
| 4304 | return; |
| 4305 | |
| 4306 | // Extract function name from declarator chain |
| 4307 | char *func_name = NULL; |
| 4308 | const char *saved_class_qn = ctx->enclosing_class_qn; |
| 4309 | TSNode params_node = (TSNode){0}; |
| 4310 | |
| 4311 | // Navigate declarator to find name and parameters |
| 4312 | TSNode cur = decl; |
| 4313 | for (int depth = 0; depth < 10 && !ts_node_is_null(cur); depth++) { |
| 4314 | const char *dk = ts_node_type(cur); |
| 4315 | |
| 4316 | if (strcmp(dk, "function_declarator") == 0) { |
| 4317 | TSNode fdecl = ts_node_child_by_field_name(cur, "declarator", 10); |
| 4318 | params_node = ts_node_child_by_field_name(cur, "parameters", 10); |
| 4319 | cur = fdecl; |
| 4320 | continue; |
| 4321 | } |
| 4322 | if (strcmp(dk, "pointer_declarator") == 0 || strcmp(dk, "reference_declarator") == 0) { |
| 4323 | if (ts_node_named_child_count(cur) > 0) |
| 4324 | cur = ts_node_named_child(cur, ts_node_named_child_count(cur) - 1); |
| 4325 | else |
| 4326 | break; |
| 4327 | continue; |
| 4328 | } |
| 4329 | if (strcmp(dk, "qualified_identifier") == 0 || strcmp(dk, "scoped_identifier") == 0) { |
| 4330 | func_name = c_node_text(ctx, cur); |
| 4331 | // Check if this is a method (has Class:: prefix) |
| 4332 | TSNode scope_node = ts_node_child_by_field_name(cur, "scope", 5); |
| 4333 | if (!ts_node_is_null(scope_node)) { |
| 4334 | char *scope_text = c_node_text(ctx, scope_node); |
| 4335 | if (scope_text) { |
| 4336 | const char *scope_qn = c_build_qn(ctx, scope_text); |
| 4337 | // Try as a type for enclosing class |
| 4338 | const CBMRegisteredType *rt = cbm_registry_lookup_type(ctx->registry, scope_qn); |
| 4339 | if (rt) { |
| 4340 | ctx->enclosing_class_qn = scope_qn; |
| 4341 | } else if (ctx->module_qn) { |
| 4342 | const char *fqn = |
| 4343 | cbm_arena_sprintf(ctx->arena, "%s.%s", ctx->module_qn, scope_qn); |
| 4344 | rt = cbm_registry_lookup_type(ctx->registry, fqn); |
| 4345 | if (rt) |
| 4346 | ctx->enclosing_class_qn = fqn; |
| 4347 | } |
| 4348 | } |
| 4349 | } |
| 4350 | break; |
| 4351 | } |
| 4352 | if (strcmp(dk, "identifier") == 0) { |
| 4353 | func_name = c_node_text(ctx, cur); |
| 4354 | break; |
| 4355 | } |
| 4356 | if (strcmp(dk, "field_identifier") == 0) { |
| 4357 | func_name = c_node_text(ctx, cur); |
| 4358 | break; |
no test coverage detected