* Recursively visit a Pascal block/statement tree for call expressions
(node: SyntaxNode)
| 6609 | * Recursively visit a Pascal block/statement tree for call expressions |
| 6610 | */ |
| 6611 | private visitPascalBlock(node: SyntaxNode): void { |
| 6612 | for (let i = 0; i < node.namedChildCount; i++) { |
| 6613 | const child = node.namedChild(i); |
| 6614 | if (!child) continue; |
| 6615 | // Function-as-value capture (#756): Pascal bodies are walked here, not |
| 6616 | // in visitNode/visitForCallsAndStructure, so the capture hook fires here |
| 6617 | // — assignment RHS is the Delphi event-wiring idiom (`OnFire := Handler`). |
| 6618 | this.maybeCaptureFnRefs(child, child.type); |
| 6619 | if (child.type === 'exprCall') { |
| 6620 | this.extractPascalCall(child); |
| 6621 | // The walker doesn't descend into a call's arguments — dispatch the |
| 6622 | // argument container directly (`RegisterHandler(TargetCb)` / `(@Cb)`). |
| 6623 | const args = child.namedChildren.find((c: SyntaxNode) => c.type === 'exprArgs'); |
| 6624 | if (args) this.maybeCaptureFnRefs(args, 'exprArgs'); |
| 6625 | } else if (child.type === 'exprDot') { |
| 6626 | // A STATEMENT-level bare exprDot is a paren-less call (`Obj.Free;`, |
| 6627 | // `TFoo.GetInstance.DoIt;`). Anywhere else (assignment side, condition, |
| 6628 | // expression) a bare exprDot is ambiguous with a field/property access, |
| 6629 | // so there we only descend for paren'd inner calls. |
| 6630 | if (node.type === 'statement') { |
| 6631 | this.extractPascalParenlessCall(child); |
| 6632 | } else { |
| 6633 | for (let j = 0; j < child.namedChildCount; j++) { |
| 6634 | const grandchild = child.namedChild(j); |
| 6635 | if (grandchild?.type === 'exprCall') { |
| 6636 | this.extractPascalCall(grandchild); |
| 6637 | } |
| 6638 | } |
| 6639 | } |
| 6640 | } else { |
| 6641 | this.visitPascalBlock(child); |
| 6642 | } |
| 6643 | } |
| 6644 | } |
| 6645 | } |
| 6646 | |
| 6647 |
no test coverage detected