| 2758 | } |
| 2759 | |
| 2760 | static void collect_use_declaration(PHPLSPContext *ctx, TSNode use_decl) { |
| 2761 | /* Determine kind: function / const / class (default). */ |
| 2762 | int kind = CBM_PHP_USE_CLASS; |
| 2763 | uint32_t nc = ts_node_child_count(use_decl); |
| 2764 | /* tree-sitter-php emits `function` or `const` keyword children. */ |
| 2765 | for (uint32_t i = 0; i < nc; i++) { |
| 2766 | TSNode c = ts_node_child(use_decl, i); |
| 2767 | if (ts_node_is_null(c)) |
| 2768 | continue; |
| 2769 | const char *k = ts_node_type(c); |
| 2770 | if (strcmp(k, "function") == 0) |
| 2771 | kind = CBM_PHP_USE_FUNCTION; |
| 2772 | if (strcmp(k, "const") == 0) |
| 2773 | kind = CBM_PHP_USE_CONST; |
| 2774 | } |
| 2775 | for (uint32_t i = 0; i < nc; i++) { |
| 2776 | TSNode c = ts_node_child(use_decl, i); |
| 2777 | if (ts_node_is_null(c) || !ts_node_is_named(c)) |
| 2778 | continue; |
| 2779 | const char *k = ts_node_type(c); |
| 2780 | if (strcmp(k, "namespace_use_clause") == 0) { |
| 2781 | collect_use_clause(ctx, c, kind); |
| 2782 | } else if (strcmp(k, "namespace_use_group") == 0) { |
| 2783 | /* use App\\{Foo, Bar as B}; — recurse into clauses inside. */ |
| 2784 | uint32_t gc = ts_node_child_count(c); |
| 2785 | for (uint32_t j = 0; j < gc; j++) { |
| 2786 | TSNode gch = ts_node_child(c, j); |
| 2787 | if (!ts_node_is_null(gch) && ts_node_is_named(gch) && |
| 2788 | strcmp(ts_node_type(gch), "namespace_use_clause") == 0) { |
| 2789 | collect_use_clause(ctx, gch, kind); |
| 2790 | } |
| 2791 | } |
| 2792 | } |
| 2793 | } |
| 2794 | } |
| 2795 | |
| 2796 | static void set_namespace_from_decl(PHPLSPContext *ctx, TSNode ns_decl) { |
| 2797 | uint32_t nc = ts_node_child_count(ns_decl); |
no test coverage detected