(&mut self, node: Node<'t>)
| 529 | } |
| 530 | |
| 531 | fn visit_for_calls_and_structure(&mut self, node: Node<'t>) { |
| 532 | stack_guard!(); |
| 533 | let kind = node.kind(); |
| 534 | self.maybe_capture_fn_refs(node); |
| 535 | |
| 536 | if kind == "call" { |
| 537 | self.extract_call(node); |
| 538 | } else if let Some(bare) = self.bare_call_name(node) { |
| 539 | // extractBareCall: statement-level identifiers in BLOCK_PARENTS |
| 540 | // bodies (`do…end` = body_statement; brace blocks are block_body — |
| 541 | // NOT in the set, so `5.times { beep }` emits nothing for beep). |
| 542 | let name = bare.to_string(); |
| 543 | let from = self.top_row(); |
| 544 | self.push_ref_at(from, &name, edge_kind_index("calls").unwrap(), node); |
| 545 | } |
| 546 | |
| 547 | // (No INSTANTIATION_KINDS for ruby — `.new` is handled in extract_call; |
| 548 | // extractStaticMemberRef is gated off; no type annotations.) |
| 549 | |
| 550 | // Nested NAMED defs become their own function nodes; classes extract. |
| 551 | // A `module` inside a body mints NOTHING (the visitNode hook does not |
| 552 | // run here) — its children just recurse. Same for singleton_method |
| 553 | // (functionTypes-only check): unmatched, recursed. |
| 554 | if kind == "method" { |
| 555 | let name = self.extract_name(node); |
| 556 | if name != "<anonymous>" { |
| 557 | self.extract_function(node); |
| 558 | return; |
| 559 | } |
| 560 | } |
| 561 | if kind == "class" { |
| 562 | self.extract_class(node); |
| 563 | return; |
| 564 | } |
| 565 | |
| 566 | for i in 0..node.named_child_count() { |
| 567 | if let Some(c) = node.named_child(i) { |
| 568 | self.visit_for_calls_and_structure(c); |
| 569 | } |
| 570 | } |
| 571 | } |
| 572 | |
| 573 | /// rubyExtractor.extractBareCall (languages/ruby.ts:77-105). |
| 574 | fn bare_call_name(&self, node: Node) -> Option<&'t str> { |
no test coverage detected