* Recursively visit a Pascal block/statement tree for call expressions
(node: SyntaxNode)
| 5741 | * Recursively visit a Pascal block/statement tree for call expressions |
| 5742 | */ |
| 5743 | private visitPascalBlock(node: SyntaxNode): void { |
| 5744 | for (let i = 0; i < node.namedChildCount; i++) { |
| 5745 | const child = node.namedChild(i); |
| 5746 | if (!child) continue; |
| 5747 | // Function-as-value capture (#756): Pascal bodies are walked here, not |
| 5748 | // in visitNode/visitForCallsAndStructure, so the capture hook fires here |
| 5749 | // — assignment RHS is the Delphi event-wiring idiom (`OnFire := Handler`). |
| 5750 | this.maybeCaptureFnRefs(child, child.type); |
| 5751 | if (child.type === 'exprCall') { |
| 5752 | this.extractPascalCall(child); |
| 5753 | // The walker doesn't descend into a call's arguments — dispatch the |
| 5754 | // argument container directly (`RegisterHandler(TargetCb)` / `(@Cb)`). |
| 5755 | const args = child.namedChildren.find((c: SyntaxNode) => c.type === 'exprArgs'); |
| 5756 | if (args) this.maybeCaptureFnRefs(args, 'exprArgs'); |
| 5757 | } else if (child.type === 'exprDot') { |
| 5758 | // A STATEMENT-level bare exprDot is a paren-less call (`Obj.Free;`, |
| 5759 | // `TFoo.GetInstance.DoIt;`). Anywhere else (assignment side, condition, |
| 5760 | // expression) a bare exprDot is ambiguous with a field/property access, |
| 5761 | // so there we only descend for paren'd inner calls. |
| 5762 | if (node.type === 'statement') { |
| 5763 | this.extractPascalParenlessCall(child); |
| 5764 | } else { |
| 5765 | for (let j = 0; j < child.namedChildCount; j++) { |
| 5766 | const grandchild = child.namedChild(j); |
| 5767 | if (grandchild?.type === 'exprCall') { |
| 5768 | this.extractPascalCall(grandchild); |
| 5769 | } |
| 5770 | } |
| 5771 | } |
| 5772 | } else { |
| 5773 | this.visitPascalBlock(child); |
| 5774 | } |
| 5775 | } |
| 5776 | } |
| 5777 | } |
| 5778 | |
| 5779 |
no test coverage detected