Give Rust and Python real cross-file calls and stop fabricating Python imports - #28
Merged
Merged
Conversation
…n imports Python import resolution now checks that a candidate actually exists on disk (module file, then package __init__.py, in Python's own order) instead of returning the first plausible-looking path, so phantom File nodes at paths that never existed are gone. Bare-dot imports (from . import mod) try the submodule file before falling back to the package __init__, and namespace aliases (import pkg as p) record the alias. The shared generic call extractor is import-aware: calls to imported names and module-qualified calls now emit the callee's defining file, and always under the name DECLARED at that file, never the local alias, so the edge actually binds. Rust resolves mod-declared siblings, crate paths anchored at the nearest Cargo.toml, self and super, and aliased use items, all existence-verified; external crates stay unresolved. Go deliberately emits no cross-file callees: its calls address a package directory, not a file, and guessing is worse than absence; the honest fix needs a project-wide package symbol table, recorded on the ledger. The pipeline honors the resolved callee file instead of structurally forcing every non-TS call edge to be same-file. Two adversarial review rounds drove out the alias blocker (found independently in both extractors) plus two adjacent Python bugs, all verified by live-index runs; the composition sweep across nine fixtures found zero dangling callees and zero phantom files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
Batch three, wave two: cross-file call resolution for non-TypeScript languages, with honesty as the design constraint. Resolve what per-file import analysis can prove, drop what it cannot, never fabricate.
Python
The generic engine (Python plus ~35 tier-2 languages)
The shared call extractor accepts the file's imports as context and emits the callee's defining file, always under the name declared at that file rather than the local alias, so the edge binds to a real node.
Rust
Resolves mod-declared siblings (both foo.rs and foo/mod.rs forms), use crate:: paths anchored at the nearest Cargo.toml, self and super, and aliased items, all verified with existence checks. External crates stay unresolved. Method calls deliberately get no bare-call fallback to avoid coincidental name matches.
Go
Deliberately emits no cross-file callees: Go calls address a package (a directory), not a file, and per-file analysis cannot know which file declares a symbol. Guessing would create wrong edges, so the behavior is locked by tests and the honest fix (a project-wide package symbol table pre-pass) is recorded on the ledger.
Pipeline
Call edges are built from the resolved callee file when present instead of structurally forcing every non-TS edge to be same-file, which is what made cross-file resolution impossible for all these languages.
Review process
Two adversarial rounds of live-index attacks. Round one found the alias blocker independently in both the generic and Rust extractors (the unit tests had enshrined the wrong expectation), plus two adjacent Python bugs. Round two verified all fixes with hostile probes, including a target file declaring both the alias and the real name as separate functions, and a composition sweep across nine fixtures with zero dangling callees and zero phantom files.
Verification
Known gaps deliberately not in this PR (ledger)
🤖 Generated with Claude Code