Skip to content

fix(pipeline): resolve PSR-4 imports to exact class files - #2509

Merged
DeusData merged 1 commit into
mainfrom
fix/issue-1186-psr4-imports-v2
Oct 4, 2026
Merged

DeusData merged 1 commit into
mainfrom
fix/issue-1186-psr4-imports-v2

Conversation

@DeusData

@DeusData DeusData commented Oct 3, 2026

Copy link
Copy Markdown
Owner

PHP PSR-4 class imports can point at the first file in a namespace instead of the imported class file. Resolve class imports through Composer autoload and autoload-dev mappings, use the longest matching prefix, and require the exact class file. Preserve separate handling for use function and use const, and retain current JavaScript/TypeScript default-import metadata.

Refs #1186. Existing indexes need a full rebuild. Array-valued PSR-4 roots and duplicate-prefix ordering remain outside this change; PHP vendor-name and cross-file receiver follow-ups remain separate.

Validation: the native regression suite passes all 68 tests; reverting the fix reproduces exactly four PSR-4 failures (64 passed), and restoring it passes all 68 again. The final affected suites pass 891 tests and lint passes, without sanitizer diagnostics. Further local CI was waived for this continuation; GitHub checks will validate the published revision.

Preserve import kinds and resolve class imports through Composer prefixes
to the existing target class file, including autoload-dev mappings.

Refs #1186

Signed-off-by: Martin Vogel <[email protected]>
@DeusData

DeusData commented Oct 3, 2026

Copy link
Copy Markdown
Owner Author

Checkpoint and handover (2026-10-03 UTC)

Published head: 830f0ccfae65349b8fed2e92d37163b5cc34347c. The remote head was verified.

The PSR-4/vendor import fix for #1186 is published. Historical narrow evidence was 68 passing, 64 passing plus 4 owned failures on revert, then 68 passing after restoration; the affected run reached 891 passing before the local-CI waiver. Scope is references and requires a full reindex. PHP import/type follow-ups are tracked separately in #2515 and #2520.

Hosted snapshot at 2026-10-03 21:54:09 UTC: 14 queued, 4 skipped, 21 success. Confirm the required checks on this exact head before treating it as ready.

No additional local build, test, lint, sanitizer, benchmark or CI runs were performed at this checkpoint, as requested. Earlier executed evidence remains historical; prepared tests and the newer source-reviewed changes must still be validated by the hosted gate.

The campaign is paused at the maintainer’s request. Local monitoring has stopped; hosted jobs remain running. No merge was performed. Thanks for reviewing this change.

@DeusData
DeusData merged commit 02abf31 into main Oct 4, 2026
41 checks passed
DeusData added a commit that referenced this pull request Oct 4, 2026
…olver

Why: since 830f0cc (#2509) the package map stores a composer.json PSR-4
prefix ("Acme\Blog\") as its repo-relative directory ("packages/blog/src"),
not as a dotted QN root. The route-handler resolver still formatted that
value as a QN root and built "packages/blog/src.Http.PostsController.
PostsController.index", which names no node. The PSR-4 step therefore
resolved nothing. Handlers whose folders mirror their namespace
(App\Http\Controllers -> app/Http/Controllers) still got their edge through
the namespace/folder fallback, but a package class under a root whose folder
does not mirror its namespace got no HANDLES edge. That is the case of
packages/blog/src in the test fixture and of krayin's
Webkul\Admin\ -> packages/Webkul/Admin/src.

Change: resolve the handler class the way the import pass resolves
`use Ns\Class;` for PHP.
- pass_pkgmap.c: psr4_file_node and resolve_php_psr4_class take the graph
  buffer instead of the pipeline ctx, since they only read ctx->gbuf. The
  new cbm_pipeline_psr4_member_qn runs resolve_php_psr4_class for the class
  FQN, takes the Class/Interface/Trait/Enum node of that name defined in the
  resolved file, and returns the QN of <class QN>.<member> when that node
  exists.
- registry.c: psr4_member_qn delegates to it and no longer builds a QN from
  the package-map value. cbm_registry_resolve_handler takes the graph buffer
  in place of the package map. The namespace/folder fallback is unchanged.
- pass_calls.c and pass_parallel.c pass the graph buffer they already use
  for the handler lookup: ctx->gbuf, and main_gbuf, which is read-only
  during the resolve phase.

Proof:
- handles_laravel_class_handlers_issue1146 and its _parallel twin
  (edge_types_probe): RED 3/3 before the change ("missing
  PostsController.index -> /blog", expected=4 actual=3; suite 75 passed,
  2 failed). GREEN 3/3 after (77 passed). RED again with the production
  change reverted. GREEN again once it was restored.
- Real input: no Laravel app with a non-mirroring PSR-4 root is available
  locally. koel/koel v9.11.1 (App\ -> app/) was indexed with the binary
  before and after, each under a private runtime and cache. The results
  are identical: 16,564 nodes, 60,177 edges, 15 Routes and 1 HANDLES
  (/demo/new-session -> NewSessionController.__invoke), with the same
  handler rows.
- Suites: edge_types_probe 77, edge_imports 68, pipeline 317 and
  route_canon 11 all pass (473). make lint-ci passes.

Refs #1146

Signed-off-by: Martin Vogel <[email protected]>
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.

1 participant