--- Helper: parse template parameter defaults ---
| 485 | |
| 486 | // --- Helper: parse template parameter defaults --- |
| 487 | static void c_parse_template_params(CLSPContext *ctx, TSNode template_decl) { |
| 488 | TSNode params = ts_node_child_by_field_name(template_decl, "parameters", 10); |
| 489 | if (ts_node_is_null(params)) |
| 490 | return; |
| 491 | |
| 492 | ctx->template_param_count = 0; |
| 493 | uint32_t nc = ts_node_named_child_count(params); |
| 494 | if (nc == 0) |
| 495 | return; |
| 496 | |
| 497 | const char **names = |
| 498 | (const char **)cbm_arena_alloc(ctx->arena, (nc + 1) * sizeof(const char *)); |
| 499 | const CBMType **defaults = |
| 500 | (const CBMType **)cbm_arena_alloc(ctx->arena, (nc + 1) * sizeof(const CBMType *)); |
| 501 | if (!names || !defaults) |
| 502 | return; |
| 503 | |
| 504 | int idx = 0; |
| 505 | for (uint32_t i = 0; i < nc && idx < 16; i++) { |
| 506 | TSNode param = ts_node_named_child(params, i); |
| 507 | if (ts_node_is_null(param)) |
| 508 | continue; |
| 509 | const char *pk = ts_node_type(param); |
| 510 | |
| 511 | // type_parameter_declaration: template<class T = int> |
| 512 | // optional_type_parameter_declaration: template<class T = Default> |
| 513 | if (strcmp(pk, "type_parameter_declaration") == 0 || |
| 514 | strcmp(pk, "optional_type_parameter_declaration") == 0) { |
| 515 | // Get parameter name |
| 516 | TSNode name_node = ts_node_child_by_field_name(param, "name", 4); |
| 517 | if (ts_node_is_null(name_node)) { |
| 518 | // Some grammars put the identifier as a direct child |
| 519 | for (uint32_t j = 0; j < ts_node_named_child_count(param); j++) { |
| 520 | TSNode ch = ts_node_named_child(param, j); |
| 521 | if (strcmp(ts_node_type(ch), "type_identifier") == 0 || |
| 522 | strcmp(ts_node_type(ch), "identifier") == 0) { |
| 523 | name_node = ch; |
| 524 | break; |
| 525 | } |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | char *pname = NULL; |
| 530 | if (!ts_node_is_null(name_node)) |
| 531 | pname = c_node_text(ctx, name_node); |
| 532 | if (!pname) |
| 533 | pname = cbm_arena_sprintf(ctx->arena, "T%d", idx); |
| 534 | |
| 535 | names[idx] = pname; |
| 536 | |
| 537 | // Get default type |
| 538 | TSNode default_node = ts_node_child_by_field_name(param, "default_type", 12); |
| 539 | if (ts_node_is_null(default_node)) { |
| 540 | // Try "default_value" field |
| 541 | default_node = ts_node_child_by_field_name(param, "default", 7); |
| 542 | } |
| 543 | if (!ts_node_is_null(default_node)) { |
| 544 | defaults[idx] = c_parse_type_node(ctx, default_node); |
no test coverage detected