Extract exception types from a Java-style throws clause.
| 76 | |
| 77 | // Extract exception types from a Java-style throws clause. |
| 78 | static void extract_throws_clause(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec *spec, |
| 79 | const char *func_qn) { |
| 80 | if (!spec->throws_clause_field || !spec->throws_clause_field[0]) { |
| 81 | return; |
| 82 | } |
| 83 | const char *kind = ts_node_type(node); |
| 84 | if (strcmp(kind, "method_declaration") != 0 && strcmp(kind, "constructor_declaration") != 0) { |
| 85 | return; |
| 86 | } |
| 87 | TSNode throws_clause = ts_node_child_by_field_name(node, spec->throws_clause_field, |
| 88 | (uint32_t)strlen(spec->throws_clause_field)); |
| 89 | if (ts_node_is_null(throws_clause)) { |
| 90 | return; |
| 91 | } |
| 92 | uint32_t nc = ts_node_child_count(throws_clause); |
| 93 | for (uint32_t i = 0; i < nc; i++) { |
| 94 | TSNode child = ts_node_child(throws_clause, i); |
| 95 | const char *ck = ts_node_type(child); |
| 96 | if (strcmp(ck, "type_identifier") == 0 || strcmp(ck, "identifier") == 0 || |
| 97 | strcmp(ck, "scoped_type_identifier") == 0) { |
| 98 | char *exc = cbm_node_text(ctx->arena, child, ctx->source); |
| 99 | if (exc && exc[0]) { |
| 100 | CBMThrow thr = {.exception_name = exc, .enclosing_func_qn = func_qn}; |
| 101 | cbm_throws_push(&ctx->result->throws, ctx->arena, thr); |
| 102 | } |
| 103 | } |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | // Process a single node for throw extraction (called from iterative walker). |
| 108 | static void process_throw_node(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec *spec) { |
no test coverage detected