| 4014 | } |
| 4015 | |
| 4016 | static void py_process_function(PyLSPContext *ctx, TSNode func_node, const char *container_qn) { |
| 4017 | TSNode name_node = ts_node_child_by_field_name(func_node, "name", 4); |
| 4018 | if (ts_node_is_null(name_node)) |
| 4019 | return; |
| 4020 | char *fname = py_node_text(ctx, name_node); |
| 4021 | if (!fname || !fname[0]) |
| 4022 | return; |
| 4023 | |
| 4024 | const char *prev_func = ctx->enclosing_func_qn; |
| 4025 | const char *base_qn = container_qn ? container_qn : ctx->module_qn; |
| 4026 | ctx->enclosing_func_qn = cbm_arena_sprintf(ctx->arena, "%s.%s", base_qn, fname); |
| 4027 | |
| 4028 | CBMScope *saved = ctx->current_scope; |
| 4029 | ctx->current_scope = py_scope_push_checked(ctx); |
| 4030 | |
| 4031 | TSNode params = ts_node_child_by_field_name(func_node, "parameters", 10); |
| 4032 | py_bind_parameters(ctx, params); |
| 4033 | |
| 4034 | // For methods, bind `self`/`cls` AFTER param walk so the receiver type |
| 4035 | // wins over the unannotated `self` / `cls` parameter declaration. |
| 4036 | if (ctx->enclosing_class_qn) { |
| 4037 | py_scope_bind(ctx, "self", cbm_type_named(ctx->arena, ctx->enclosing_class_qn)); |
| 4038 | py_scope_bind(ctx, "cls", cbm_type_named(ctx->arena, ctx->enclosing_class_qn)); |
| 4039 | } |
| 4040 | |
| 4041 | TSNode body = ts_node_child_by_field_name(func_node, "body", 4); |
| 4042 | if (!ts_node_is_null(body)) { |
| 4043 | py_resolve_calls_in(ctx, body); |
| 4044 | // Also descend into nested function/class definitions in the body. |
| 4045 | uint32_t bnc = ts_node_named_child_count(body); |
| 4046 | for (uint32_t i = 0; i < bnc; i++) { |
| 4047 | TSNode c = ts_node_named_child(body, i); |
| 4048 | const char *ck = ts_node_type(c); |
| 4049 | if (strcmp(ck, "function_definition") == 0) { |
| 4050 | py_process_function(ctx, c, ctx->enclosing_func_qn); |
| 4051 | } else if (strcmp(ck, "decorated_definition") == 0) { |
| 4052 | TSNode def = ts_node_child_by_field_name(c, "definition", 10); |
| 4053 | if (!ts_node_is_null(def) && |
| 4054 | strcmp(ts_node_type(def), "function_definition") == 0) { |
| 4055 | py_process_function(ctx, def, ctx->enclosing_func_qn); |
| 4056 | } |
| 4057 | } |
| 4058 | } |
| 4059 | } |
| 4060 | |
| 4061 | py_scope_restore(ctx, saved); |
| 4062 | ctx->enclosing_func_qn = prev_func; |
| 4063 | } |
| 4064 | |
| 4065 | /* Return true iff func_node's name is __init__ or __post_init__. */ |
| 4066 | static bool py_is_init_method(PyLSPContext *ctx, TSNode func_node) { |
no test coverage detected