Skip to content

Commit

Permalink
fix: cast Model to string if its gonna be in array-key position in Co…
Browse files Browse the repository at this point in the history
…llection
  • Loading branch information
canvural committed Nov 9, 2022
1 parent d898af7 commit 0936d48
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 4 deletions.
Expand Up @@ -14,6 +14,7 @@
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\UnionType;
Expand Down Expand Up @@ -109,14 +110,21 @@ private function handleGenericObjectType(ClassReflection $classReflection, Class

$genericTypes = $returnTypeClassReflection->typeMapToList($returnTypeClassReflection->getActiveTemplateTypeMap());

// If the key type is gonna be a model, we change it to string
if ((new ObjectType(Model::class))->isSuperTypeOf($genericTypes[0])->yes()) {
$genericTypes[0] = new StringType();
}

$genericTypes = array_map(static function (Type $type) use ($classReflection) {
return TypeTraverser::map($type, static function (Type $type, callable $traverse) use ($classReflection): Type {
if ($type instanceof UnionType || $type instanceof IntersectionType) {
return $traverse($type);
}

if ($type instanceof GenericObjectType && (($innerTypeReflection = $type->getClassReflection()) !== null)) {
return new GenericObjectType($classReflection->getName(), $innerTypeReflection->typeMapToList($innerTypeReflection->getActiveTemplateTypeMap()));
$genericTypes = $innerTypeReflection->typeMapToList($innerTypeReflection->getActiveTemplateTypeMap());

return new GenericObjectType($classReflection->getName(), $genericTypes);
}

return $traverse($type);
Expand Down
6 changes: 3 additions & 3 deletions tests/Type/data/collection-generic-static-methods.php
Expand Up @@ -74,10 +74,10 @@
assertType('App\UserCollection', $secondCustomEloquentCollection->mergeRecursive([1 => new User()]));
assertType('Illuminate\Support\Collection<string, int>', $items->mergeRecursive(['foo' => 2]));

assertType('Illuminate\Database\Eloquent\Collection<int, int>', $collection->combine([1]));
assertType('App\TransactionCollection<int, int>', $customEloquentCollection->combine([1]));
assertType('Illuminate\Database\Eloquent\Collection<string, int>', $collection->combine([1]));
assertType('App\TransactionCollection<string, int>', $customEloquentCollection->combine([1]));
assertType('App\UserCollection', $secondCustomEloquentCollection->combine([1]));
assertType('Illuminate\Support\Collection<string, string>', $items->combine(['foo']));
assertType('Illuminate\Support\Collection<int, string>', $items->combine(['foo']));

assertType('App\User|Illuminate\Database\Eloquent\Collection<int, App\User>|null', $collection->pop(1));
assertType('App\Transaction|App\TransactionCollection<int, App\Transaction>|null', $customEloquentCollection->pop(2));
Expand Down

0 comments on commit 0936d48

Please sign in to comment.