extractCall — the Java method_invocation paths.
(&mut self, node: Node<'t>)
| 816 | |
| 817 | /// extractCall — the Java method_invocation paths. |
| 818 | fn extract_call(&mut self, node: Node<'t>) { |
| 819 | if self.stack.is_empty() { |
| 820 | return; |
| 821 | } |
| 822 | let caller = self.top_row(); |
| 823 | let name_field = node.child_by_field_name("name"); |
| 824 | let object_field = node |
| 825 | .child_by_field_name("object") |
| 826 | .or_else(|| node.child_by_field_name("scope")); |
| 827 | |
| 828 | let mut callee_name = String::new(); |
| 829 | if let (Some(name_field), Some(object_field)) = (name_field, object_field) { |
| 830 | let method_name = self.text(name_field); |
| 831 | |
| 832 | // Static-factory / fluent chain: `Foo.getInstance().bar()` → |
| 833 | // `<inner-receiver>.<inner-method>().<method>` (#645/#608). |
| 834 | if !method_name.is_empty() && object_field.kind() == "method_invocation" { |
| 835 | let inner_obj = object_field.child_by_field_name("object"); |
| 836 | let inner_name = object_field.child_by_field_name("name"); |
| 837 | if let (Some(io), Some(inm)) = (inner_obj, inner_name) { |
| 838 | let callee = format!("{}.{}().{}", self.text(io), self.text(inm), method_name); |
| 839 | self.push_ref_at(caller, &callee, edge_kind_index("calls").unwrap(), node); |
| 840 | return; |
| 841 | } |
| 842 | } |
| 843 | |
| 844 | // `this.userbo.toLogin2()` — unwrap the field after `this.`. |
| 845 | let receiver_name = if object_field.kind() == "field_access" { |
| 846 | let inner = object_field.child_by_field_name("object"); |
| 847 | let fld = object_field.child_by_field_name("field"); |
| 848 | match (inner, fld) { |
| 849 | (Some(inner), Some(fld)) |
| 850 | if matches!(inner.kind(), "this" | "this_expression") => |
| 851 | { |
| 852 | self.text(fld).to_string() |
| 853 | } |
| 854 | _ => self.text(object_field).to_string(), |
| 855 | } |
| 856 | } else { |
| 857 | self.text(object_field).to_string() |
| 858 | }; |
| 859 | let receiver_name = receiver_name.strip_prefix('$').unwrap_or(&receiver_name); |
| 860 | |
| 861 | if !method_name.is_empty() { |
| 862 | if matches!(receiver_name, "self" | "this" | "cls" | "super" | "parent" | "static") { |
| 863 | callee_name = method_name.to_string(); |
| 864 | } else { |
| 865 | callee_name = format!("{receiver_name}.{method_name}"); |
| 866 | } |
| 867 | } |
| 868 | } else { |
| 869 | // Bare call `foo()` — the generic tail: function field ?? first child. |
| 870 | let func = node |
| 871 | .child_by_field_name("function") |
| 872 | .or_else(|| node.named_child(0)); |
| 873 | if let Some(func) = func { |
| 874 | callee_name = self.text(func).to_string(); |
| 875 | } |
no test coverage detected