extractField — the php property_element branch (2077-2104): one `field` node per element, `$` re-added in the signature only, then RETURN — no decorators, no type-annotation refs from fields.
(&mut self, node: Node<'t>)
| 790 | /// node per element, `$` re-added in the signature only, then RETURN — no |
| 791 | /// decorators, no type-annotation refs from fields. |
| 792 | fn extract_field(&mut self, node: Node<'t>) { |
| 793 | let docstring = preceding_docstring(node, self.src); |
| 794 | let visibility = Some(self.visibility_of(node)); |
| 795 | let is_static = Some(self.is_static(node)); |
| 796 | |
| 797 | let prop_elements: Vec<Node> = (0..node.named_child_count()) |
| 798 | .filter_map(|i| node.named_child(i)) |
| 799 | .filter(|c| c.kind() == "property_element") |
| 800 | .collect(); |
| 801 | if prop_elements.is_empty() { |
| 802 | // The declarator/bare fallbacks find nothing on php shapes. |
| 803 | return; |
| 804 | } |
| 805 | // The type node: first namedChild that isn't a modifier or element. |
| 806 | // QUIRK: final_modifier/abstract_modifier are NOT excluded — a |
| 807 | // `final public Foo $x` takes `final` as the type text. PRESERVE. |
| 808 | let type_node = (0..node.named_child_count()) |
| 809 | .filter_map(|i| node.named_child(i)) |
| 810 | .find(|c| { |
| 811 | !matches!( |
| 812 | c.kind(), |
| 813 | "visibility_modifier" | "static_modifier" | "readonly_modifier" |
| 814 | | "property_element" | "var_modifier" |
| 815 | ) |
| 816 | }); |
| 817 | let type_text = type_node.map(|t| self.text(t).to_string()); |
| 818 | |
| 819 | for elem in prop_elements { |
| 820 | let var_name = (0..elem.named_child_count()) |
| 821 | .filter_map(|i| elem.named_child(i)) |
| 822 | .find(|c| c.kind() == "variable_name"); |
| 823 | let Some(var_name) = var_name else { continue }; |
| 824 | let name_node = (0..var_name.named_child_count()) |
| 825 | .filter_map(|i| var_name.named_child(i)) |
| 826 | .find(|c| c.kind() == "name"); |
| 827 | let Some(name_node) = name_node else { continue }; |
| 828 | let name = self.text(name_node).to_string(); |
| 829 | let signature = match &type_text { |
| 830 | Some(t) => format!("{t} ${name}"), |
| 831 | None => format!("${name}"), |
| 832 | }; |
| 833 | self.create_node( |
| 834 | "field", |
| 835 | &name, |
| 836 | elem, |
| 837 | Extra { |
| 838 | docstring: docstring.clone(), |
| 839 | signature: Some(signature), |
| 840 | visibility, |
| 841 | is_static, |
| 842 | ..Extra::default() |
| 843 | }, |
| 844 | ); |
| 845 | } |
| 846 | } |
| 847 | |
| 848 | // --- imports ------------------------------------------------------------------- |
| 849 |
no test coverage detected