diff --git a/internal/cbm/extract_imports.c b/internal/cbm/extract_imports.c index 9573dad..ae6c67c 100644 --- a/internal/cbm/extract_imports.c +++ b/internal/cbm/extract_imports.c @@ -575,9 +575,18 @@ static void parse_lua_imports(CBMExtractCtx *ctx) { static void parse_generic_imports(CBMExtractCtx *ctx, const char *node_type) { CBMArena *a = ctx->arena; - uint32_t count = ts_node_child_count(ctx->root); - for (uint32_t i = 0; i < count; i++) { - TSNode node = ts_node_child(ctx->root, i); + /* Use TSTreeCursor for O(1)-per-step sibling traversal. + * ts_node_child(root, i) and ts_node_next_sibling() both call + * ts_node_child_with_descendant() internally, making naive iteration + * O(N²) on roots with thousands of children (e.g. generated .d.ts files). + * ts_tree_cursor_goto_next_sibling() maintains cursor state and is O(1). */ + TSTreeCursor cursor = ts_tree_cursor_new(ctx->root); + if (!ts_tree_cursor_goto_first_child(&cursor)) { + ts_tree_cursor_delete(&cursor); + return; + } + do { + TSNode node = ts_tree_cursor_current_node(&cursor); if (strcmp(ts_node_type(node), node_type) != 0) { continue; } @@ -616,7 +625,8 @@ static void parse_generic_imports(CBMExtractCtx *ctx, const char *node_type) { } } } - } + } while (ts_tree_cursor_goto_next_sibling(&cursor)); + ts_tree_cursor_delete(&cursor); } // --- Wolfram imports ---