--- Helper: parse template parameter defaults ---
| 432 | |
| 433 | // --- Helper: parse template parameter defaults --- |
| 434 | static void c_parse_template_params(CLSPContext *ctx, TSNode template_decl) { |
| 435 | TSNode params = ts_node_child_by_field_name(template_decl, "parameters", 10); |
| 436 | if (ts_node_is_null(params)) |
| 437 | return; |
| 438 | |
| 439 | ctx->template_param_count = 0; |
| 440 | uint32_t nc = ts_node_named_child_count(params); |
| 441 | if (nc == 0) |
| 442 | return; |
| 443 | |
| 444 | const char **names = |
| 445 | (const char **)cbm_arena_alloc(ctx->arena, (nc + 1) * sizeof(const char *)); |
| 446 | const CBMType **defaults = |
| 447 | (const CBMType **)cbm_arena_alloc(ctx->arena, (nc + 1) * sizeof(const CBMType *)); |
| 448 | if (!names || !defaults) |
| 449 | return; |
| 450 | |
| 451 | int idx = 0; |
| 452 | for (uint32_t i = 0; i < nc && idx < 16; i++) { |
| 453 | TSNode param = ts_node_named_child(params, i); |
| 454 | if (ts_node_is_null(param)) |
| 455 | continue; |
| 456 | const char *pk = ts_node_type(param); |
| 457 | |
| 458 | // type_parameter_declaration: template<class T = int> |
| 459 | // optional_type_parameter_declaration: template<class T = Default> |
| 460 | if (strcmp(pk, "type_parameter_declaration") == 0 || |
| 461 | strcmp(pk, "optional_type_parameter_declaration") == 0) { |
| 462 | // Get parameter name |
| 463 | TSNode name_node = ts_node_child_by_field_name(param, "name", 4); |
| 464 | if (ts_node_is_null(name_node)) { |
| 465 | // Some grammars put the identifier as a direct child |
| 466 | for (uint32_t j = 0; j < ts_node_named_child_count(param); j++) { |
| 467 | TSNode ch = ts_node_named_child(param, j); |
| 468 | if (strcmp(ts_node_type(ch), "type_identifier") == 0 || |
| 469 | strcmp(ts_node_type(ch), "identifier") == 0) { |
| 470 | name_node = ch; |
| 471 | break; |
| 472 | } |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | char *pname = NULL; |
| 477 | if (!ts_node_is_null(name_node)) |
| 478 | pname = c_node_text(ctx, name_node); |
| 479 | if (!pname) |
| 480 | pname = cbm_arena_sprintf(ctx->arena, "T%d", idx); |
| 481 | |
| 482 | names[idx] = pname; |
| 483 | |
| 484 | // Get default type |
| 485 | TSNode default_node = ts_node_child_by_field_name(param, "default_type", 12); |
| 486 | if (ts_node_is_null(default_node)) { |
| 487 | // Try "default_value" field |
| 488 | default_node = ts_node_child_by_field_name(param, "default", 7); |
| 489 | } |
| 490 | if (!ts_node_is_null(default_node)) { |
| 491 | defaults[idx] = c_parse_type_node(ctx, default_node); |
no test coverage detected