(&mut self, node: Node<'t>)
| 1159 | } |
| 1160 | |
| 1161 | pub(super) fn extract_call(&mut self, node: Node<'t>) { |
| 1162 | if self.stack.is_empty() { |
| 1163 | return; |
| 1164 | } |
| 1165 | let func = node |
| 1166 | .child_by_field_name("function") |
| 1167 | .or_else(|| node.named_child(0)); |
| 1168 | let mut callee_name = String::new(); |
| 1169 | |
| 1170 | if let Some(func) = func { |
| 1171 | if func.kind() == "member_expression" { |
| 1172 | let property = func |
| 1173 | .child_by_field_name("property") |
| 1174 | .or_else(|| func.child_by_field_name("field")) |
| 1175 | .or_else(|| func.named_child(1)); |
| 1176 | if let Some(property) = property { |
| 1177 | let method_name = self.text(property); |
| 1178 | let receiver = func |
| 1179 | .child_by_field_name("object") |
| 1180 | .or_else(|| func.child_by_field_name("operand")) |
| 1181 | .or_else(|| func.child_by_field_name("argument")) |
| 1182 | .or_else(|| func.named_child(0)) |
| 1183 | // Look through `(x)`, `x!`, `(x as T)`, `(await f())` |
| 1184 | // (mirrors peelTsJsReceiver). |
| 1185 | .map(peel_receiver); |
| 1186 | // Literal receivers call builtins, never project symbols (#1230). |
| 1187 | if let Some(r) = receiver { |
| 1188 | if is_literal_receiver(r.kind()) { |
| 1189 | return; |
| 1190 | } |
| 1191 | } |
| 1192 | let recv_ident = receiver.filter(|r| { |
| 1193 | matches!(r.kind(), "identifier" | "simple_identifier" | "field_identifier") |
| 1194 | }); |
| 1195 | if let Some(r) = recv_ident { |
| 1196 | let receiver_name = self.text(r); |
| 1197 | if !matches!(receiver_name, "self" | "this" | "cls" | "super") { |
| 1198 | callee_name = format!("{receiver_name}.{method_name}"); |
| 1199 | } else { |
| 1200 | callee_name = method_name.to_string(); |
| 1201 | } |
| 1202 | } else if receiver.is_some_and(|r| self.is_unresolved_member_chain(r)) { |
| 1203 | // Retain the call site for effects without guessing a |
| 1204 | // project method. Mirrors the TS extraction path. |
| 1205 | let chain = self.text(func).replace("?.", "."); |
| 1206 | let Some(chain) = Self::plain_member_name(&chain) else { return }; |
| 1207 | callee_name = chain; |
| 1208 | } else if let Some(field) = receiver.and_then(|r| self.this_field_of(r)) { |
| 1209 | // `this.<field>.<method>()` — keep the field so the |
| 1210 | // resolver can read its declared type (#1496). Mirrors |
| 1211 | // TreeSitterExtractor.extractCall. |
| 1212 | callee_name = format!("this.{field}.{method_name}"); |
| 1213 | } else if let Some(r) = receiver.filter(|r| r.kind() == "call_expression") { |
| 1214 | // Call receiver — `make().run()` (#1683): keep the inner |
| 1215 | // callee as `<inner>().<method>`, or emit nothing when it |
| 1216 | // is not a plain name / member chain. Mirrors |
| 1217 | // TreeSitterExtractor.extractCall. |
| 1218 | let Some(inner) = self.plain_inner_callee(r) else { return }; |
no test coverage detected