Resolve exception name from the first meaningful child of a throw/raise node.
| 39 | |
| 40 | // Resolve exception name from the first meaningful child of a throw/raise node. |
| 41 | static char *resolve_exception_name(CBMArena *a, TSNode throw_node, const char *source) { |
| 42 | uint32_t nc = ts_node_child_count(throw_node); |
| 43 | for (uint32_t i = 0; i < nc; i++) { |
| 44 | TSNode child = ts_node_child(throw_node, i); |
| 45 | const char *ck = ts_node_type(child); |
| 46 | if (strcmp(ck, "raise") == 0 || strcmp(ck, "throw") == 0) { |
| 47 | continue; |
| 48 | } |
| 49 | if (ck[0] == ';' || ck[0] == '(' || ck[0] == ')') { |
| 50 | continue; |
| 51 | } |
| 52 | |
| 53 | if (strcmp(ck, "call") == 0 || strcmp(ck, "call_expression") == 0 || |
| 54 | strcmp(ck, "new_expression") == 0 || strcmp(ck, "object_creation_expression") == 0 || |
| 55 | strcmp(ck, "instance_expression") == 0) { |
| 56 | TSNode fn = ts_node_child_by_field_name(child, TS_FIELD("function")); |
| 57 | if (ts_node_is_null(fn)) { |
| 58 | fn = ts_node_child_by_field_name(child, "constructor", FIELD_LEN_CONSTRUCTOR); |
| 59 | } |
| 60 | if (ts_node_is_null(fn)) { |
| 61 | fn = ts_node_child_by_field_name(child, TS_FIELD("type")); |
| 62 | } |
| 63 | if (ts_node_is_null(fn) && ts_node_named_child_count(child) > 0) { |
| 64 | fn = ts_node_named_child(child, 0); |
| 65 | } |
| 66 | if (!ts_node_is_null(fn)) { |
| 67 | return cbm_node_text(a, fn, source); |
| 68 | } |
| 69 | } else { |
| 70 | return cbm_node_text(a, child, source); |
| 71 | } |
| 72 | break; |
| 73 | } |
| 74 | return NULL; |
| 75 | } |
| 76 | |
| 77 | // Extract exception types from a Java-style throws clause. |
| 78 | static void extract_throws_clause(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec *spec, |
no test coverage detected