Skip to content

fix(kernel): correct the options shape accepted by AspectKernel::init() - #586

Merged
lisachenko merged 1 commit into
masterfrom
claude/laravel-bridge-phpstan-max-yn8jqd
Aug 10, 2026
Merged

fix(kernel): correct the options shape accepted by AspectKernel::init()#586
lisachenko merged 1 commit into
masterfrom
claude/laravel-bridge-phpstan-max-yn8jqd

Conversation

@lisachenko

Copy link
Copy Markdown
Member

Summary

The inline @phpstan-param shape on AspectKernel::init() is narrower than what the kernel actually accepts — and narrower than the KernelOptions type declared on the same class:

 * @phpstan-param array{
 *   appDir?: literal-string&non-falsy-string,   // KernelOptions says: appDir: string
 *   includePaths?: array{},                     // KernelOptions says: includePaths: string[]
 *   excludePaths?: array{},                     // KernelOptions says: excludePaths: string[]
 *   ...
 * } $options

Two consequences for anyone running PHPStan over code that boots the kernel:

  • appDir demands a literal-string. Any application that computes its root at runtime — a framework bridge calling base_path(), a value read from configuration, $_SERVER, getcwd() — is reported as passing an invalid argument.
  • includePaths/excludePaths are typed array{}, i.e. only an empty array literal is accepted, even though listing directories is the entire purpose of both options.

Neither restriction is real: normalizeOptions() accepts any string for appDir (is_string($merged['appDir'] ?? null) ? … : '') and filters both path lists with array_filter($raw, is_string(...)). The annotation was the only thing rejecting valid calls.

It stayed unnoticed because the only in-repo caller is demos/autoload_aspect.php, which happens to pass a literal __DIR__ . '/../demos' for appDir and no include paths at all.

Changes

  • Add a UserKernelOptions @phpstan-type next to the existing KernelOptions: the same value types, with every key optional — that is exactly the contract init() offers.
  • Point init() at it, replacing the inline shape. Keeping the two types adjacent means the accepted input and the normalized output cannot drift apart.

No runtime change — this is a type annotation fix.

Testing

  • ./vendor/bin/phpstan analyze --memory-limit=512M (level 10) — no errors, baseline unchanged.
  • ./vendor/bin/phpunit — 2474 tests, 2877 assertions, green.
  • Verified downstream: with this patch applied to the goaop/framework copy in chore(phpstan): raise analysis level to max goaop-laravel-bridge#36, that package analyses clean at PHPStan level: max with no @phpstan-ignore at its $kernel->init(...) call. That suppression exists today only because of this annotation, and can be dropped once this lands.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HRJrrw79a8r4YTLyAxzJTF


Generated by Claude Code

The inline shape on init() was narrower than what the kernel actually
accepts and than what the KernelOptions type on the same class declares:

* "appDir" required a literal-string, so any application computing its
  root directory at runtime (a framework bridge calling base_path(), a
  path read from configuration, $_SERVER, getcwd(), ...) was reported as
  an invalid argument;
* "includePaths" and "excludePaths" were typed as array{}, i.e. only an
  empty array literal was accepted, even though listing directories is
  the entire purpose of both options.

Both are normalized by normalizeOptions(), which accepts any string for
"appDir" and filters both path lists with is_string(), so the annotation
was the only thing rejecting valid calls. Only the bundled demo passed a
literal __DIR__-based "appDir" and no include paths at all, which is why
this stayed unnoticed.

Express the accepted options as a UserKernelOptions type sitting next to
KernelOptions, so both stay in sync: same value types, all keys optional.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRJrrw79a8r4YTLyAxzJTF
@lisachenko
lisachenko marked this pull request as ready for review August 10, 2026 22:20
@lisachenko
lisachenko merged commit 13f0fe0 into master Aug 10, 2026
7 checks passed
@lisachenko
lisachenko deleted the claude/laravel-bridge-phpstan-max-yn8jqd branch August 10, 2026 22:21
lisachenko pushed a commit to goaop/goaop-laravel-bridge that referenced this pull request Aug 10, 2026
goaop/framework#586 corrected the options shape annotated on
AspectKernel::init(), so the options assembled by kernelOptions() are now
accepted as they are. The suppression is not merely redundant: with
reportUnmatchedIgnoredErrors it fails the analysis outright once that fix
reaches the installed dev-master.

The package now passes PHPStan level max with no suppressions at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRJrrw79a8r4YTLyAxzJTF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants