| 2917 | } |
| 2918 | |
| 2919 | static void kt_process_lambda(KotlinLSPContext *ctx, TSNode lambda, const CBMType *receiver_type) { |
| 2920 | /* lambda_literal: '{' lambda_parameters? '->' statements '}' |
| 2921 | * If no parameters, `it` is bound to the receiver. */ |
| 2922 | if (ts_node_is_null(lambda)) { |
| 2923 | return; |
| 2924 | } |
| 2925 | ctx->current_scope = cbm_scope_push(ctx->arena, ctx->current_scope); |
| 2926 | const CBMType *prev_it = ctx->it_type; |
| 2927 | /* DSL receiver: when the callee's lambda parameter has a function-with- |
| 2928 | * receiver type (`Foo.() -> Unit`), the lambda's `this` is Foo and bare |
| 2929 | * calls inside resolve against Foo's members. The dsl_this_type is |
| 2930 | * passed via receiver_type when the caller can determine it. */ |
| 2931 | const CBMType *prev_this = ctx->this_type; |
| 2932 | if (receiver_type && !cbm_type_is_unknown(receiver_type)) { |
| 2933 | ctx->this_type = receiver_type; |
| 2934 | } |
| 2935 | TSNode params = kt_child_kind(lambda, "lambda_parameters"); |
| 2936 | if (ts_node_is_null(params)) { |
| 2937 | if (receiver_type && !cbm_type_is_unknown(receiver_type)) { |
| 2938 | ctx->it_type = receiver_type; |
| 2939 | } |
| 2940 | } else { |
| 2941 | uint32_t pnc = ts_node_named_child_count(params); |
| 2942 | for (uint32_t i = 0; i < pnc; i++) { |
| 2943 | TSNode pn = ts_node_named_child(params, i); |
| 2944 | TSNode id = kt_name_child(pn); |
| 2945 | if (ts_node_is_null(id)) { |
| 2946 | id = kt_child_kind_named(pn, "simple_identifier"); |
| 2947 | } |
| 2948 | if (!ts_node_is_null(id)) { |
| 2949 | char *name = kt_node_text(ctx, id); |
| 2950 | if (name) { |
| 2951 | /* Type annotation? */ |
| 2952 | TSNode tn = kt_child_kind(pn, "type"); |
| 2953 | const CBMType *t = |
| 2954 | ts_node_is_null(tn) ? cbm_type_unknown() : kotlin_parse_type_node(ctx, tn); |
| 2955 | cbm_scope_bind(ctx->current_scope, cbm_arena_strdup(ctx->arena, name), t); |
| 2956 | } |
| 2957 | } |
| 2958 | } |
| 2959 | } |
| 2960 | /* Walk lambda body */ |
| 2961 | uint32_t nc = ts_node_named_child_count(lambda); |
| 2962 | for (uint32_t i = 0; i < nc; i++) { |
| 2963 | TSNode c = ts_node_named_child(lambda, i); |
| 2964 | const char *k = ts_node_type(c); |
| 2965 | if (strcmp(k, "lambda_parameters") == 0) { |
| 2966 | continue; |
| 2967 | } |
| 2968 | kt_process_statement(ctx, c); |
| 2969 | } |
| 2970 | ctx->it_type = prev_it; |
| 2971 | ctx->this_type = prev_this; |
| 2972 | ctx->current_scope = cbm_scope_pop(ctx->current_scope); |
| 2973 | } |
| 2974 | |
| 2975 | static void kt_process_call_with_lambda(KotlinLSPContext *ctx, TSNode call_node) { |
| 2976 | /* If call has trailing lambda, propagate the receiver type as `it`. |
no test coverage detected