|
Completion |
|
|
| C1 |
Array functions needing new code paths |
Medium |
High |
| C11 |
Smarter member ordering after -> / :: |
Medium |
High |
| C8 |
Filesystem proximity as an affinity tiebreaker |
Low-Medium |
Medium |
| C3 |
Go-to-definition for array shape keys via bracket access |
Low-Medium |
Medium |
| C7 |
class_alias() support |
Low-Medium |
Medium-High |
| C5 |
#[ReturnTypeContract] parameter-dependent return types |
Low |
Medium |
| C6 |
#[ExpectedValues] parameter value suggestions |
Low |
Medium |
| C10 |
Deprecation markers on class-name completions from all sources |
Low |
Medium |
| C12 |
The implicit $value of a set hook is not offered by variable completion |
Low |
Medium |
| C4 |
Non-array functions with dynamic return types |
Low |
High |
|
Type Inference |
|
|
| T20 |
Type narrowing reconciliation engine (CNF clause algebra, sure/sureNot tracking) |
Medium-High |
Very High |
| T41 |
@param-out is parsed but never read |
Medium |
Medium |
| T28 |
Template inference depth priority (shallowest bound wins) |
Medium |
Medium-High |
| T3 |
Property hooks (PHP 8.4) |
Medium |
Medium-High |
| T34 |
static::CONST over-narrows to the declaring class's value |
Medium |
Medium-High |
| T29 |
Definite vs possible variable existence tracking |
Medium |
High |
| T30 |
Literal type collapse limit |
Low-Medium |
Medium |
| T40 |
pathinfo() returns a shape or a string depending on the flags argument |
Low-Medium |
Medium |
| T26 |
Globbed constant unions (Foo::BAR_*) |
Low-Medium |
Medium |
| T33 |
Class constant on an expression ($obj::CONST) resolves to nothing |
Low-Medium |
Medium |
| T6 |
Closure::bind() / Closure::fromCallable() return type preservation |
Low-Medium |
Medium-High |
| T13 |
Closure variables lose callable signature detail |
Low-Medium |
Medium-High |
| T31 |
Closure literal-return shape inference |
Low-Medium |
Medium-High |
| T4 |
Non-empty-* type narrowing and propagation |
Low-Medium |
High |
| T5 |
Fiber type resolution |
Low |
Medium |
| T10 |
Ternary expression as RHS of list destructuring |
Low |
Medium |
| T11 |
Nested list destructuring |
Low |
Medium |
|
Bugs |
|
|
| B238 |
new self(...)/new static(...) resolves by short name, colliding with a same-named global class |
High |
Medium |
| B239 |
$this inside a trait method resolves to the trait itself, not the using class |
High |
Medium-High |
| B229 |
instanceof narrowing is not recognized for several common condition shapes |
High |
High |
| B228 |
A condition-established narrowing of a method-call expression doesn't survive assignment, elseif siblings, or loop merges |
High |
Very High |
| B227 |
The replace function family's conditional return type never collapses |
Medium-High |
Low-Medium |
| B235 |
A lost chained-call re-narrowing misattributes the member lookup to the enclosing file's own class |
Medium-High |
Medium-High |
| B256 |
instanceof does not narrow an array element ($types[$i]) |
Medium-High |
Medium |
| B253 |
A closure parameter's type isn't inferred from a @template-parameterized callable(T): X signature |
Medium-High |
High |
| B230 |
$a === $b doesn't narrow the nullable side against a definite-type operand |
Medium |
Medium |
| B231 |
array_key_exists() doesn't narrow an optional array-shape key the way isset() does |
Medium |
Medium |
| B232 |
use (&$var) doesn't establish $var as defined when it's new to the enclosing scope |
Medium |
Medium |
| B233 |
isset($var) && … doesn't mark a possibly-undefined variable as defined for the rest of the branch |
Medium |
Medium |
| B234 |
is_float()/is_int()'s negative branch doesn't strip a member from a declared union |
Medium |
Medium |
| B237 |
A vendor interface's own @phpstan-assert-if-true Type $this tag isn't honored |
Medium |
Medium |
| B240 |
static return type on an intersection-typed receiver drops the non-declaring interface members |
Medium |
Medium |
| B242 |
Composer\Autoload\ClassLoader is invisible to class resolution |
Medium |
Medium |
| B257 |
A closure parameter binds the whole container when the argument is a union of array shapes |
Medium |
Medium |
| B252 |
??= doesn't route its RHS through the callable-property-invocation resolution path |
Medium |
Medium |
| B236 |
instanceof $variable (a class-string held in a variable) narrowing is unsupported |
Medium |
Medium-High |
| B251 |
A closure's by-reference use mutation isn't tracked when the closure is invoked indirectly |
Medium |
Medium-High |
| B226 |
A function-static variable's type is not tracked across its own reads |
Low-Medium |
Medium-High |
| B243 |
Two more confirmed unknown_member false positives with an unidentified mechanism |
Low-Medium |
Unknown |
| B218 |
new ReflectionProperty(Foo::class, 'bar') forgets what it reflects |
Low |
Medium |
| B254 |
Unused-variable check doesn't account for a closure's use() capture feeding a required file's scope |
Low |
Medium |
| B246 |
array_keys() on an array whose keys the + operator merged |
Low |
Medium |
| B255 |
An array shape key spelled with a backslash widens the shape's key type to int\|string |
Low |
Medium |
| B241 |
An abstract class isn't accepted where a union of exactly its known subclasses is declared |
Low |
High |
|
Diagnostics |
|
|
| D6 |
Unreachable code diagnostic |
Low-Medium |
Medium |
| D16 |
unreachable_match_arm ignores literal subject types |
Low-Medium |
Medium |
| D5 |
External tool diagnostic suppression actions |
Low |
Low |
| D15 |
Unused parameter diagnostic |
Low |
Medium |
| D17 |
docblock_native_mismatch only judges nullability |
Low |
Medium-High |
| D18 |
array<int, T> is accepted wherever a list<T> is declared |
Low |
Medium-High |
|
Code Actions |
|
|
| A40 |
Generate method from call |
Medium-High |
Medium-High |
| A28 |
Explicit nullable parameter type (PHP 8.4 deprecation) |
Medium |
Low |
| A16 |
Snippet placeholder for extracted method name (lets the user type over the generated name immediately) |
Medium |
Medium |
| A46 |
Honor context.only in code action responses |
Medium |
Medium |
| A25 |
strpos → str_contains (PHP 8.0+) |
Medium |
Medium |
| A41 |
Create class from non-existing name |
Medium |
Medium-High |
| A34 |
Unified code action handler architecture (closure-based resolve, unified fix type) |
Medium |
Very High |
| A29 |
Simplify boolean return (if (cond) return true; return false; → return cond;) |
Low-Medium |
Medium |
| A45 |
Simplify with ?: (replace $x ? $x : $y with $x ?: $y) |
Low-Medium |
Medium |
| A31 |
Remove always-else (extract guard clause) |
Low-Medium |
Medium-High |
| A37 |
Simplify with ?-> (replace null-checked chains with the nullsafe operator) |
Low-Medium |
Medium-High |
| A38 |
Convert if/elseif chain to switch |
Low-Medium |
Medium-High |
| A43 |
Update docblock generics |
Low |
Medium |
|
PHPStan Code Actions |
|
|
| H4 |
assign.byRefForeachExpr — unset by-reference foreach variable |
Medium |
Medium |
| H13 |
property.notFound — declare missing property (same-class) |
Medium |
Medium |
| H15 |
Template bound from tip — add @template T of X |
Medium |
Medium |
| H16 |
match.unhandled — add missing match arms |
Medium |
Medium-High |
| H19 |
property.unused / method.unused — remove unused member |
Low |
Low |
| H23 |
instanceof.alwaysTrue — remove redundant instanceof check |
Low |
Low |
| H24 |
catch.neverThrown — remove unnecessary catch clause |
Low |
Low |
| H20 |
generics.callSiteVarianceRedundant — remove redundant variance annotation |
Low |
Medium |
|
CLI Fix Rules |
|
|
| FX7 |
add_return_type — generate @return docblocks from function bodies |
Medium-High |
Medium-High |
| FX1 |
deprecated — replace deprecated symbol usage |
Medium |
Low |
| FX3 |
phpstan.return.unusedType — remove unused type from return union |
Medium |
Low |
| FX4 |
phpstan.missingType.iterableValue — add @return with iterable type |
Medium |
Low |
| FX2 |
unused_variable — remove unused variables |
Medium |
Medium |
| FX5 |
phpstan.property.unused / phpstan.method.unused — remove unused member |
Low |
Low |
| FX6 |
phpstan.generics.callSiteVarianceRedundant — remove redundant variance |
Low |
Medium |
|
LSP Features |
|
|
| F11 |
VS Code extension |
High |
Medium-High |
| F12 |
IntelliJ / PHPStorm plugin |
High |
Medium-High |
| F13 |
Homebrew formula |
Medium |
Low |
| F17 |
Wire class move to workspace/willRenameFiles |
Medium |
Medium |
| F5 |
Call hierarchy (incoming/outgoing calls) |
Medium |
Medium |
| F2 |
Partial result streaming via $/progress |
Medium |
Medium-High |
| F7 |
Evaluatable expression support (DAP integration) |
Low-Medium |
Low |
| F15 |
Go-to-declaration |
Low-Medium |
Low |
| F14 |
Helix upstream PR (depends on F13) |
Low-Medium |
Low |
| F16 |
On-type } brace de-indent |
Low |
Low |
| F19 |
Connect to a remote/TCP language server |
Low |
Medium |
|
Signature Help |
|
|
| S2 |
Closure / arrow function parameter signature help |
Medium |
Medium |
| S3 |
Multiple overloaded signatures |
Medium |
Medium-High |
| S4 |
Named argument awareness in active parameter |
Low-Medium |
Medium |
| S5 |
Language construct signature help and hover |
Low |
Medium |
|
Laravel |
|
|
| L24 |
Translation depth: JSON lang files, locales, placeholders |
Medium-High |
Medium-High |
| L46 |
->can() on a user model the receiver does not name |
Medium-High |
Medium-High |
| L30 |
Eloquent attribute-array key completion |
Medium |
Medium |
| L32 |
Config-backed named-resource strings (log channels, cache stores, guards, connections, rate limiters) |
Medium |
Medium |
| L49 |
Unguarded Eloquent mass assignment diagnostic |
Medium |
Medium |
| L17 |
Additional string contexts without booting (middleware, assets, validation, Inertia) |
Medium |
Medium-High |
| L25 |
Storage disk name strings |
Low-Medium |
Low |
| L31 |
String-key rename, highlight, and semantic tokens |
Low-Medium |
Medium |
| L42 |
Morph alias completion in array positions |
Low-Medium |
Medium |
| L3 |
$dates array (deprecated) |
Low-Medium |
Medium |
| L12 |
HasUuids / HasUlids trait — $id typed as string |
Low-Medium |
Medium |
| L44 |
Sibling resource registrations and degenerate resource names |
Low-Medium |
Medium |
| L50 |
"Create route" quick-fix for an unresolved route name |
Low-Medium |
Medium |
| L47 |
Morph aliases in *_type column comparisons |
Low-Medium |
Medium-High |
| L8 |
withSum/withAvg/withMin/withMax aggregate properties |
Low-Medium |
High |
| L45 |
*_count properties are offered on every relationship |
Low-Medium |
High |
| L29 |
Livewire and Volt component names (Livewire projects only) |
Low |
Low |
| L27 |
Legacy Controller@method action strings |
Low |
Low |
| L10 |
View::withX() / RedirectResponse::withX() dynamic methods |
Low |
Medium |
| L39 |
Unused view and translation key detection |
Low |
Medium |
| L51 |
"Convert facade call to dependency injection" refactor |
Low |
Medium |
|
Blade |
|
|
| BL11 |
Custom directive discovery (Blade::directive() / Blade::if() registrations) |
Medium |
Medium |
|
External Stubs |
|
|
| E7 |
Stub-based framework patches |
Medium |
Medium-High |
| E6 |
Stub install prompt for non-Composer projects |
Low |
Medium |
|
Performance |
|
|
| P16 |
Pre-parsed stub format (eliminate raw PHP embedding) |
High |
Very High |
| P35 |
Diagnostic passes reach only a fraction of available cores |
Medium-High |
Very High |
| P30 |
Evaluate migrating parse/resolve/docblock pipeline to mago-hir (parked — re-evaluated at mago 1.46.0, still no mago-hir consumers upstream) |
Medium-High |
Very High |
| P52 |
The diagnostic benchmarks measure a path no consumer takes |
Medium |
Low |
| P53 |
The deprecated collector deep-copies a class per member access |
Medium |
Low |
| P51 |
CI-gated scaling and memory invariants |
Medium |
Low-Medium |
| P17 |
mago-names resolution on the parse hot path |
Medium |
High |
| P18 |
Subtype result caching (per-request HashMap for hierarchy walks) |
Medium |
High |
| P47 |
The resolved-class cache lock caps concurrent class resolution |
Medium |
Very High |
| P20 |
Content-hash gated resolution cache persistence |
Medium |
Very High |
| P21 |
Offset-shifting for cached diagnostics on partial edits |
Medium |
Very High |
| P3 |
Parallel pre-filter in find_implementors |
Low-Medium |
Medium-High |
| P50 |
Cache the top-level scope for global keyword resolution |
Low-Medium |
High |
| P48 |
Higher-order collection proxy injection repeats work |
Low |
Medium |
| P49 |
A very long method chain costs superlinear time to analyse |
Low |
Medium |
| P54 |
Property narrowing re-walks the whole body once per subject |
Low |
Medium |
| P15 |
Two-phase stub index construction (eliminate RwLock on stub maps) |
Low |
Medium-High |
| P6 |
O(n²) transitive eviction in evict_fqn |
Low |
High |
|
Indexing |
|
|
| X7 |
Recency tracking |
Medium |
Medium-High |
| X6 |
Disk cache (evaluate later) |
Medium |
Very High |
| X2 |
Parallel file processing — remaining work |
Low-Medium |
Medium-High |
| X9 |
Honor editor file excludes and PHP associations during indexing |
Low-Medium |
Medium-High |
|
Inline Completion |
|
|
| N1 |
Template engine (type-aware snippets) |
Medium |
Medium |
| N2 |
N-gram prediction from PHP corpus |
Medium |
Very High |
| N3 |
Fine-tuned GGUF sidecar model |
Medium |
Very High |