fix(kernel): correct the options shape accepted by AspectKernel::init() - #586
Merged
Merged
Conversation
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
marked this pull request as ready for review
August 10, 2026 22:20
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
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The inline
@phpstan-paramshape onAspectKernel::init()is narrower than what the kernel actually accepts — and narrower than theKernelOptionstype 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[] * ... * } $optionsTwo consequences for anyone running PHPStan over code that boots the kernel:
appDirdemands aliteral-string. Any application that computes its root at runtime — a framework bridge callingbase_path(), a value read from configuration,$_SERVER,getcwd()— is reported as passing an invalid argument.includePaths/excludePathsare typedarray{}, 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 forappDir(is_string($merged['appDir'] ?? null) ? … : '') and filters both path lists witharray_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'forappDirand no include paths at all.Changes
UserKernelOptions@phpstan-typenext to the existingKernelOptions: the same value types, with every key optional — that is exactly the contractinit()offers.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.goaop/frameworkcopy in chore(phpstan): raise analysis level to max goaop-laravel-bridge#36, that package analyses clean at PHPStanlevel: maxwith no@phpstan-ignoreat 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