| 2552 | } |
| 2553 | |
| 2554 | static void collect_use_declaration(PHPLSPContext *ctx, TSNode use_decl) { |
| 2555 | /* Determine kind: function / const / class (default). */ |
| 2556 | int kind = CBM_PHP_USE_CLASS; |
| 2557 | uint32_t nc = ts_node_child_count(use_decl); |
| 2558 | /* tree-sitter-php emits `function` or `const` keyword children. */ |
| 2559 | for (uint32_t i = 0; i < nc; i++) { |
| 2560 | TSNode c = ts_node_child(use_decl, i); |
| 2561 | if (ts_node_is_null(c)) |
| 2562 | continue; |
| 2563 | const char *k = ts_node_type(c); |
| 2564 | if (strcmp(k, "function") == 0) |
| 2565 | kind = CBM_PHP_USE_FUNCTION; |
| 2566 | if (strcmp(k, "const") == 0) |
| 2567 | kind = CBM_PHP_USE_CONST; |
| 2568 | } |
| 2569 | for (uint32_t i = 0; i < nc; i++) { |
| 2570 | TSNode c = ts_node_child(use_decl, i); |
| 2571 | if (ts_node_is_null(c) || !ts_node_is_named(c)) |
| 2572 | continue; |
| 2573 | const char *k = ts_node_type(c); |
| 2574 | if (strcmp(k, "namespace_use_clause") == 0) { |
| 2575 | collect_use_clause(ctx, c, kind); |
| 2576 | } else if (strcmp(k, "namespace_use_group") == 0) { |
| 2577 | /* use App\\{Foo, Bar as B}; — recurse into clauses inside. */ |
| 2578 | uint32_t gc = ts_node_child_count(c); |
| 2579 | for (uint32_t j = 0; j < gc; j++) { |
| 2580 | TSNode gch = ts_node_child(c, j); |
| 2581 | if (!ts_node_is_null(gch) && ts_node_is_named(gch) && |
| 2582 | strcmp(ts_node_type(gch), "namespace_use_clause") == 0) { |
| 2583 | collect_use_clause(ctx, gch, kind); |
| 2584 | } |
| 2585 | } |
| 2586 | } |
| 2587 | } |
| 2588 | } |
| 2589 | |
| 2590 | static void set_namespace_from_decl(PHPLSPContext *ctx, TSNode ns_decl) { |
| 2591 | uint32_t nc = ts_node_child_count(ns_decl); |
no test coverage detected