mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-11-05 07:37:30 +00:00
1 commit
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
36e16434ea
|
fix(php): type locals from namespaced-function factory calls (#3498) (#3662)
* fix(php): type locals from namespaced-function factory calls
`namespace App; use App\Mod as rp; $x = rp\make(); $x->m()` left `$x`
untyped although `make` is declared `: C` in `namespace App\Mod`, and the
inline `rp\make()->m()` recorded a drop. The query matched only an
unqualified callee (`function: (name)`), so a `qualified_name` callee minted
neither a call site nor a result binding; `\App\Mod\make()`, `Mod\make()`
and `namespace\make()` failed the same way, and nothing could have expanded
the path anyway: functions were never indexed by fully qualified name.
- A `qualified_name` / `relative_name` callee is captured as a free call
(tail name, written path as `@reference.qualified-name`) and as a
call-result binding that keeps the whole path, leading `\` included.
- New `php/qualified-function.ts` expands that path by PHP's name rules:
`\` is absolute, `namespace\` is the file's namespace, and a qualified
head goes through the file's class/namespace `use` table, else the file's
namespace. It indexes every `Function` def by lower-cased FQN per pass and
answers only when exactly one def declares the name.
- PHP implements `resolveQualifiedCallee` and `resolveQualifiedFreeCall`
with that one resolution, so a call's type and its CALLS edge agree.
`Qff\Decoy\make` in the fixture is never picked.
- A receiver bound to an in-program namespaced function with no return type
(`$x = rp\untyped()`) now records a `receiver-unresolved` drop.
A full lang-resolution A/B against the parent removes no CALLS/ACCESSES edge
and no drop. It adds 20 edges, all inside the new
php-qualified-function-factory fixture, and 2 drops (its two untyped sites).
The PHP capture golden gains the new fixture only. Existing fixtures' digests
are byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(php): bind use-function imports outside PSR-4 by fully qualified name
`use function App\Mod\make; $x = make(); $x->m()` typed nothing, and the
call itself had no CALLS edge, when `make` is declared outside any PSR-4
path: loaded through composer `autoload.files`, or in a project with no
composer.json. Import resolution finds a function only through a PSR-4
directory or a file named after it, so the import bound nothing (or, with a
PSR-4 directory that holds other files, resolved to one that declares no
`make`). In the new fixture, `namedCall` even picked up another `make`'s
return type, mirrored by name from a sibling file, and emitted a wrong
`QffGadget.ping` edge.
After namespaces are known, a `use function A\f` whose module scope binds
nothing for its local name is bound to the one workspace function named
`A\f`, through the same per-pass FQN index as qualified callees. The fully
qualified name is the function's identity, so this guesses nothing; a
resolved import or a local declaration is left alone, and two declarations
of one name bind nothing. The IMPORTS edge is unchanged: finalize has no
namespaces yet.
Lang-resolution A/B against the parent: one wrong edge removed
(`namedCall -> QffGadget.ping`), two correct fixture edges added
(`namedCall -> make`, `namedCall -> QffWidget.ping`), and four correct
edges the combined corpus lacked because its merged composer configs map
`App\` to many fixtures: php-calls `create_user -> write_audit`,
php-overload-dispatch `run -> format_text` and `run -> format_text_padded`,
php-use-function-const `Calculator.process -> formatName`. Each FQN is
declared once in the corpus. Drops are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test(bench): rebaseline php captures and receiver counts
- receiver-resolution: the new php-qualified-function-factory fixture's two
untyped sites (`$x = rp\untyped(); $x->ping()` and inline
`rp\untyped()->ping()`) are each one call drop: call drops 154 -> 156,
all kinds 224 -> 226. No other drop moves in a same-corpus A/B, and
shape-arm cells are unchanged.
- scope-capture (php): corpus growth only. The query now captures
qualified function callees, but no existing fixture has one: parking the
new fixture reproduces the prior fingerprint byte-for-byte. It adds 96
capture groups and 9 fixture entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(php): fail closed on qualified calls the path cannot resolve
A qualified call site was named by its tail (`count` for `\count($x)`),
so when `resolveQualifiedFreeCall` refused the path, the free-call pass
fell through to its simple-name tiers and could bind a same-named
function in the caller's namespace: `\count($x)` -> a user `Qff\Ext\count`,
`\Vendor\Pkg\make()` -> `Qff\Ext\make`, and a twice-declared
`\Qff\Dup\make()` the same way. Before this branch such calls minted no
site at all, so these were new wrong edges.
The site is now named by its whole written path, the same text it carries
as `@reference.qualified-name`. The provider hook still resolves it by
PHP's name rules. Every simple-name tier (scope chain, implicit `this`,
global unique-name fallback) looks up a name with a `\` in it and finds
nothing, so a refused path (builtin, uninstalled package, ambiguous name,
multi-namespace file) leaves the call unresolved. This change is PHP-only.
Lang-resolution A/B against the parent: no edge or drop removed. Added
edges: the three new fixture functions' `new QffWidget()` calls. No edge
from builtinCall, vendorCall or ambiguousCall. Versus the pre-branch base:
29 edges added (25 in the fixture, plus the 4 `use function` edges from
|