CodeGraph/docs
Section 2.6.1

Call Graph Resolution

Resolving function and method invocations from AST CallExpression nodes across local scopes, class instances, and imported modules.

Source: server/src/parser/extractors/RelationshipExtractor.ts

Call Target Resolution Branches

The entry point extractCallRelationship() inspects the AST CallExpression callee:

Branch A: Direct Identifier Calls (foo())

Queries Babel's scope binding path.scope.getBinding(callee.name). If found locally, it resolves to the declaration symbol. If imported, resolveImportedBindingToSymbol() resolves it across files.

Branch B: Member Expression Calls (X.foo())

For member calls, the extractor resolves the object X:

  • this.foo(): Walks up the parentSymbolId chain from the current scope to find the enclosing class symbol.
  • X.foo() where const X = new SomeClass(): Inspects X's binding node. If initialized via NewExpression, resolves the class binding and finds the method where parentSymbolId === classSymbol.id.

Cross-File Import Binding Resolution

When a called function originates from an import statement:

Cross-File Resolution Flow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private resolveImportedBindingToSymbol(parsedFile: ParsedFile, binding: Binding): ParsedSymbol | undefined { const importDeclaration = binding.path.parentPath?.node; if (importDeclaration?.type !== "ImportDeclaration") return undefined; const importSource = importDeclaration.source.value; // 1. Resolve relative path or tsconfig path alias const resolvedPath = this.resolveRelativeImportPath(parsedFile, importSource) || this.resolveAliasPath(parsedFile, importSource); // 2. Find imported file in parsedFiles[] const importedFile = this.findParsedFileByResolvedPath(resolvedPath, this.parsedFiles); if (!importedFile) return undefined; // 3. Match exported name to foreign symbol ID const importedName = this.resolveImportedExportName(binding.path.node); const exportedSymbol = importedFile.exports.find(e => e.exportedName === importedName); if (!exportedSymbol) return undefined; return importedFile.symbols.find(s => s.id === exportedSymbol.symbolId); }