Skip to content

A container key leads to the provider that binds it - #335

Merged
AJenbo merged 3 commits into
PHPantom-dev:mainfrom
shuvroroy:feat/container-binding-registrations-from-service-providers
Aug 16, 2026
Merged

A container key leads to the provider that binds it#335
AJenbo merged 3 commits into
PHPantom-dev:mainfrom
shuvroroy:feat/container-binding-registrations-from-service-providers

Conversation

@shuvroroy

Copy link
Copy Markdown
Contributor

A service provider's string bindings were already indexed, so app('payments')->charge() resolved to the bound class. Three things were still missing: the $bindings / $singletons arrays Laravel reads off a provider, factories that declare what they return rather than building it inline, and any way to navigate from the key itself. This PR finishes all three.

app('payments'), resolve('payments'), App::make('payments'), and $this->app->make('payments') now hover with the class the key resolves to and the provider that registered it, Ctrl+Click jumps to the registration, and find-references collects every other call that asks for the same key — including the registration itself.

What changed

Registrations recovered

  • $bindings / $singletons provider arrays. Laravel applies these itself in Application::register(), after calling register(), so an array entry now beats what register() bound the same key to — the class the container actually ends up holding. Integer keys are skipped: that is Laravel's shorthand for binding a class to itself, which needs no table.
  • Factories that declare their return type. singleton('k', function ($app): Gateway { … }) resolves through the hint when the body hands back something the scan cannot follow.
  • Registration sites. Each binding now records the provider file and the byte offset of the key it was bound under — inside the quotes of a literal, or the start of whatever expression names it (static::$abstract). An alias() records its own key's position rather than the registration it points at, so each key navigates to where it is written.

Navigation

  • New LaravelStringKind::ContainerBinding, emitted for app() / resolve(), the App facade's static calls, and container-receiver method calls ($this->app->, $app->, app()->). Registrations are marked as writes; extend() is a read, since it decorates a key that must already exist.
  • Go-to-definition offers the registration first, then the bound class — matching every other string kind. A core alias the framework declares has no registration of its own, so it offers the class alone.
  • Hover reports Resolves to \X`` plus the registering provider.
  • No diagnostic fires. Anything can be bound at runtime, so an unrecognised key proves nothing.

Declared types are unchanged. A Contract::class key binds a name that already resolves, so app(Gateway::class) stays the contract. An argument spelled as a class name is a class reference, not a binding key, and is never recorded as one.

Refactors

Three, each because the alternative was code that could not be reached or tested:

  1. declared_factory_return re-derived the closure signature behind a ? that its only two callers make impossible. It takes the return-type hint directly now.
  2. Completion's kind→candidates and kind→icon matches were buried inside a function driven by a text detector that cannot produce three of the ten kinds. Extracted as string_key_candidates / string_key_item_kind and unit-tested directly, including that those three offer nothing — which pins the documented decision rather than leaving it as an unexercised arm.
  3. Diagnostics matched LaravelStringKind twice, once to filter and once to check, so the second match needed a dead arm for kinds the first had already dropped. It now carries a CheckedStringKind (seven variants, all reachable), stating the "not judged here" reason once instead of twice.

The third touches a hot path, so the full integration suite was re-run and the failing-test list diffed against baseline: identical.

Two things worth flagging

  1. Provider registrations are not refreshed on edit. build_provider_resources runs only at initialized and in the analyze CLI; there is no refresh_provider_resources the way macros, gates, the morph map, and commands each have one. A newly written binding needs a restart before it resolves. This is pre-existing for the whole provider scan — view directories, route files, component namespaces — and not something this PR introduces, so I left it alone rather than widen the diff. It is the obvious follow-up if the feature should feel live while editing a provider; whoever does it must also reset laravel_aliases and clear the class-not-found cache, as build_provider_resources already does.

  2. No completion for container keys. L36 asked for the alias-table merge, go-to-definition, and hover, and this PR delivers those. Typing inside app('…') still offers nothing: the completion detector never reports this kind, and the extracted string_key_candidates returns an empty list for it. Worth doing as its own change — happy to add it here instead if you'd rather it ship together.

Checklist

If applicable:

  • I have updated CHANGELOG.md
  • I have updated the documentation (README.md, docs/, examples/)
  • I have updated the config schema (config-schema.json)
  • I have added/updated tests to cover my changes

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@shuvroroy
shuvroroy marked this pull request as ready for review August 10, 2026 14:05
shuvroroy and others added 3 commits August 16, 2026 03:48
This wires through hover, go-to-definition, and references for container keys, adds container-key behavior in completion/diagnostics paths, and includes broad unit/integration coverage plus Laravel demo/assertion updates. Todo docs were updated to mark the service-provider binding item as completed.
@AJenbo
AJenbo force-pushed the feat/container-binding-registrations-from-service-providers branch from 9914763 to b439bfb Compare August 16, 2026 03:01
@AJenbo
AJenbo merged commit 0e06c05 into PHPantom-dev:main Aug 16, 2026
7 of 8 checks passed
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.

3 participants