4
4
5
5
use PhpParser \Node \Expr \MethodCall ;
6
6
use PHPStan \Analyser \Scope ;
7
+ use PHPStan \Broker \Broker ;
8
+ use PHPStan \Reflection \BrokerAwareExtension ;
7
9
use PHPStan \Reflection \MethodReflection ;
10
+ use PHPStan \Reflection \ParametersAcceptorSelector ;
8
11
use PHPStan \Type \ArrayType ;
9
12
use PHPStan \Type \IntegerType ;
10
13
use PHPStan \Type \MixedType ;
11
14
use PHPStan \Type \ObjectType ;
12
15
use PHPStan \Type \Type ;
13
16
use PHPStan \Type \TypeCombinator ;
17
+ use PHPStan \Type \TypeWithClassName ;
14
18
15
- class ObjectRepositoryDynamicReturnTypeExtension implements \PHPStan \Type \DynamicMethodReturnTypeExtension
19
+ class ObjectRepositoryDynamicReturnTypeExtension implements \PHPStan \Type \DynamicMethodReturnTypeExtension, BrokerAwareExtension
16
20
{
17
21
22
+ /** @var Broker */
23
+ private $ broker ;
24
+
25
+ public function setBroker (Broker $ broker ): void
26
+ {
27
+ $ this ->broker = $ broker ;
28
+ }
29
+
18
30
public function getClass (): string
19
31
{
20
32
return 'Doctrine\Common\Persistence\ObjectRepository ' ;
@@ -36,10 +48,35 @@ public function getTypeFromMethodCall(
36
48
): Type
37
49
{
38
50
$ calledOnType = $ scope ->getType ($ methodCall ->var );
39
- if (!$ calledOnType instanceof ObjectRepositoryType ) {
51
+ if (!$ calledOnType instanceof TypeWithClassName ) {
40
52
return new MixedType ();
41
53
}
54
+
42
55
$ methodName = $ methodReflection ->getName ();
56
+ $ repositoryClassReflection = $ this ->broker ->getClass ($ calledOnType ->getClassName ());
57
+ if (
58
+ (
59
+ (
60
+ strpos ($ methodName , 'findBy ' ) === 0
61
+ && strlen ($ methodName ) > strlen ('findBy ' )
62
+ ) || (
63
+ strpos ($ methodName , 'findOneBy ' ) === 0
64
+ && strlen ($ methodName ) > strlen ('findOneBy ' )
65
+ )
66
+ )
67
+ && $ repositoryClassReflection ->hasNativeMethod ($ methodName )
68
+ ) {
69
+ return ParametersAcceptorSelector::selectFromArgs (
70
+ $ scope ,
71
+ $ methodCall ->args ,
72
+ $ repositoryClassReflection ->getNativeMethod ($ methodName )->getVariants ()
73
+ )->getReturnType ();
74
+ }
75
+
76
+ if (!$ calledOnType instanceof ObjectRepositoryType) {
77
+ return new MixedType ();
78
+ }
79
+
43
80
$ entityType = new ObjectType ($ calledOnType ->getEntityClass ());
44
81
45
82
if ($ methodName === 'find ' || strpos ($ methodName , 'findOneBy ' ) === 0 ) {
0 commit comments