* Recursively visit a Pascal block/statement tree for call expressions
(node: SyntaxNode)
| 6662 | * Recursively visit a Pascal block/statement tree for call expressions |
| 6663 | */ |
| 6664 | private visitPascalBlock(node: SyntaxNode): void { |
| 6665 | for (let i = 0; i < node.namedChildCount; i++) { |
| 6666 | const child = node.namedChild(i); |
| 6667 | if (!child) continue; |
| 6668 | // Function-as-value capture (#756): Pascal bodies are walked here, not |
| 6669 | // in visitNode/visitForCallsAndStructure, so the capture hook fires here |
| 6670 | // — assignment RHS is the Delphi event-wiring idiom (`OnFire := Handler`). |
| 6671 | this.maybeCaptureFnRefs(child, child.type); |
| 6672 | if (child.type === 'exprCall') { |
| 6673 | this.extractPascalCall(child); |
| 6674 | // The walker doesn't descend into a call's arguments — dispatch the |
| 6675 | // argument container directly (`RegisterHandler(TargetCb)` / `(@Cb)`). |
| 6676 | const args = child.namedChildren.find((c: SyntaxNode) => c.type === 'exprArgs'); |
| 6677 | if (args) this.maybeCaptureFnRefs(args, 'exprArgs'); |
| 6678 | } else if (child.type === 'exprDot') { |
| 6679 | // A STATEMENT-level bare exprDot is a paren-less call (`Obj.Free;`, |
| 6680 | // `TFoo.GetInstance.DoIt;`). Anywhere else (assignment side, condition, |
| 6681 | // expression) a bare exprDot is ambiguous with a field/property access, |
| 6682 | // so there we only descend for paren'd inner calls. |
| 6683 | if (node.type === 'statement') { |
| 6684 | this.extractPascalParenlessCall(child); |
| 6685 | } else { |
| 6686 | for (let j = 0; j < child.namedChildCount; j++) { |
| 6687 | const grandchild = child.namedChild(j); |
| 6688 | if (grandchild?.type === 'exprCall') { |
| 6689 | this.extractPascalCall(grandchild); |
| 6690 | } |
| 6691 | } |
| 6692 | } |
| 6693 | } else { |
| 6694 | this.visitPascalBlock(child); |
| 6695 | } |
| 6696 | } |
| 6697 | } |
| 6698 | } |
| 6699 | |
| 6700 |
no test coverage detected