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. */
| 3792 | * fallback type. Handles tuple_pattern, struct_pattern, tuple_struct_pattern, |
| 3793 | * ref_pattern, mut_pattern, captured_pattern, identifier. */ |
| 3794 | static void rust_bind_pattern(RustLSPContext *ctx, TSNode pattern, const CBMType *type) { |
| 3795 | if (ts_node_is_null(pattern)) |
| 3796 | return; |
| 3797 | const char *kind = ts_node_type(pattern); |
| 3798 | |
| 3799 | if (strcmp(kind, "identifier") == 0) { |
| 3800 | char *name = rust_node_text(ctx, pattern); |
| 3801 | if (name && strcmp(name, "_") != 0) { |
| 3802 | cbm_scope_bind(ctx->current_scope, name, type); |
| 3803 | } |
| 3804 | return; |
| 3805 | } |
| 3806 | if (strcmp(kind, "captured_pattern") == 0) { |
| 3807 | /* name @ subpattern */ |
| 3808 | TSNode name_node = ts_node_child_by_field_name(pattern, "name", 4); |
| 3809 | if (!ts_node_is_null(name_node)) { |
| 3810 | char *name = rust_node_text(ctx, name_node); |
| 3811 | if (name && strcmp(name, "_") != 0) { |
| 3812 | cbm_scope_bind(ctx->current_scope, name, type); |
| 3813 | } |
| 3814 | } |
| 3815 | TSNode sub = ts_node_child_by_field_name(pattern, "pattern", 7); |
| 3816 | if (!ts_node_is_null(sub)) |
| 3817 | rust_bind_pattern(ctx, sub, type); |
| 3818 | return; |
| 3819 | } |
| 3820 | if (strcmp(kind, "ref_pattern") == 0 || strcmp(kind, "mut_pattern") == 0 || |
| 3821 | strcmp(kind, "reference_pattern") == 0) { |
| 3822 | if (ts_node_named_child_count(pattern) > 0) { |
| 3823 | rust_bind_pattern(ctx, ts_node_named_child(pattern, 0), type); |
| 3824 | } |
| 3825 | return; |
| 3826 | } |
| 3827 | if (strcmp(kind, "tuple_pattern") == 0) { |
| 3828 | const CBMType *base = type; |
| 3829 | while (base && base->kind == CBM_TYPE_REFERENCE) |
| 3830 | base = base->data.reference.elem; |
| 3831 | uint32_t nc = ts_node_named_child_count(pattern); |
| 3832 | for (uint32_t i = 0; i < nc; i++) { |
| 3833 | const CBMType *elem_t = cbm_type_unknown(); |
| 3834 | if (base && base->kind == CBM_TYPE_TUPLE && (int)i < base->data.tuple.count) { |
| 3835 | elem_t = base->data.tuple.elems[i]; |
| 3836 | } |
| 3837 | rust_bind_pattern(ctx, ts_node_named_child(pattern, i), elem_t); |
| 3838 | } |
| 3839 | return; |
| 3840 | } |
| 3841 | if (strcmp(kind, "tuple_struct_pattern") == 0) { |
| 3842 | /* Some(x), Ok(x), Err(e) — peel one Option/Result/template. */ |
| 3843 | const CBMType *base = type; |
| 3844 | while (base && base->kind == CBM_TYPE_REFERENCE) |
| 3845 | base = base->data.reference.elem; |
| 3846 | const CBMType *inner = cbm_type_unknown(); |
| 3847 | if (base && base->kind == CBM_TYPE_TEMPLATE && base->data.template_type.arg_count > 0) { |
| 3848 | inner = base->data.template_type.template_args[0]; |
| 3849 | } |
| 3850 | uint32_t nc = ts_node_named_child_count(pattern); |
| 3851 | /* First named child is the path; subsequent are sub-patterns. */ |
no test coverage detected