Skip to content

fix(php): emit a calls edge for object creation, new Foo(...) (#3115) - #3169

Open
abhay-codes07 wants to merge 1 commit into
Graphify-Labs:v8from
abhay-codes07:fix/php-object-creation
Open

fix(php): emit a calls edge for object creation, new Foo(...) (#3115)#3169
abhay-codes07 wants to merge 1 commit into
Graphify-Labs:v8from
abhay-codes07:fix/php-object-creation

Conversation

@abhay-codes07

Copy link
Copy Markdown
Contributor

Closes #3115.

The problem

object_creation_expression was absent from _PHP_CONFIG.call_types, so a class a PHP method merely constructs got no edge at all — the PHP twin of the gap Java closed in #1373 and C# in #2997/#2998. On the reporter's Symfony/DDD corpus (615 files), 505 new X( sites across 178 distinct classes emitted nothing, worst on message-bus code where construction is the control flow: 0 of 22 $bus->dispatch(new SomeCommand(...)) sites had any edge to the command they construct.

The change

  • object_creation_expression joins _PHP_CONFIG.call_types.
  • A dedicated engine branch (placed beside C#'s) names the constructed class: PHP keeps it in a bare name/qualified_name child — no field — so the generic call path never saw it. A qualified new \App\Bar() names the last segment, matching how the PHP namespace pass keys classes.
  • Nothing is guessed: new $cls() is dynamic and stays unnamed; new self() / new static() / new parent() name no other class and are skipped rather than minting junk nodes or edges.

Tests

tests/test_php_object_creation.py — 6 tests mirroring the C# suite: new in assignment, new in argument position (the $bus->dispatch(new Bar(2)) shape), qualified construction naming the last segment, dynamic/self/static producing nothing, existing static-call edges unchanged, and a cross-file dispatcher reaching its command class through use + new. With the fix reverted, 4 of 6 fail. test_php_type_resolution is unchanged; the full suite matches the fresh v8 (0.9.51) baseline.

…hify-Labs#3115)

`object_creation_expression` was absent from _PHP_CONFIG.call_types, so a
class a method merely constructs got no edge at all - the PHP twin of the
gap Java closed in Graphify-Labs#1373 and C# in Graphify-Labs#2997. On the reporter's Symfony corpus
505 `new X(` sites across 178 classes were invisible, worst on message-bus
code where construction IS the control flow: 0 of 22
`$bus->dispatch(new SomeCommand(...))` sites had any edge to the command.

PHP keeps the constructed class in a bare name/qualified_name child (no
field), so the generic call path never names it; a dedicated engine branch
(beside C#'s) reads it, naming the last segment of a qualified
`new \App\Bar()` to match how the namespace pass keys classes. `new $cls()`
is dynamic and `new self()`/`static`/`parent` name no other class - all
stay unnamed rather than minting junk edges.
Copilot AI lite review requested due to automatic review settings August 28, 2026 14:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Treats PHP new Foo(...) as a call so a method that only constructs a class links to it, matching the existing Java and C# behaviour. The engine reads the class from the bare name/qualified_name child (qualified names resolve to the last segment), while new $cls(), new self(), new static(), and new parent() stay unnamed rather than minting phantom edges.

Worth a look

  • PHP constructor calls via new parent() are silently droppedgraphify/extractors/engine.py:5169 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 1924 functions depend on the 425 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 502 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: _extract_generic() — 18 callers, 24 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_js() — 85 callers, 3 callees
  • new: dispatch_command() — 2 callers, 122 callees
  • new: extract_objc() — 27 callers, 9 callees
  • new: _get_extractor() — 26 callers, 6 callees
  • …and 32 more — each is listed as a finding

Verification — 1924 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 1767 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_extract\_generic.

The verifier did not have enough to check \_extract\_generic, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set

· 40 more finding(s) on lines outside this diff (see the check run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PHP: new Foo(...) produces no edge — object_creation_expression missing from _PHP_CONFIG.call_types

2 participants