You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AST extraction: cross-file call resolution is limited to Python imports only #298
walk_calls in extract.py resolves call targets using a file-locallabel_to_nid dict (L948-949):
tgt_nid=label_to_nid.get(callee_name.lower())
This means any call to a function/class defined in another file is silently dropped. Cross-file relationships — which are theoretically fully resolvable from AST — are almost entirely lost.
Current state
The only cross-file mechanism is _resolve_cross_file_imports() (L2039), which has significant limitations:
Limitation
Detail
Python-only
L2652: # Python only - uses Python parser internally
Import-level only
Only resolves from .module import Name, does not trace actual call sites
Coarse granularity
Connects all classes in the importing file to the imported entity, regardless of whether they actually use it
Stem-only module matching
Matches by filename stem (L2083), ignores package paths like foo.bar.baz
All other languages (JS/TS, Go, Rust, Java, C/C++, etc.) have zero cross-file resolution — calls to imported symbols produce no edges at all.
Impact
For any multi-file codebase, the AST call graph is effectively incomplete. The semantic subagents (LLM) partially compensate, but:
They are non-deterministic and token-expensive
They miss structural relationships that AST could extract for free
Code-only corpora skip semantic extraction entirely, so cross-file calls are completely lost
Proposed approach
Build a global symbol table in a two-pass architecture:
Pass 1 (existing): Per-file extraction — collect all nodes (label_to_nid) and raw call names
Pass 2 (new): Merge all per-file symbol tables into a global label_to_nid, then re-resolve unresolved calls against the global table
This is the minimal change — walk_calls already extracts the callee name, it just fails to find a target because the lookup scope is too narrow. A global lookup table would immediately resolve cross-file calls for all languages without language-specific import handlers.
Additional improvements (optional, can be separate PRs)
Per-language import resolvers to map import X from './foo' to the actual file's symbols
Package-path-aware module matching (not just stem)
Narrowing _resolve_cross_file_imports granularity to only connect entities that actually reference the import
Environment
graphify version: installed via pip install graphifyy
This is an accurate description of the current limitation. The cross-file call resolution in _resolve_cross_file_imports() is Python-only and import-level only -- it does not trace actual call sites, and all other languages have zero cross-file resolution from AST.
The reason it works this way is that full cross-file call resolution requires building a per-language scope/symbol table across the entire corpus before emitting any edges, which is a significant amount of work to get right for each language. The current implementation trades completeness for speed and simplicity.
The semantic subagents compensate for this on mixed corpora -- the LLM can reason across files and emit cross-file edges that AST misses. For code-only corpora (no LLM), the gap is real.
A proper fix would require:
A two-pass extraction: first pass builds a corpus-wide symbol table (exported symbols per file), second pass resolves call sites against it.
Per-language import resolution (each language has different import semantics).
This is on the roadmap but there is no timeline. For now, the LLM semantic pass is the intended mechanism for cross-file relationship discovery on mixed corpora.
Fixed in v0.4.18. Cross-file call resolution now works for Go, Rust, Zig, PowerShell, and Elixir. Each extractor now saves unresolved callees to raw_calls, which are resolved against the global node index after all files are extracted. pip install --upgrade graphifyy
Activity
feat: add persistent cross-file edge overlays
safishamsi commentedon Apr 16, 2026
This is an accurate description of the current limitation. The cross-file call resolution in
_resolve_cross_file_imports()is Python-only and import-level only -- it does not trace actual call sites, and all other languages have zero cross-file resolution from AST.The reason it works this way is that full cross-file call resolution requires building a per-language scope/symbol table across the entire corpus before emitting any edges, which is a significant amount of work to get right for each language. The current implementation trades completeness for speed and simplicity.
The semantic subagents compensate for this on mixed corpora -- the LLM can reason across files and emit cross-file edges that AST misses. For code-only corpora (no LLM), the gap is real.
A proper fix would require:
This is on the roadmap but there is no timeline. For now, the LLM semantic pass is the intended mechanism for cross-file relationship discovery on mixed corpora.
safishamsi commentedon Apr 16, 2026
Fixed in v0.4.18. Cross-file call resolution now works for Go, Rust, Zig, PowerShell, and Elixir. Each extractor now saves unresolved callees to
raw_calls, which are resolved against the global node index after all files are extracted.pip install --upgrade graphifyyv0.4.19: fix #390 #298 #410 #401 #385, team workflow docs, Windows/pi…
fix(objc): add cross-file call resolution and unary message parsing
v0.4.19: fix #390 #298 #410 #401 #385, team workflow docs, Windows/pi…
v0.4.19: fix Graphify-Labs#390 Graphify-Labs#298 Graphify-Labs#410 Gr…