Bind a variable_declarator: `let x: T = init` / `const x = init` / `var x = ...`.
| 2006 | |
| 2007 | // Bind a variable_declarator: `let x: T = init` / `const x = init` / `var x = ...`. |
| 2008 | static void bind_variable_declarator(TSLSPContext *ctx, TSNode decl) { |
| 2009 | TSNode name = ts_node_child_by_field_name(decl, "name", TS_LSP_FIELD_LEN("name")); |
| 2010 | TSNode tann = ts_node_child_by_field_name(decl, "type", TS_LSP_FIELD_LEN("type")); |
| 2011 | TSNode value = ts_node_child_by_field_name(decl, "value", TS_LSP_FIELD_LEN("value")); |
| 2012 | if (ts_node_is_null(name)) |
| 2013 | return; |
| 2014 | |
| 2015 | const CBMType *declared = NULL; |
| 2016 | if (!ts_node_is_null(tann)) { |
| 2017 | // type_annotation contains the actual type as a named child. |
| 2018 | TSNode tch = ts_node_named_child(tann, 0); |
| 2019 | if (!ts_node_is_null(tch)) |
| 2020 | declared = ts_parse_type_node(ctx, tch); |
| 2021 | } |
| 2022 | const CBMType *inferred = |
| 2023 | ts_node_is_null(value) ? cbm_type_unknown() : ts_eval_expr_type(ctx, value); |
| 2024 | const CBMType *bound = (declared && !cbm_type_is_unknown(declared)) ? declared : inferred; |
| 2025 | |
| 2026 | if (node_kind_is(name, "identifier")) { |
| 2027 | char *nm = node_text(ctx, name); |
| 2028 | if (nm) |
| 2029 | cbm_scope_bind(ctx->current_scope, nm, bound); |
| 2030 | } else if (node_kind_is(name, "object_pattern")) { |
| 2031 | // Destructure object: `const { a, b } = obj` — bind a and b to obj.a and obj.b types. |
| 2032 | uint32_t nc = ts_node_named_child_count(name); |
| 2033 | for (uint32_t i = 0; i < nc; i++) { |
| 2034 | TSNode pn = ts_node_named_child(name, i); |
| 2035 | if (ts_node_is_null(pn)) |
| 2036 | continue; |
| 2037 | const char *pk = ts_node_type(pn); |
| 2038 | if (strcmp(pk, "shorthand_property_identifier_pattern") == 0) { |
| 2039 | char *pnm = node_text(ctx, pn); |
| 2040 | if (pnm) |
| 2041 | cbm_scope_bind(ctx->current_scope, pnm, lookup_member_type(ctx, bound, pnm)); |
| 2042 | } else if (strcmp(pk, "pair_pattern") == 0) { |
| 2043 | TSNode key = ts_node_child_by_field_name(pn, "key", TS_LSP_FIELD_LEN("key")); |
| 2044 | TSNode val = ts_node_child_by_field_name(pn, "value", TS_LSP_FIELD_LEN("value")); |
| 2045 | if (!ts_node_is_null(key) && !ts_node_is_null(val) && |
| 2046 | node_kind_is(val, "identifier")) { |
| 2047 | char *knm = node_text(ctx, key); |
| 2048 | char *vnm = node_text(ctx, val); |
| 2049 | if (knm && vnm) { |
| 2050 | cbm_scope_bind(ctx->current_scope, vnm, |
| 2051 | lookup_member_type(ctx, bound, knm)); |
| 2052 | } |
| 2053 | } |
| 2054 | } |
| 2055 | } |
| 2056 | } else if (node_kind_is(name, "array_pattern")) { |
| 2057 | // Destructure array / tuple: `const [a, b] = pair`. |
| 2058 | uint32_t nc = ts_node_named_child_count(name); |
| 2059 | for (uint32_t i = 0; i < nc; i++) { |
| 2060 | TSNode pn = ts_node_named_child(name, i); |
| 2061 | if (ts_node_is_null(pn) || !node_kind_is(pn, "identifier")) |
| 2062 | continue; |
| 2063 | char *pnm = node_text(ctx, pn); |
| 2064 | if (!pnm) |
| 2065 | continue; |
no test coverage detected