Skip to content

Commit 2703caa

Browse files
committed
refactor: use new BuilderHelper::getBuilderTypeForModels method
1 parent fcc4f70 commit 2703caa

4 files changed

+43
-67
lines changed

src/Methods/ModelForwardsCallsExtension.php

+13-12
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
use PHPStan\Reflection\ParameterReflection;
1717
use PHPStan\Reflection\ParametersAcceptor;
1818
use PHPStan\Reflection\Php\DummyParameter;
19-
use PHPStan\Reflection\ReflectionProvider;
2019
use PHPStan\ShouldNotHappenException;
2120
use PHPStan\TrinaryLogic;
22-
use PHPStan\Type\Generic\GenericObjectType;
2321
use PHPStan\Type\ObjectType;
2422
use PHPStan\Type\StaticType;
2523
use PHPStan\Type\Type;
@@ -35,7 +33,7 @@ final class ModelForwardsCallsExtension implements MethodsClassReflectionExtensi
3533
/** @var array<string, MethodReflection> */
3634
private array $cache = [];
3735

38-
public function __construct(private BuilderHelper $builderHelper, private ReflectionProvider $reflectionProvider, private EloquentBuilderForwardsCallsExtension $eloquentBuilderForwardsCallsExtension)
36+
public function __construct(private BuilderHelper $builderHelper, private EloquentBuilderForwardsCallsExtension $eloquentBuilderForwardsCallsExtension)
3937
{
4038
}
4139

