Recursively bind every identifier inside a pattern node to the given * fallback type. Handles tuple_pattern, struct_pattern, tuple_struct_pattern, * ref_pattern, mut_pattern, captured_pattern, identifier. */
| 3327 | * fallback type. Handles tuple_pattern, struct_pattern, tuple_struct_pattern, |
| 3328 | * ref_pattern, mut_pattern, captured_pattern, identifier. */ |
| 3329 | static void rust_bind_pattern(RustLSPContext *ctx, TSNode pattern, const CBMType *type) { |
| 3330 | if (ts_node_is_null(pattern)) |
| 3331 | return; |
| 3332 | const char *kind = ts_node_type(pattern); |
| 3333 | |
| 3334 | if (strcmp(kind, "identifier") == 0) { |
| 3335 | char *name = rust_node_text(ctx, pattern); |
| 3336 | if (name && strcmp(name, "_") != 0) { |
| 3337 | cbm_scope_bind(ctx->current_scope, name, type); |
| 3338 | } |
| 3339 | return; |
| 3340 | } |
| 3341 | if (strcmp(kind, "captured_pattern") == 0) { |
| 3342 | /* name @ subpattern */ |
| 3343 | TSNode name_node = ts_node_child_by_field_name(pattern, "name", 4); |
| 3344 | if (!ts_node_is_null(name_node)) { |
| 3345 | char *name = rust_node_text(ctx, name_node); |
| 3346 | if (name && strcmp(name, "_") != 0) { |
| 3347 | cbm_scope_bind(ctx->current_scope, name, type); |
| 3348 | } |
| 3349 | } |
| 3350 | TSNode sub = ts_node_child_by_field_name(pattern, "pattern", 7); |
| 3351 | if (!ts_node_is_null(sub)) |
| 3352 | rust_bind_pattern(ctx, sub, type); |
| 3353 | return; |
| 3354 | } |
| 3355 | if (strcmp(kind, "ref_pattern") == 0 || strcmp(kind, "mut_pattern") == 0 || |
| 3356 | strcmp(kind, "reference_pattern") == 0) { |
| 3357 | if (ts_node_named_child_count(pattern) > 0) { |
| 3358 | rust_bind_pattern(ctx, ts_node_named_child(pattern, 0), type); |
| 3359 | } |
| 3360 | return; |
| 3361 | } |
| 3362 | if (strcmp(kind, "tuple_pattern") == 0) { |
| 3363 | const CBMType *base = type; |
| 3364 | while (base && base->kind == CBM_TYPE_REFERENCE) |
| 3365 | base = base->data.reference.elem; |
| 3366 | uint32_t nc = ts_node_named_child_count(pattern); |
| 3367 | for (uint32_t i = 0; i < nc; i++) { |
| 3368 | const CBMType *elem_t = cbm_type_unknown(); |
| 3369 | if (base && base->kind == CBM_TYPE_TUPLE && (int)i < base->data.tuple.count) { |
| 3370 | elem_t = base->data.tuple.elems[i]; |
| 3371 | } |
| 3372 | rust_bind_pattern(ctx, ts_node_named_child(pattern, i), elem_t); |
| 3373 | } |
| 3374 | return; |
| 3375 | } |
| 3376 | if (strcmp(kind, "tuple_struct_pattern") == 0) { |
| 3377 | /* Some(x), Ok(x), Err(e) — peel one Option/Result/template. */ |
| 3378 | const CBMType *base = type; |
| 3379 | while (base && base->kind == CBM_TYPE_REFERENCE) |
| 3380 | base = base->data.reference.elem; |
| 3381 | const CBMType *inner = cbm_type_unknown(); |
| 3382 | if (base && base->kind == CBM_TYPE_TEMPLATE && base->data.template_type.arg_count > 0) { |
| 3383 | inner = base->data.template_type.template_args[0]; |
| 3384 | } |
| 3385 | uint32_t nc = ts_node_named_child_count(pattern); |
| 3386 | /* First named child is the path; subsequent are sub-patterns. */ |
no test coverage detected