You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/CHANGELOG.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
17
-**Eloquent `$dates` array.** Legacy models using `protected $dates = [...]` now get `Carbon\Carbon`-typed virtual properties for each listed column. Explicit `$casts` entries take priority when both define the same column.
18
18
-**`fix` CLI subcommand.**`phpantom_lsp fix` applies automated code fixes across a project, modeled after php-cs-fixer. Specify rules with `--rule unused_import` (multiple allowed) or omit to run all preferred native fixers. `--dry-run` reports what would change without writing files (exit code 2). `--with-phpstan` enables PHPStan-based fixers (not yet implemented). The first shipped rule, `unused_import`, removes all unused `use` statements project-wide, handling simple imports, group imports, and blank-line collapsing. Supports path filtering (`fix src/`) and single-file mode.
19
19
-**Array element type extraction from property generics.** Bracket access on properties annotated with generic array types (e.g. `$this->cache[$key]->` where `cache` is `array<string, IntCollection>`, or `$this->translations[0]->` where `translations` is `Collection<int, Translation>`) now resolves the element type correctly. Previously the generic parameters were lost during property chain resolution, causing "subject type could not be resolved" on any member access after the bracket. Works for `$this->prop`, `$obj->prop`, nested chains like `$this->nested->prop[0]->`, string-literal keys, and method chains after the bracket access.
20
-
-**Template binding from closure return types.**Methods like `Collection::reduce()` that declare a method-level `@template` parameter bound through a callable's return type now resolve correctly. When the closure or arrow function argument has a return type annotation (e.g. `fn(Decimal $carry, $item): Decimal => ...`), the return type binds the template parameter, so the method's own return type resolves to the concrete class. This works for `fn()` arrow functions, `function()`closures, and closures with `use()`clauses.
20
+
-**Bidirectional template inference from closures.**When a method or function declares a `@template` parameter that appears in a callable's signature, the template is inferred from both the closure's return type and its parameter types. Return-type binding (e.g. `@param callable(...): T` with `fn(...): Decimal => ...` infers `T` as `Decimal`) was already supported. Parameter-type binding is new: `@param Closure(T): void` with `function(User $u): void { ... }` now infers `T` as `User` from the closure's parameter type annotation. Positional matching is supported, so `@param Closure(int, T): void` correctly picks `T` from the second parameter. When the same template appears in both the callable's return type and parameters, the return type takes priority. Works for methods, standalone functions, and constructors with `fn()`arrow functions and `function()`closures.
21
21
-**Inherited docblock type propagation.** When a child class overrides a method from a parent class or interface without providing its own `@return` or `@param` docblock, the ancestor's richer types now flow through automatically. An interface declaring `@return list<Pen>` with a native `: array` hint propagates `list<Pen>` to any implementor that only declares `: array`. The same applies to parent class methods, parameter types (matched by position so renamed parameters still inherit), and property type hints. Descriptions and return descriptions are also inherited when the child lacks them. If the child provides its own docblock type, it is respected as an intentional override.
22
22
-**Drupal project support.** Drupal projects are detected via `composer.json` (`drupal/core`, `drupal/core-recommended`, or `drupal/core-dev`). The web root is resolved from `extra.drupal-scaffold.locations.web-root` with a filesystem fallback. Drupal-specific directories (`core`, `modules/contrib`, `modules/custom`, `themes/contrib`, `themes/custom`, `profiles`, `sites`) are scanned with `.gitignore` bypassed so that Composer-managed code is always indexed. Drupal PHP extensions (`.module`, `.install`, `.theme`, `.profile`, `.inc`, `.engine`) are recognized as PHP source. Contributed by @syntlyx in https://github.com/AJenbo/phpantom_lsp/pull/52.
23
23
-**`@phpstan-assert-if-true $this` narrowing.** Instance methods annotated with `@phpstan-assert-if-true` or `@phpstan-assert-if-false` targeting `$this` now narrow the receiver variable in the corresponding branch. For example, `if ($app->isTestApp())` narrows `$app` to the asserted subtype inside the then-body. Contributed by @syntlyx in https://github.com/AJenbo/phpantom_lsp/pull/52.
| T23 |[`class-string<T>` static method dispatch](todo/type-inference.md#t23-class-stringt-static-method-dispatch)| Medium | Medium |
27
-
| T21 |[Bidirectional template inference](todo/type-inference.md#t21-bidirectional-template-inference-upperlower-bounds) (closure return type → generic) | Medium | Medium-High |
28
27
| H10 |[`return.unusedType` — remove unused type from return union](todo/phpstan-actions.md#h10-returnunusedtype--remove-unused-type-from-return-union)| Medium | Medium |
29
28
| H6 |`return.type` — update return type to match actual returns | Medium | Medium |
0 commit comments