fix: resolve scoped/static (Class::method) call targets for PHP and Rust#568
Open
NaeemHaque wants to merge 1 commit into
Open
fix: resolve scoped/static (Class::method) call targets for PHP and Rust#568NaeemHaque wants to merge 1 commit into
Class::method) call targets for PHP and Rust#568NaeemHaque wants to merge 1 commit into
Conversation
Scoped/static calls — PHP `Mailer::send()`, Rust `Notifier::notify()`, `Self::method()` — were stored as CALLS edges with the intermediate `Class::method` target form, which matches neither the qualified-name (`<file>::Class.method`) nor the bare-name lookup path. The edges dangled, so callers_of / get_impact_radius / tests_for silently under-reported these callers (notably every Rust associated-fn/constructor call). Add a conservative post-build resolver (scoped_resolver.py) that rewrites resolvable `Class::method` targets to the canonical node qualified name, mirroring the existing Spring/Temporal/ReScript resolvers, wired into both full build and incremental update. It only rewrites unambiguous (class, method) matches or import-disambiguated ones; external/unknown targets like `Vec::new` are left untouched so no false edge is created. self/static/Self/ this resolve to the enclosing class; parent to its base. Resolved edges are tagged confidence_tier=INFERRED. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Scoped/static calls (
Mailer::send()in PHP,Mailer::send(x)/Self::method()in Rust) were stored as CALLS edges with the intermediateClass::methodtarget, which matches neither the qualified-name lookup (<file>::Class.method) nor the bare-name lookup. The edges dangled, socallers_of,get_impact_radius, andtests_forsilently missed these callers — especially impactful in Rust, whereType::method()/Self::method()is the dominant call form.Fixes #567.
What this does
Adds a post-build resolver (
code_review_graph/scoped_resolver.py) in the same style as the existing Spring/Temporal/ReScript resolvers. It rewrites resolvableClass::methodCALLS targets to the canonical node qualified name, wired into both full build and incremental update (gated to.php/.rs).It is deliberately conservative so it never fabricates an edge:
Class::methodtargets are resolved. Multi-segment Rust module paths (a::b::c) are left alone — resolving them by their last two segments would point at unrelated types.App\Mailer→Mailer).self/Selfresolve to the enclosing class.(class, method)node, or disambiguates via the caller file'sIMPORTS_FROMedges. Ambiguous or unknown targets (external types likeVec::new) are left untouched.confidence_tier = INFERREDto distinguish them from directly-extracted ones.Known limitation: same-name collisions across files with no import statement have nothing to disambiguate on and stay unresolved. Strictly better than today, not 100%.
Scope is PHP and Rust — the two languages that actually produce a dangling
Class::methodedge. C++/Ruby produce no CALLS edge for scoped calls (a separate extraction gap), and R's::is external-package access; both are out of scope here.Tests
tests/test_scoped_resolver.py(14 tests): PHP cross-file and namespaced calls, Rust cross-file andSelf::, the multi-segment false-edge guard, external-target-left-untouched, import disambiguation (resolved + ambiguous), incremental re-resolution, idempotency, andINFERREDtagging.uv run pytest— all pass (full suite green)uv run ruff check code_review_graph/— clean