Parent
Spec: #18 (ticket 3/5). This ticket closes #16.
What to build
A PhpNameResolver mirroring CsharpNameResolver (graphify/extractors/csharp.py:174-296), returning a (node_id, decisive) verdict, consulted in _resolve_php_member_calls (extract.py:3247-3260) in front of the corpus-wide type_def_nids short-name fallback — exactly like the C# call site (extract.py:2870-2885).
Minimal decisive rules for this ticket:
Strictly subtractive: this ticket may only delete edges relative to v8, never add or re-point.
Repro that must go green (from #16 / probe scenario 10 — the canonical copy lives in spec #18)
Two files: App\Local\Client::send() and a caller in App\Http with use Vendor\Sdk\Client; + private Client $c; + $this->c->send(). Today: false edge App\Http\I::go -> App\Local\Client::send INFERRED 0.8. After: no edge.
Constraints
- Red-first: the repro test must be shown failing before the fix.
- Decoy discipline: add a positive guard — a caller whose
use App\Local\Client; points at the real in-corpus class must KEEP its edge (that path may bind via the existing unique-short-name fallback; it must not regress).
- Refusal is correct on both full and incremental runs without new markers (the
use map belongs to the freshly-dispatched calling file) — but add a mirrored incremental test per test_php_member_calls.py:1544-1878 (_full_then_incremental) proving it.
- CHANGELOG line naming the deleted-edge class (alias-claimed short names no longer bare-name fallback).
Acceptance criteria
Blocked by
#19 (needs the captured use metadata). #20 extends coverage to fully-qualified annotations but is not required for the alias case.
Parent
Spec: #18 (ticket 3/5). This ticket closes #16.
What to build
A
PhpNameResolvermirroringCsharpNameResolver(graphify/extractors/csharp.py:174-296), returning a(node_id, decisive)verdict, consulted in_resolve_php_member_calls(extract.py:3247-3260) in front of the corpus-widetype_def_nidsshort-name fallback — exactly like the C# call site (extract.py:2870-2885).Minimal decisive rules for this ticket:
usealias/import in the calling file → resolve the aliased FQN against the in-corpus FQN index; hit →(nid, True); miss →(None, True)— refuse, never fall back. (The miss case is PHP: use-alias pointing outside the corpus + one same-short-named in-corpus class mints a wrong INFERRED edge (design risk 6, measured) #16's false edge.)(None, False)→ existing fallback runs unchanged.Strictly subtractive: this ticket may only delete edges relative to v8, never add or re-point.
Repro that must go green (from #16 / probe scenario 10 — the canonical copy lives in spec #18)
Two files:
App\Local\Client::send()and a caller inApp\Httpwithuse Vendor\Sdk\Client;+private Client $c;+$this->c->send(). Today: false edgeApp\Http\I::go -> App\Local\Client::send INFERRED 0.8. After: no edge.Constraints
use App\Local\Client;points at the real in-corpus class must KEEP its edge (that path may bind via the existing unique-short-name fallback; it must not regress).usemap belongs to the freshly-dispatched calling file) — but add a mirrored incremental test pertest_php_member_calls.py:1544-1878(_full_then_incremental) proving it.Acceptance criteria
callsedge (same-file and cross-file variants)usealias keeps its edge (positive guard with same-short-named decoy getting NO edge)extract()seamBlocked by
#19 (needs the captured
usemetadata). #20 extends coverage to fully-qualified annotations but is not required for the alias case.