|
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 |
| C13 |
self::/static:: inside a @require-extends trait does not see the required class's static members |
Low-Medium |
Medium |
| C4 |
Non-array functions with dynamic return types |
Low |
High |
|
Type Inference |
|
|
| T26 |
Class constants named as docblock types (Foo::BAR, Foo::BAR_*) |
Medium |
Medium |
| T34 |
static::CONST over-narrows to the declaring class's value |
Medium |
Medium-High |
| T29 |
Definite vs possible variable existence tracking |
Medium |
High |
| T44 |
A single enum case has no type |
Medium |
High |
| T46 |
Template arguments are not inferred from how the object is used later |
Medium |
High |
| T47 |
A closure assigned to a variable gets no parameter types from where it is used |
Medium |
High |
| T41 |
A reading of the callee's body overrides a declared @param-out |
Low-Medium |
Low |
| T43 |
self::TypeAlias inside @extends's generic argument is not resolved |
Low |
Medium |
|
Diagnostics |
|
|
| 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 |
| D19 |
invalid_member_access cannot tell a property read from a write (includes PHP 8.4 private(set)) |
Medium |
Medium |
| D20 |
Foo::$bar and Foo::bar are the same span |
Low |
Medium |
| D21 |
A union of an unreachable and a missing member is reported by neither check |
Low |
Medium-High |
| D22 |
Member provenance is recomputed instead of recorded |
Medium |
Medium-High |
| D23 |
A rebound closure's scope is added to the lexical one rather than replacing it |
Low-Medium |
Medium |
| D28 |
"Remove unreachable code" is wired to PHPStan only |
Low-Medium |
Medium |
| D29 |
namespace and declare bodies break the reachability flow |
Low |
Low-Medium |
|
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 |
| F23 |
Rename a class through its YAML/XML occurrences |
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 |
| F22 |
Merge a namespace onto one that shares a class name |
Low-Medium |
Medium-High |
| 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 |
|
|
| L46 |
->can() on a user model the receiver does not name |
Medium-High |
Medium-High |
| L30 |
Eloquent attribute-array key completion |
Medium |
Medium |
| L56 |
Typed Laravel connection names |
Medium |
Medium |
| L58 |
Laravel rate limiter names |
Medium |
Medium |
| L57 |
Laravel queue names |
Low-Medium |
Medium |
| L59 |
Typed controller middleware names |
Low-Medium |
Medium |
| L53 |
Collection key types from the column for keyBy / groupBy / pluck |
Medium |
Medium |
| L49 |
Unguarded Eloquent mass assignment diagnostic |
Medium |
Medium |
| L17 |
Additional string contexts without booting (middleware, assets, validation, Inertia) |
Medium |
Medium-High |
| L54 |
Audit custom-builder and relation-closure inference against the PHPStan extensions |
Medium |
Medium-High |
| 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 |
| 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 |
|
External Stubs |
|
|
| E7 |
Stub-based framework patches |
Medium |
Medium-High |
| E6 |
Stub install prompt for non-Composer projects |
Low |
Medium |
|
Performance |
|
|
| P76 |
Literal-key writes under separate ifs grow far faster than their count |
Medium |
Medium |
| P77 |
A long method chain costs the cube of its length |
Medium |
Medium |
| P21 |
Offset-shifting for cached diagnostics on partial edits |
Medium |
Very High |
| P73 |
A lazily loaded file is parsed three times |
Low-Medium |
Low |
| P78 |
A switch over thousands of distinct literals is still quadratic |
Low-Medium |
Medium |
| P79 |
Writes under the same dynamic key in separate ifs are quadratic |
Low-Medium |
Medium |
|
Indexing |
|
|
| X7 |
Recency tracking |
Medium |
Medium-High |
| X6 |
Disk cache (evaluate later) |
Medium |
Very High |
| X16 |
Composer's own class lists bypass [indexing] exclude |
Low-Medium |
Low |
| X13 |
Decide how workspace-wide edits treat excluded files |
Low-Medium |
Medium |
| X2 |
Parallel file processing — remaining work |
Low-Medium |
Medium-High |
| X12 |
Say when an exclude hid the class a diagnostic names |
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 |