(node, caller_nid: str)
| 5053 | _JS_CLOSURE_TYPES = ("arrow_function", "function_expression") |
| 5054 | |
| 5055 | def walk_calls(node, caller_nid: str) -> None: |
| 5056 | if node.type in config.function_boundary_types: |
| 5057 | # JS/TS: an inline/returned closure not separately tracked in |
| 5058 | # function_bodies would otherwise drop its calls at this boundary. |
| 5059 | # Descend into it with the enclosing caller so `return () => |
| 5060 | # svc.doThing()` links to the caller (#1630). Tracked closures |
| 5061 | # (const-assigned arrows) are walked with their own nid — skip to |
| 5062 | # avoid double-counting. |
| 5063 | if (config.ts_module in ("tree_sitter_javascript", "tree_sitter_typescript") |
| 5064 | and node.type in _JS_CLOSURE_TYPES): |
| 5065 | body = node.child_by_field_name("body") |
| 5066 | if body is not None and id(body) not in _tracked_body_ids: |
| 5067 | for child in node.children: |
| 5068 | walk_calls(child, caller_nid) |
| 5069 | return |
| 5070 | |
| 5071 | if node.type in config.call_types: |
| 5072 | # JS/TS dynamic imports: await import('./foo.js') |
| 5073 | if config.ts_module in ("tree_sitter_javascript", "tree_sitter_typescript"): |
| 5074 | if _dynamic_import_js(node, source, caller_nid, str_path, |
| 5075 | edges, seen_dyn_import_pairs): |
| 5076 | # Still recurse into children (import().then(...) may have calls) |
| 5077 | for child in node.children: |
| 5078 | walk_calls(child, caller_nid) |
| 5079 | return |
| 5080 | |
| 5081 | callee_name: str | None = None |
| 5082 | is_member_call: bool = False |
| 5083 | is_this_field_call: bool = False |
| 5084 | swift_receiver: str | None = None |
| 5085 | member_receiver: str | None = None |
| 5086 | |
| 5087 | # Special handling per language |
| 5088 | if config.ts_module == "tree_sitter_swift": |
| 5089 | # Swift: first child may be simple_identifier or navigation_expression |
| 5090 | first = node.children[0] if node.children else None |
| 5091 | if first: |
| 5092 | if first.type == "simple_identifier": |
| 5093 | callee_name = _read_text(first, source) |
| 5094 | elif first.type == "navigation_expression": |
| 5095 | is_member_call = True |
| 5096 | for child in first.children: |
| 5097 | if child.type == "navigation_suffix": |
| 5098 | for sc in child.children: |
| 5099 | if sc.type == "simple_identifier": |
| 5100 | callee_name = _read_text(sc, source) |
| 5101 | # #1356: capture the receiver so the cross-file pass can |
| 5102 | # resolve it through the file's type table. |
| 5103 | recv_node = first.children[0] if first.children else None |
| 5104 | swift_receiver = _swift_receiver_name(recv_node, source) |
| 5105 | elif config.ts_module == "tree_sitter_kotlin": |
| 5106 | # Kotlin: first child may be simple_identifier/identifier or |
| 5107 | # navigation_expression. PyPI's `tree_sitter_kotlin` produces |
| 5108 | # `identifier` for plain identifier nodes; older grammar |
| 5109 | # versions (including the JVM `io.github.bonede:tree-sitter-kotlin` |
| 5110 | # binding) produce `simple_identifier`. Accept both. |
| 5111 | first = node.children[0] if node.children else None |
| 5112 | if first: |
no test coverage detected