test(php): gate legacy-DAG-divergent assertions via parity helper

CI scope-parity / php parity was failing under REGISTRY_PRIMARY_PHP=0 on
three assertions added by commit af9af4a9 (U1 arity-narrowing, U3 trait
shadows parent). Per that commit's stance — "parity with the legacy DAG
is not a correctness criterion when the legacy DAG itself has the same
defect" — backporting these fixes to the legacy resolver is out of scope.

Adopt the existing sibling pattern (csharp/typescript/python use the
same helper):
- php.test.ts: switch to `const it = createResolverParityIt('php')` so
  expected-failure assertions skip under legacy mode.
- helpers.ts: register three test names in
  LEGACY_RESOLVER_PARITY_EXPECTED_FAILURES.php with the rationale.

Verified locally: 172 passed + 3 skipped under REGISTRY_PRIMARY_PHP=0,
175 passed under REGISTRY_PRIMARY_PHP=1, tsc clean.
This commit is contained in:
Gergo Magyar 2026-05-11 14:54:34 +01:00
parent b1f0cd8cf1
commit fd30b61c38
2 changed files with 25 additions and 1 deletions

View file

@ -34,6 +34,23 @@ const LEGACY_RESOLVER_PARITY_EXPECTED_FAILURES: Readonly<Record<string, Readonly
// which is only available in the registry-primary path.
'resolves user.Save() to the method whose receiver type is declared in another package file',
]),
php: new Set([
// Arity-narrowing in `pickUniqueGlobalCallable` rejects free-call
// candidates that are definitively below required-parameter-count. The
// legacy DAG path does not narrow on arity, so it emits over-broad CALLS
// edges for variadic functions invoked with too few args even though
// the only candidate's required count is non-zero. Scope-resolver-only
// correctness win (commit af9af4a9 U1); backporting to legacy is out
// of scope.
'does NOT emit CALLS edge for record() with zero args (below required=1)',
'does NOT emit CALLS edge for pad() with zero args (below required=1)',
// `$this->method()` precedence inside a class that composes a trait AND
// extends a parent both defining the same method requires the augmented
// trait-aware MRO (trait shadows parent). The legacy DAG has no
// trait-aware MRO, so it fails to bind the call to the trait. Scope-
// resolver-only correctness win (commit af9af4a9 U3).
'$this->record() still resolves to Auditable::record (trait shadows parent)',
]),
python: new Set([
// Suffix-fallback lex tiebreak depends on the registry-primary
// resolver's deterministic sort. The legacy resolver returns the

View file

@ -1,11 +1,12 @@
/**
* PHP: PSR-4 imports, extends, implements, trait use, enums, calls + ambiguous disambiguation
*/
import { describe, it, expect, beforeAll } from 'vitest';
import { describe, expect, beforeAll } from 'vitest';
import path from 'path';
import {
FIXTURES,
CROSS_FILE_FIXTURES,
createResolverParityIt,
getRelationships,
getNodesByLabel,
getNodesByLabelFull,
@ -14,6 +15,12 @@ import {
type PipelineResult,
} from './helpers.js';
// Wrap vitest's `it` so legacy-DAG-only divergences (commit af9af4a9 U1/U3)
// are skipped under REGISTRY_PRIMARY_PHP=0. The skip list lives in
// helpers.ts:LEGACY_RESOLVER_PARITY_EXPECTED_FAILURES.php — sibling pattern
// to csharp/typescript/python.
const it = createResolverParityIt('php');
// ---------------------------------------------------------------------------
// Heritage: PSR-4 imports, extends, implements, trait use, enums, calls
// ---------------------------------------------------------------------------