MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / extractPascalCall

Method extractPascalCall

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

* Extract function calls from a Pascal expression

(node: SyntaxNode)

Source from the content-addressed store, hash-verified

6479 * Extract function calls from a Pascal expression
6480 */
6481 private extractPascalCall(node: SyntaxNode): void {
6482 if (this.nodeStack.length === 0) return;
6483 const callerId = this.nodeStack[this.nodeStack.length - 1];
6484 if (!callerId) return;
6485
6486 // Get the callee name — first child is typically the identifier or exprDot
6487 const firstChild = node.namedChild(0);
6488 if (!firstChild) return;
6489
6490 let calleeName = '';
6491 if (firstChild.type === 'exprDot') {
6492 // Chained static-factory call: `TFoo.GetInstance().DoIt()` — the exprDot's
6493 // receiver is itself an `exprCall`, so the bare identifier list would
6494 // collapse to just `DoIt` and mis-resolve to a same-named method on an
6495 // unrelated class. Encode `TFoo.GetInstance().DoIt` so resolution infers
6496 // DoIt's class from what `TFoo.GetInstance` RETURNS (#645/#608). Only a
6497 // capitalized class-factory chain; a unary outer method.
6498 const innerCall = firstChild.namedChildren.find((c: SyntaxNode) => c.type === 'exprCall');
6499 const outerId = firstChild.namedChildren.filter((c: SyntaxNode) => c.type === 'identifier').pop();
6500 const method = outerId ? getNodeText(outerId, this.source) : '';
6501 if (innerCall && method && /^\w+$/.test(method)) {
6502 const innerFirst = innerCall.namedChild(0);
6503 let innerCallee = '';
6504 if (innerFirst?.type === 'exprDot') {
6505 innerCallee = innerFirst.namedChildren
6506 .filter((c: SyntaxNode) => c.type === 'identifier')
6507 .map((id: SyntaxNode) => getNodeText(id, this.source))
6508 .join('.');
6509 } else if (innerFirst?.type === 'identifier') {
6510 innerCallee = getNodeText(innerFirst, this.source);
6511 }
6512 // Gate on the Delphi type-naming convention — `TFoo` classes / `IFoo`
6513 // interfaces — so a class-factory chain re-encodes but a capitalized
6514 // VARIABLE/parameter chain (Pascal capitalizes locals too: `Curve.X().Y()`,
6515 // `Self.X().Y()`) stays bare and keeps its existing bare-name resolution.
6516 calleeName = innerCallee && /^[TI][A-Z]/.test(innerCallee)
6517 ? `${innerCallee}().${method}`
6518 : method;
6519 } else {
6520 // Qualified call: Obj.Method(...)
6521 const identifiers = firstChild.namedChildren.filter(
6522 (c: SyntaxNode) => c.type === 'identifier'
6523 );
6524 if (identifiers.length > 0) {
6525 calleeName = identifiers.map((id: SyntaxNode) => getNodeText(id, this.source)).join('.');
6526 }
6527 }
6528 } else if (firstChild.type === 'identifier') {
6529 calleeName = getNodeText(firstChild, this.source);
6530 }
6531
6532 if (calleeName) {
6533 this.unresolvedReferences.push({
6534 fromNodeId: callerId,
6535 referenceName: calleeName,
6536 referenceKind: 'calls',
6537 line: node.startPosition.row + 1,
6538 column: node.startPosition.column,

Callers 3

visitPascalNodeMethod · 0.95
visitPascalBlockMethod · 0.95

Calls 3

visitPascalBlockMethod · 0.95
getNodeTextFunction · 0.90
joinMethod · 0.45

Tested by

no test coverage detected