@@ -80,8 +78,7 @@ private function findMethod(ClassReflection $classReflection, string $methodName
8078
if (in_array($methodName, ['increment', 'decrement'], true)) {
8179
$methodReflection = $classReflection->getNativeMethod($methodName);
8280

83-
return new class ($classReflection, $methodName, $methodReflection) implements MethodReflection
84-
{
81+
return new class ($classReflection, $methodName, $methodReflection) implements MethodReflection {
8582
private ClassReflection $classReflection;
8683

8784
private string $methodName;
@@ -168,17 +165,21 @@ public function hasSideEffects(): TrinaryLogic
168165
};
169166
}
170167

171-
$builderReflection = $this->reflectionProvider->getClass($builderName)->withTypes([new ObjectType($classReflection->getName())]);
172-
$genericBuilderAndModelType = new GenericObjectType($builderName, [new ObjectType($classReflection->getName())]);
168+
$builderType = $this->builderHelper->getBuilderTypeForModels($classReflection->getName());
169+
$builderReflection = $builderType->getClassReflection();
170+
171+
if ($builderReflection === null) {
172+
return null;
173+
}
173174

174175
if ($builderReflection->hasNativeMethod($methodName)) {
175176
$reflection = $builderReflection->getNativeMethod($methodName);
176177

177-
$parametersAcceptor = $this->transformStaticParameters($reflection, $genericBuilderAndModelType);
178+
$parametersAcceptor = $this->transformStaticParameters($reflection, $builderType);
178179

179-
$returnType = TypeTraverser::map($parametersAcceptor->getReturnType(), static function (Type $type, callable $traverse) use ($genericBuilderAndModelType) {
180+
$returnType = TypeTraverser::map($parametersAcceptor->getReturnType(), static function (Type $type, callable $traverse) use ($builderType) {
180181
if ($type instanceof TypeWithClassName && $type->getClassName() === Builder::class) {
181-
return $genericBuilderAndModelType;
182+
return $builderType;
182183
}
183184

184185
return $traverse($type);
@@ -200,7 +201,7 @@ public function hasSideEffects(): TrinaryLogic
200201
return null;
201202
}
202203

203-
private function transformStaticParameters(MethodReflection $method, GenericObjectType $builder): ParametersAcceptor
204+
private function transformStaticParameters(MethodReflection $method, ObjectType $builder): ParametersAcceptor
204205
{
205206
$acceptor = $method->getVariants()[0];
206207

@@ -218,7 +219,7 @@ private function transformStaticParameters(MethodReflection $method, GenericObje
218219
}, $acceptor->getParameters()), $acceptor->isVariadic(), $this->transformStaticType($acceptor->getReturnType(), $builder));
219220
}
220221

221-
private function transformStaticType(Type $type, GenericObjectType $builder): Type
222+
private function transformStaticType(Type $type, ObjectType $builder): Type
222223
{
223224
return TypeTraverser::map($type, static function (Type $type, callable $traverse) use ($builder): Type {
224225
if ($type instanceof StaticType) {

src/Methods/RelationForwardsCallsExtension.php

+1-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use PHPStan\Reflection\MissingMethodFromReflectionException;
1616
use PHPStan\Reflection\ReflectionProvider;
1717
use PHPStan\ShouldNotHappenException;
18-
use PHPStan\Type\Generic\GenericObjectType;
1918
use PHPStan\Type\ObjectType;
2019
use PHPStan\Type\ThisType;
2120

@@ -80,8 +79,7 @@ private function findMethod(ClassReflection $classReflection, string $methodName
8079
return null;
8180
}
8281

83-
$builderName = $this->builderHelper->determineBuilderName($modelReflection->getName());
84-
$builderType = new GenericObjectType($builderName, [new ObjectType($modelReflection->getName())]);
82+
$builderType = $this->builderHelper->getBuilderTypeForModels($modelReflection->getName());
8583

8684
if (! $builderType->hasMethod($methodName)->yes()) {
8785
return null;

src/ReturnTypes/ModelDynamicStaticMethodReturnTypeExtension.php

+18-31
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,14 @@
1515
use PhpParser\Node\Name;
1616
use PHPStan\Analyser\Scope;
1717
use PHPStan\Reflection\MethodReflection;
18-
use PHPStan\Reflection\MissingMethodFromReflectionException;
1918
use PHPStan\Reflection\ParametersAcceptorSelector;
2019
use PHPStan\Reflection\ReflectionProvider;
2120
use PHPStan\Type\DynamicStaticMethodReturnTypeExtension;
22-
use PHPStan\Type\Generic\GenericObjectType;
23-
use PHPStan\Type\ObjectType;
2421
use PHPStan\Type\Type;
2522
use PHPStan\Type\TypeCombinator;
2623

2724
use function array_intersect;
25+
use function collect;
2826
use function count;
2927
use function in_array;
3028

@@ -79,39 +77,28 @@ public function getTypeFromStaticMethodCall(
7977

8078
if (count(array_intersect([EloquentBuilder::class], $returnType->getReferencedClasses())) > 0) {
8179
if ($methodCall->class instanceof Name) {
82-
return new GenericObjectType(
83-
$this->builderHelper->determineBuilderName($scope->resolveName($methodCall->class)),
84-
[$scope->resolveTypeByName($methodCall->class)],
80+
return $this->builderHelper->getBuilderTypeForModels(
81+
$scope->resolveTypeByName($methodCall->class),
8582
);
8683
}
8784

8885
$type = $scope->getType($methodCall->class);
8986

90-
if ($type->isClassString()->yes()) {
91-
$type = $type->getClassStringObjectType();
92-
}
93-
94-
$classNames = $type->getObjectClassNames();
95-
96-
$types = [];
97-
98-
foreach ($classNames as $className) {
99-
if (! $this->reflectionProvider->hasClass($className)) {
100-
continue;
101-
}
102-
103-
try {
104-
$types[] = new GenericObjectType(
105-
$this->builderHelper->determineBuilderName($className),
106-
[new ObjectType($className)],
107-
);
108-
} catch (MissingMethodFromReflectionException) {
109-
}
110-
}
111-
112-
if ($types !== []) {
113-
return TypeCombinator::union(...$types);
114-
}
87+
return collect($type->getObjectTypeOrClassStringObjectType()->getObjectClassNames())
88+
->filter(function ($class) {
89+
if (! $this->reflectionProvider->hasClass($class)) {
90+
return false;
91+
}
92+
93+
return $this->reflectionProvider->getClass($class)->is(Model::class);
94+
})
95+
->pipe(function ($models) use ($returnType) {
96+
if ($models->isEmpty()) {
97+
return $returnType;
98+
}
99+
100+
return $this->builderHelper->getBuilderTypeForModels($models->all());
101+
});
115102
}
116103

117104
if (in_array(Collection::class, $returnType->getReferencedClasses(), true)) {

src/ReturnTypes/NewModelQueryDynamicMethodReturnTypeExtension.php

+11-21
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010
use PHPStan\Analyser\Scope;
1111
use PHPStan\Reflection\MethodReflection;
1212
use PHPStan\Type\DynamicMethodReturnTypeExtension;
13-
use PHPStan\Type\Generic\GenericObjectType;
14-
use PHPStan\Type\ObjectType;
1513
use PHPStan\Type\Type;
16-
use PHPStan\Type\TypeCombinator;
1714

15+
use function collect;
1816
use function in_array;
1917

2018
class NewModelQueryDynamicMethodReturnTypeExtension implements DynamicMethodReturnTypeExtension
@@ -45,30 +43,22 @@ public function getTypeFromMethodCall(
4543
MethodCall $methodCall,
4644
Scope $scope,
4745
): Type|null {
48-
$calledOnType = $scope->getType($methodCall->var);
49-
46+
$calledOnType = $scope->getType($methodCall->var);
5047
$classReflections = $calledOnType->getObjectClassReflections();
5148

5249
if ($classReflections === []) {
5350
return null;
5451
}
5552

56-
$types = [];
57-
58-
foreach ($classReflections as $classReflection) {
59-
if (! $classReflection->isSubclassOf(Model::class)) {
60-
continue;
61-
}
62-
63-
$builderName = $this->builderHelper->determineBuilderName($classReflection->getName());
64-
65-
$types[] = new GenericObjectType($builderName, [new ObjectType($classReflection->getName())]);
66-
}
67-
68-
if ($types === []) {
69-
return null;
70-
}
53+
return collect($classReflections)
54+
->filter(static fn ($r) => $r->is(Model::class))
55+
->map(static fn ($r) => $r->getName())
56+
->pipe(function ($models) {
57+
if ($models->isEmpty()) {
58+
return null;
59+
}
7160

72-
return TypeCombinator::union(...$types);
61+
return $this->builderHelper->getBuilderTypeForModels($models->all());
62+
});
7363
}
7464
}

0 commit comments

Comments
 (0)