MCPcopy
hub / github.com/colbymchenry/codegraph / extractPascalCall

Method extractPascalCall

src/extraction/tree-sitter.ts:5607–5675  ·  view source on GitHub ↗

* Extract function calls from a Pascal expression

(node: SyntaxNode)

Source from the content-addressed store, hash-verified

5605 * Extract function calls from a Pascal expression
5606 */
5607 private extractPascalCall(node: SyntaxNode): void {
5608 if (this.nodeStack.length === 0) return;
5609 const callerId = this.nodeStack[this.nodeStack.length - 1];
5610 if (!callerId) return;
5611
5612 // Get the callee name — first child is typically the identifier or exprDot
5613 const firstChild = node.namedChild(0);
5614 if (!firstChild) return;
5615
5616 let calleeName = '';
5617 if (firstChild.type === 'exprDot') {
5618 // Chained static-factory call: `TFoo.GetInstance().DoIt()` — the exprDot's
5619 // receiver is itself an `exprCall`, so the bare identifier list would
5620 // collapse to just `DoIt` and mis-resolve to a same-named method on an
5621 // unrelated class. Encode `TFoo.GetInstance().DoIt` so resolution infers
5622 // DoIt's class from what `TFoo.GetInstance` RETURNS (#645/#608). Only a
5623 // capitalized class-factory chain; a unary outer method.
5624 const innerCall = firstChild.namedChildren.find((c: SyntaxNode) => c.type === 'exprCall');
5625 const outerId = firstChild.namedChildren.filter((c: SyntaxNode) => c.type === 'identifier').pop();
5626 const method = outerId ? getNodeText(outerId, this.source) : '';
5627 if (innerCall && method && /^\w+$/.test(method)) {
5628 const innerFirst = innerCall.namedChild(0);
5629 let innerCallee = '';
5630 if (innerFirst?.type === 'exprDot') {
5631 innerCallee = innerFirst.namedChildren
5632 .filter((c: SyntaxNode) => c.type === 'identifier')
5633 .map((id: SyntaxNode) => getNodeText(id, this.source))
5634 .join('.');
5635 } else if (innerFirst?.type === 'identifier') {
5636 innerCallee = getNodeText(innerFirst, this.source);
5637 }
5638 // Gate on the Delphi type-naming convention — `TFoo` classes / `IFoo`
5639 // interfaces — so a class-factory chain re-encodes but a capitalized
5640 // VARIABLE/parameter chain (Pascal capitalizes locals too: `Curve.X().Y()`,
5641 // `Self.X().Y()`) stays bare and keeps its existing bare-name resolution.
5642 calleeName = innerCallee && /^[TI][A-Z]/.test(innerCallee)
5643 ? `${innerCallee}().${method}`
5644 : method;
5645 } else {
5646 // Qualified call: Obj.Method(...)
5647 const identifiers = firstChild.namedChildren.filter(
5648 (c: SyntaxNode) => c.type === 'identifier'
5649 );
5650 if (identifiers.length > 0) {
5651 calleeName = identifiers.map((id: SyntaxNode) => getNodeText(id, this.source)).join('.');
5652 }
5653 }
5654 } else if (firstChild.type === 'identifier') {
5655 calleeName = getNodeText(firstChild, this.source);
5656 }
5657
5658 if (calleeName) {
5659 this.unresolvedReferences.push({
5660 fromNodeId: callerId,
5661 referenceName: calleeName,
5662 referenceKind: 'calls',
5663 line: node.startPosition.row + 1,
5664 column: node.startPosition.column,

Callers 3

visitPascalNodeMethod · 0.95
visitPascalBlockMethod · 0.95

Calls 3

visitPascalBlockMethod · 0.95
getNodeTextFunction · 0.90
joinMethod · 0.80

Tested by

no test coverage detected