(&mut self, node: Node<'t>)
| 858 | } |
| 859 | |
| 860 | fn extract_import(&mut self, node: Node<'t>) { |
| 861 | let kind = node.kind(); |
| 862 | let import_text = self.text(node).trim().to_string(); |
| 863 | let imports_kind = edge_kind_index("imports").unwrap(); |
| 864 | |
| 865 | if matches!( |
| 866 | kind, |
| 867 | "include_expression" | "include_once_expression" | "require_expression" |
| 868 | | "require_once_expression" |
| 869 | ) { |
| 870 | // phpStaticIncludePath: static string literals only; dynamic |
| 871 | // forms (`__DIR__ . '/x'`, interpolation) emit NOTHING. |
| 872 | let mut arg = node.named_child(0); |
| 873 | if let Some(a) = arg { |
| 874 | if a.kind() == "parenthesized_expression" { |
| 875 | arg = a.named_child(0); |
| 876 | } |
| 877 | } |
| 878 | let Some(arg) = arg else { return }; |
| 879 | if !matches!(arg.kind(), "string" | "encapsed_string") { |
| 880 | return; |
| 881 | } |
| 882 | let mut content: Option<Node> = None; |
| 883 | for i in 0..arg.named_child_count() { |
| 884 | let Some(c) = arg.named_child(i) else { continue }; |
| 885 | if c.kind() != "string_content" { |
| 886 | return; // interpolation/escape → not a static path |
| 887 | } |
| 888 | if content.is_none() { |
| 889 | content = Some(c); |
| 890 | } |
| 891 | } |
| 892 | let Some(content) = content else { return }; |
| 893 | let module_name = self.text(content).to_string(); |
| 894 | if module_name.is_empty() { |
| 895 | return; |
| 896 | } |
| 897 | self.create_node( |
| 898 | "import", |
| 899 | &module_name, |
| 900 | node, |
| 901 | Extra { signature: Some(import_text), ..Extra::default() }, |
| 902 | ); |
| 903 | let parent = self.top_row(); |
| 904 | self.push_ref_at(parent, &module_name.clone(), imports_kind, node); |
| 905 | return; |
| 906 | } |
| 907 | |
| 908 | // namespace_use_declaration. |
| 909 | let ns_prefix = (0..node.named_child_count()) |
| 910 | .filter_map(|i| node.named_child(i)) |
| 911 | .find(|c| c.kind() == "namespace_name"); |
| 912 | let use_group = (0..node.named_child_count()) |
| 913 | .filter_map(|i| node.named_child(i)) |
| 914 | .find(|c| c.kind() == "namespace_use_group"); |
| 915 | if let (Some(ns_prefix), Some(use_group)) = (ns_prefix, use_group) { |
| 916 | // Grouped `use A\{B, C as D, Sub\E}` — hook declines, the inline |
| 917 | // branch emits per-member nodes named `A\B` (first `name` child = |
no test coverage detected