| 1244 | /* ── parameter binding ──────────────────────────────────────────── */ |
| 1245 | |
| 1246 | static void cs_bind_parameters(CSLSPContext *ctx, TSNode params_node, bool is_extension) { |
| 1247 | if (ts_node_is_null(params_node)) return; |
| 1248 | uint32_t nc = ts_node_child_count(params_node); |
| 1249 | int idx = 0; |
| 1250 | for (uint32_t i = 0; i < nc; i++) { |
| 1251 | TSNode c = ts_node_child(params_node, i); |
| 1252 | if (ts_node_is_null(c) || !ts_node_is_named(c)) continue; |
| 1253 | const char *k = ts_node_type(c); |
| 1254 | if (strcmp(k, "parameter") != 0) continue; |
| 1255 | |
| 1256 | /* Detect `this` modifier (extension methods). */ |
| 1257 | bool has_this = is_extension && (idx == 0); |
| 1258 | TSNode tnode = ts_node_child_by_field_name(c, "type", 4); |
| 1259 | TSNode nnode = ts_node_child_by_field_name(c, "name", 4); |
| 1260 | if (ts_node_is_null(tnode) || ts_node_is_null(nnode)) { |
| 1261 | uint32_t pc = ts_node_child_count(c); |
| 1262 | for (uint32_t j = 0; j < pc; j++) { |
| 1263 | TSNode cc = ts_node_child(c, j); |
| 1264 | if (ts_node_is_null(cc) || !ts_node_is_named(cc)) continue; |
| 1265 | const char *ck = ts_node_type(cc); |
| 1266 | if (strcmp(ck, "identifier") == 0 && ts_node_is_null(nnode)) nnode = cc; |
| 1267 | else if (ts_node_is_null(tnode) && strcmp(ck, "identifier") != 0) tnode = cc; |
| 1268 | } |
| 1269 | } |
| 1270 | if (ts_node_is_null(nnode)) { |
| 1271 | idx++; |
| 1272 | continue; |
| 1273 | } |
| 1274 | char *pname = cs_node_text(ctx, nnode); |
| 1275 | if (!pname) { |
| 1276 | idx++; |
| 1277 | continue; |
| 1278 | } |
| 1279 | const CBMType *ptype = cbm_type_unknown(); |
| 1280 | if (!ts_node_is_null(tnode)) ptype = cs_parse_type_node(ctx, tnode); |
| 1281 | cbm_scope_bind(ctx->current_scope, pname, ptype); |
| 1282 | (void)has_this; |
| 1283 | idx++; |
| 1284 | } |
| 1285 | } |
| 1286 | |
| 1287 | /* ── statement processing ───────────────────────────────────────── */ |
| 1288 |
no test coverage detected