| 758 | // function_call: require("X") |
| 759 | |
| 760 | static void parse_lua_imports(CBMExtractCtx *ctx) { |
| 761 | CBMArena *a = ctx->arena; |
| 762 | |
| 763 | TSTreeCursor cursor = ts_tree_cursor_new(ctx->root); |
| 764 | if (!ts_tree_cursor_goto_first_child(&cursor)) { |
| 765 | ts_tree_cursor_delete(&cursor); |
| 766 | return; |
| 767 | } |
| 768 | do { |
| 769 | TSNode node = ts_tree_cursor_current_node(&cursor); |
| 770 | // Lua: local X = require("Y") → assignment_statement or variable_declaration |
| 771 | // containing function_call(require, "Y") |
| 772 | char *text = cbm_node_text(a, node, ctx->source); |
| 773 | if (!text) { |
| 774 | continue; |
| 775 | } |
| 776 | if (strstr(text, "require") == NULL) { |
| 777 | continue; |
| 778 | } |
| 779 | |
| 780 | // Simple extraction: find require("...") pattern in node text |
| 781 | const char *req = strstr(text, "require"); |
| 782 | if (!req) { |
| 783 | continue; |
| 784 | } |
| 785 | |
| 786 | // Find the string argument |
| 787 | const char *open = strchr(req, '('); |
| 788 | if (!open) { |
| 789 | open = strchr(req, '"'); |
| 790 | } |
| 791 | if (!open) { |
| 792 | open = strchr(req, '\''); |
| 793 | } |
| 794 | if (!open) { |
| 795 | continue; |
| 796 | } |
| 797 | |
| 798 | const char *q1 = strchr(open, '"'); |
| 799 | const char *q2 = strchr(open, '\''); |
| 800 | if (!q1 && !q2) { |
| 801 | continue; |
| 802 | } |
| 803 | const char *start = q1 && (!q2 || q1 < q2) ? q1 : q2; |
| 804 | char delim = *start; |
| 805 | start++; |
| 806 | const char *end = strchr(start, delim); |
| 807 | if (!end) { |
| 808 | continue; |
| 809 | } |
| 810 | |
| 811 | char *mod = cbm_arena_strndup(a, start, (size_t)(end - start)); |
| 812 | CBMImport imp = {.local_name = path_last(a, mod), .module_path = mod}; |
| 813 | cbm_imports_push(&ctx->result->imports, a, imp); |
| 814 | } while (ts_tree_cursor_goto_next_sibling(&cursor)); |
| 815 | ts_tree_cursor_delete(&cursor); |
| 816 | } |
| 817 |
no test coverage detected