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
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
10
10
### Added
11
11
12
+
-**Closure parameter inference.** When a closure or arrow function is passed to a method or function whose parameter is typed as `callable(T): R` or `Closure(T): R`, untyped closure parameters are now inferred from the callable signature. For example, `$users->map(fn($u) => $u->name)` infers `$u` as `User` when `map` declares `@param callable(TValue): TMapValue` and generic substitution has resolved `TValue` to `User`. Works with instance methods, static methods, null-safe calls, standalone functions, `$this->method()` receivers, and closures at any argument position. Explicit type hints on closure parameters always take precedence. Template parameters inside callable signatures (e.g. `callable(TValue): void`) are substituted during generic resolution so the inferred types are concrete.
12
13
-**Factory support.**`User::factory()->create()` and `->make()` now resolve to the model class. When a model uses the `HasFactory` trait with an explicit `@use HasFactory<UserFactory>` annotation, the generics system handles resolution. When the annotation is absent, the naming convention is used as a fallback: `App\Models\User` maps to `Database\Factories\UserFactory`, and subdirectories are preserved (`App\Models\Admin\SuperUser` maps to `Database\Factories\Admin\SuperUserFactory`). Factory chain methods that return `static` (e.g. `count()`, `state()`) continue the chain on the factory, while `create()` and `make()` return the model. The convention also works in reverse: a factory class extending `Factory` without `@extends Factory<Model>` resolves `TModel` from its own class name. Both directions are implemented as fallbacks that defer to explicit generics when present.
13
14
-**`newCollection()` override detection.** Eloquent models that override the `newCollection()` method now resolve to the custom collection class declared in the method's return type. This is the third detection mechanism alongside `#[CollectedBy]` and `@use HasCollection<X>`. Priority order: attribute, trait, method override. Works with short names resolved via `use` imports and fully-qualified return types. The standard `Collection` return type is correctly ignored. Custom collection methods appear after `->get()`, on relationship properties, and in builder chains.
14
15
-**Body-inferred relationship properties.** Eloquent relationship methods that lack `@return` annotations now produce virtual properties by scanning the method body for patterns like `$this->hasMany(Post::class)`. The relationship type is inferred from the method name (`hasMany` to `HasMany`, `belongsTo` to `BelongsTo`, etc.) and the related model class is extracted from the first `::class` argument. Supports all 10 relationship types including `HasOneThrough`. Fully-qualified class names, extra foreign key arguments, and chained builder calls (e.g. `->latest()`) are handled. When both a `@return` annotation and a body pattern are present, the annotation takes priority. Projects that don't use Larastan no longer need to add annotations for basic relationship completion.
@@ -45,6 +46,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
45
46
46
47
### Fixed
47
48
49
+
-**Arrow function parameter go-to-definition.** Go-to-definition on a variable used in an arrow function body (e.g. `$o` in `fn(Order $o) => $o->getItems()`) now jumps to the parameter on the same line. Previously the backward scan excluded the cursor line, so it would skip the arrow function parameter and jump to an unrelated earlier variable with the same name. The fix includes the cursor line in the scan but only accepts non-assignment definitions (parameters, foreach, catch, static/global) to preserve the existing behavior for reassignments like `$value = $value->value`. Go-to-definition on the parameter itself (the LHS `$o`) correctly resolves the type hint and jumps to the `Order` class.
50
+
48
51
-**Relationship property collection type uses the related model's custom collection.** When a model like `Product` had a `HasMany<Review, $this>` relationship, the virtual property `$product->reviews` incorrectly used the owning model's custom collection (`ProductCollection`) instead of the related model's (`ReviewCollection`). The provider now loads the related model via `class_loader` and reads its `custom_collection` field. The integration test was updated to use distinct collections per model so the bug is no longer masked.
49
52
50
53
-**UTF-8 boundary panic in `find_enclosing_return_type`.** Files containing multi-byte UTF-8 characters (such as `─` in comment banners) could cause a panic when `extract_method_return_from_body_brace` sliced the content at a byte offset that landed inside a multi-byte character. This broke variable type resolution for any method whose body brace fell within 2000 bytes of such a character, causing `$model->` completions to silently return empty results while `$this->` (which uses a different code path) continued to work. The slice offset is now adjusted to a valid char boundary.
0 commit comments