| 3274 | /* ── top-level walking ────────────────────────────────────────────── */ |
| 3275 | |
| 3276 | static void kt_process_function_body(KotlinLSPContext *ctx, TSNode func_node, const char *func_qn, |
| 3277 | const char *receiver_class_qn) { |
| 3278 | const char *prev_func = ctx->enclosing_func_qn; |
| 3279 | const char *prev_class = ctx->enclosing_class_qn; |
| 3280 | const CBMType *prev_this = ctx->this_type; |
| 3281 | const CBMType *prev_super = ctx->super_type; |
| 3282 | const char *prev_super_qn = ctx->enclosing_super_qn; |
| 3283 | |
| 3284 | ctx->enclosing_func_qn = func_qn; |
| 3285 | const CBMRegisteredType *receiver_rt = NULL; |
| 3286 | if (receiver_class_qn) { |
| 3287 | ctx->this_type = cbm_type_named(ctx->arena, receiver_class_qn); |
| 3288 | receiver_rt = cbm_registry_lookup_type(ctx->registry, receiver_class_qn); |
| 3289 | if (receiver_rt && receiver_rt->embedded_types && receiver_rt->embedded_types[0]) { |
| 3290 | ctx->enclosing_super_qn = receiver_rt->embedded_types[0]; |
| 3291 | ctx->super_type = cbm_type_named(ctx->arena, receiver_rt->embedded_types[0]); |
| 3292 | } |
| 3293 | } |
| 3294 | |
| 3295 | ctx->current_scope = cbm_scope_push(ctx->arena, ctx->current_scope); |
| 3296 | kt_bind_function_params(ctx, func_node); |
| 3297 | |
| 3298 | /* Bind class fields (primary-constructor val/var properties) into the |
| 3299 | * method scope so bare references like `name.uppercase()` inside a |
| 3300 | * method body resolve to the field's type. */ |
| 3301 | if (receiver_rt && receiver_rt->field_names && receiver_rt->field_types) { |
| 3302 | for (int i = 0; receiver_rt->field_names[i]; i++) { |
| 3303 | cbm_scope_bind(ctx->current_scope, |
| 3304 | cbm_arena_strdup(ctx->arena, receiver_rt->field_names[i]), |
| 3305 | receiver_rt->field_types[i]); |
| 3306 | } |
| 3307 | } |
| 3308 | |
| 3309 | TSNode body = kt_field_named(func_node, "body"); |
| 3310 | if (ts_node_is_null(body)) { |
| 3311 | body = kt_child_kind(func_node, "function_body"); |
| 3312 | } |
| 3313 | if (ts_node_is_null(body)) { |
| 3314 | body = kt_child_kind(func_node, "block"); |
| 3315 | } |
| 3316 | /* Fallback: some grammar variants emit the single-expression body |
| 3317 | * directly as a child of function_declaration without wrapping it in |
| 3318 | * `function_body`. Scan the named children for the last node that |
| 3319 | * looks like an expression or statement (i.e. not modifiers, name, |
| 3320 | * type parameters, or value parameters). */ |
| 3321 | if (ts_node_is_null(body)) { |
| 3322 | uint32_t nc = ts_node_named_child_count(func_node); |
| 3323 | for (uint32_t i = nc; i > 0; i--) { |
| 3324 | TSNode c = ts_node_named_child(func_node, i - 1); |
| 3325 | if (ts_node_is_null(c)) { |
| 3326 | continue; |
| 3327 | } |
| 3328 | const char *k = ts_node_type(c); |
| 3329 | if (strcmp(k, "modifiers") == 0 || strcmp(k, "identifier") == 0 || |
| 3330 | strcmp(k, "simple_identifier") == 0 || |
| 3331 | strcmp(k, "function_value_parameters") == 0 || strcmp(k, "type_parameters") == 0 || |
| 3332 | strcmp(k, "type_constraints") == 0 || strcmp(k, "annotation") == 0) { |
| 3333 | continue; |
no test coverage detected