Extract all arguments from a call expression into call->args[]. */
| 1335 | |
| 1336 | /* Extract all arguments from a call expression into call->args[]. */ |
| 1337 | static void extract_call_args(CBMExtractCtx *ctx, TSNode args, CBMCall *call) { |
| 1338 | uint32_t argc = ts_node_named_child_count(args); |
| 1339 | int positional_idx = 0; |
| 1340 | for (uint32_t ai = 0; ai < argc && call->arg_count < CBM_MAX_CALL_ARGS; ai++) { |
| 1341 | TSNode arg_node = ts_node_named_child(args, ai); |
| 1342 | const char *ak = ts_node_type(arg_node); |
| 1343 | CBMCallArg *ca = &call->args[call->arg_count]; |
| 1344 | memset(ca, 0, sizeof(*ca)); |
| 1345 | |
| 1346 | if (strcmp(ak, "keyword_argument") == 0 || strcmp(ak, "pair") == 0) { |
| 1347 | process_keyword_arg(ctx, arg_node, ca); |
| 1348 | ca->index = positional_idx++; |
| 1349 | call->arg_count++; |
| 1350 | } else if (strcmp(ak, "list_splat") == 0 || strcmp(ak, "dictionary_splat") == 0 || |
| 1351 | strcmp(ak, "spread_element") == 0) { |
| 1352 | positional_idx++; |
| 1353 | } else { |
| 1354 | ca->expr = cbm_node_text(ctx->arena, arg_node, ctx->source); |
| 1355 | ca->index = positional_idx++; |
| 1356 | if (is_string_like(ak) && ca->expr) { |
| 1357 | ca->value = strip_quotes(ctx->arena, ca->expr); |
| 1358 | } else if (strcmp(ak, "identifier") == 0 && ca->expr) { |
| 1359 | ca->value = lookup_string_constant(ctx, ca->expr); |
| 1360 | } |
| 1361 | call->arg_count++; |
| 1362 | } |
| 1363 | } |
| 1364 | } |
| 1365 | |
| 1366 | // Check if a keyword name matches URL or topic patterns. |
| 1367 | static bool is_url_or_topic_keyword(const char *key) { |
no test coverage detected