extractCall — Go's generic-tail paths (selector_expression callees).
(&mut self, node: Node<'t>)
| 721 | |
| 722 | /// extractCall — Go's generic-tail paths (selector_expression callees). |
| 723 | fn extract_call(&mut self, node: Node<'t>) { |
| 724 | if self.stack.is_empty() { |
| 725 | return; |
| 726 | } |
| 727 | let func = node |
| 728 | .child_by_field_name("function") |
| 729 | .or_else(|| node.named_child(0)); |
| 730 | let mut callee_name = String::new(); |
| 731 | |
| 732 | if let Some(func) = func { |
| 733 | if func.kind() == "selector_expression" { |
| 734 | let property = func |
| 735 | .child_by_field_name("property") |
| 736 | .or_else(|| func.child_by_field_name("field")); |
| 737 | if let Some(property) = property { |
| 738 | let method_name = self.text(property); |
| 739 | let receiver = func |
| 740 | .child_by_field_name("object") |
| 741 | .or_else(|| func.child_by_field_name("operand")) |
| 742 | .or_else(|| func.child_by_field_name("argument")) |
| 743 | .or_else(|| func.named_child(0)); |
| 744 | if let Some(r) = receiver { |
| 745 | if is_literal_receiver(r.kind()) { |
| 746 | return; |
| 747 | } |
| 748 | } |
| 749 | if let Some(r) = receiver { |
| 750 | match r.kind() { |
| 751 | "identifier" | "simple_identifier" | "field_identifier" => { |
| 752 | let receiver_name = self.text(r); |
| 753 | if !matches!(receiver_name, "self" | "this" | "cls" | "super") { |
| 754 | callee_name = format!("{receiver_name}.{method_name}"); |
| 755 | } else { |
| 756 | callee_name = method_name.to_string(); |
| 757 | } |
| 758 | } |
| 759 | "call_expression" => { |
| 760 | // Bare package-level factory chain `New().Method()` |
| 761 | // re-encodes; instance chains keep the bare name. |
| 762 | let inner_fn = r.child_by_field_name("function"); |
| 763 | let reencode = |
| 764 | inner_fn.map(|f| f.kind() == "identifier").unwrap_or(false); |
| 765 | if reencode { |
| 766 | let inner: String = self |
| 767 | .text(inner_fn.unwrap()) |
| 768 | .replace("->", ".") |
| 769 | .chars() |
| 770 | .filter(|c| !c.is_whitespace()) |
| 771 | .collect(); |
| 772 | callee_name = format!("{inner}().{method_name}"); |
| 773 | } else { |
| 774 | callee_name = method_name.to_string(); |
| 775 | } |
| 776 | } |
| 777 | "selector_expression" => { |
| 778 | // 2-hop field chain `t.conn.Exec` (#1276). |
| 779 | let chain: String = self |
| 780 | .text(r) |
no test coverage detected