@@ -55,9 +55,13 @@ static const char *path_last(CBMArena *a, const char *path) {
5555static void parse_go_imports (CBMExtractCtx * ctx ) {
5656 CBMArena * a = ctx -> arena ;
5757
58- uint32_t root_count = ts_node_child_count (ctx -> root );
59- for (uint32_t i = 0 ; i < root_count ; i ++ ) {
60- TSNode decl = ts_node_child (ctx -> root , i );
58+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
59+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
60+ ts_tree_cursor_delete (& cursor );
61+ return ;
62+ }
63+ do {
64+ TSNode decl = ts_tree_cursor_current_node (& cursor );
6165 if (strcmp (ts_node_type (decl ), "import_declaration" ) != 0 ) {
6266 continue ;
6367 }
@@ -121,7 +125,8 @@ static void parse_go_imports(CBMExtractCtx *ctx) {
121125 }
122126 }
123127 }
124- }
128+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
129+ ts_tree_cursor_delete (& cursor );
125130}
126131
127132// --- Python imports ---
@@ -131,9 +136,13 @@ static void parse_go_imports(CBMExtractCtx *ctx) {
131136static void parse_python_imports (CBMExtractCtx * ctx ) {
132137 CBMArena * a = ctx -> arena ;
133138
134- uint32_t count = ts_node_child_count (ctx -> root );
135- for (uint32_t i = 0 ; i < count ; i ++ ) {
136- TSNode node = ts_node_child (ctx -> root , i );
139+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
140+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
141+ ts_tree_cursor_delete (& cursor );
142+ return ;
143+ }
144+ do {
145+ TSNode node = ts_tree_cursor_current_node (& cursor );
137146 const char * kind = ts_node_type (node );
138147
139148 if (strcmp (kind , "import_statement" ) == 0 ) {
@@ -227,7 +236,8 @@ static void parse_python_imports(CBMExtractCtx *ctx) {
227236 }
228237 }
229238 }
230- }
239+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
240+ ts_tree_cursor_delete (& cursor );
231241}
232242
233243// --- ES module imports (JS/TS/TSX) ---
@@ -347,9 +357,13 @@ static void parse_es_imports(CBMExtractCtx *ctx) {
347357static void parse_java_imports (CBMExtractCtx * ctx ) {
348358 CBMArena * a = ctx -> arena ;
349359
350- uint32_t count = ts_node_child_count (ctx -> root );
351- for (uint32_t i = 0 ; i < count ; i ++ ) {
352- TSNode node = ts_node_child (ctx -> root , i );
360+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
361+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
362+ ts_tree_cursor_delete (& cursor );
363+ return ;
364+ }
365+ do {
366+ TSNode node = ts_tree_cursor_current_node (& cursor );
353367 if (strcmp (ts_node_type (node ), "import_declaration" ) != 0 ) {
354368 continue ;
355369 }
@@ -368,7 +382,8 @@ static void parse_java_imports(CBMExtractCtx *ctx) {
368382 break ;
369383 }
370384 }
371- }
385+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
386+ ts_tree_cursor_delete (& cursor );
372387}
373388
374389// --- Rust imports ---
@@ -377,9 +392,13 @@ static void parse_java_imports(CBMExtractCtx *ctx) {
377392static void parse_rust_imports (CBMExtractCtx * ctx ) {
378393 CBMArena * a = ctx -> arena ;
379394
380- uint32_t count = ts_node_child_count (ctx -> root );
381- for (uint32_t i = 0 ; i < count ; i ++ ) {
382- TSNode node = ts_node_child (ctx -> root , i );
395+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
396+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
397+ ts_tree_cursor_delete (& cursor );
398+ return ;
399+ }
400+ do {
401+ TSNode node = ts_tree_cursor_current_node (& cursor );
383402 if (strcmp (ts_node_type (node ), "use_declaration" ) != 0 ) {
384403 continue ;
385404 }
@@ -399,7 +418,8 @@ static void parse_rust_imports(CBMExtractCtx *ctx) {
399418
400419 CBMImport imp = {.local_name = path_last (a , full ), .module_path = full };
401420 cbm_imports_push (& ctx -> result -> imports , a , imp );
402- }
421+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
422+ ts_tree_cursor_delete (& cursor );
403423}
404424
405425// --- C/C++ imports ---
@@ -408,9 +428,13 @@ static void parse_rust_imports(CBMExtractCtx *ctx) {
408428static void parse_c_imports (CBMExtractCtx * ctx ) {
409429 CBMArena * a = ctx -> arena ;
410430
411- uint32_t count = ts_node_child_count (ctx -> root );
412- for (uint32_t i = 0 ; i < count ; i ++ ) {
413- TSNode node = ts_node_child (ctx -> root , i );
431+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
432+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
433+ ts_tree_cursor_delete (& cursor );
434+ return ;
435+ }
436+ do {
437+ TSNode node = ts_tree_cursor_current_node (& cursor );
414438 const char * kind = ts_node_type (node );
415439 if (strcmp (kind , "preproc_include" ) != 0 && strcmp (kind , "preproc_import" ) != 0 ) {
416440 continue ;
@@ -447,7 +471,8 @@ static void parse_c_imports(CBMExtractCtx *ctx) {
447471
448472 CBMImport imp = {.local_name = path_last (a , path ), .module_path = path };
449473 cbm_imports_push (& ctx -> result -> imports , a , imp );
450- }
474+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
475+ ts_tree_cursor_delete (& cursor );
451476}
452477
453478// --- Ruby imports ---
@@ -458,9 +483,13 @@ static void parse_ruby_imports(CBMExtractCtx *ctx) {
458483
459484 // Walk for call nodes with "require" or "require_relative"
460485 // Simple: walk top-level children
461- uint32_t count = ts_node_child_count (ctx -> root );
462- for (uint32_t i = 0 ; i < count ; i ++ ) {
463- TSNode node = ts_node_child (ctx -> root , i );
486+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
487+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
488+ ts_tree_cursor_delete (& cursor );
489+ return ;
490+ }
491+ do {
492+ TSNode node = ts_tree_cursor_current_node (& cursor );
464493 const char * kind = ts_node_type (node );
465494 if (strcmp (kind , "call" ) != 0 && strcmp (kind , "command_call" ) != 0 ) {
466495 continue ;
@@ -511,7 +540,8 @@ static void parse_ruby_imports(CBMExtractCtx *ctx) {
511540
512541 CBMImport imp = {.local_name = path_last (a , arg_text ), .module_path = arg_text };
513542 cbm_imports_push (& ctx -> result -> imports , a , imp );
514- }
543+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
544+ ts_tree_cursor_delete (& cursor );
515545}
516546
517547// --- Lua imports ---
@@ -520,9 +550,13 @@ static void parse_ruby_imports(CBMExtractCtx *ctx) {
520550static void parse_lua_imports (CBMExtractCtx * ctx ) {
521551 CBMArena * a = ctx -> arena ;
522552
523- uint32_t count = ts_node_child_count (ctx -> root );
524- for (uint32_t i = 0 ; i < count ; i ++ ) {
525- TSNode node = ts_node_child (ctx -> root , i );
553+ TSTreeCursor cursor = ts_tree_cursor_new (ctx -> root );
554+ if (!ts_tree_cursor_goto_first_child (& cursor )) {
555+ ts_tree_cursor_delete (& cursor );
556+ return ;
557+ }
558+ do {
559+ TSNode node = ts_tree_cursor_current_node (& cursor );
526560 // Lua: local X = require("Y") → assignment_statement or variable_declaration
527561 // containing function_call(require, "Y")
528562 char * text = cbm_node_text (a , node , ctx -> source );
@@ -567,7 +601,8 @@ static void parse_lua_imports(CBMExtractCtx *ctx) {
567601 char * mod = cbm_arena_strndup (a , start , (size_t )(end - start ));
568602 CBMImport imp = {.local_name = path_last (a , mod ), .module_path = mod };
569603 cbm_imports_push (& ctx -> result -> imports , a , imp );
570- }
604+ } while (ts_tree_cursor_goto_next_sibling (& cursor ));
605+ ts_tree_cursor_delete (& cursor );
571606}
572607
573608// --- Generic import parsing for languages with simple import_declaration ---
0 commit comments