99use PHPStan \Analyser \Scope ;
1010use PHPStan \Reflection \MethodReflection ;
1111use PHPStan \Reflection \ParametersAcceptorSelector ;
12+ use PHPStan \Reflection \ReflectionProvider ;
1213use PHPStan \ShouldNotHappenException ;
1314use PHPStan \Type \DynamicStaticMethodReturnTypeExtension ;
1415use PHPStan \Type \NullType ;
15- use PHPStan \Type \ObjectType ;
1616use PHPStan \Type \ThisType ;
1717use PHPStan \Type \Type ;
1818use PHPStan \Type \TypeCombinator ;
1919use PHPStan \Type \UnionType ;
2020use yii \db \ActiveQuery ;
2121use yii \db \ActiveRecord ;
2222
23- use function is_a ;
24-
2523final class ActiveRecordDynamicStaticMethodReturnTypeExtension implements DynamicStaticMethodReturnTypeExtension
2624{
25+ private ReflectionProvider $ reflectionProvider ;
26+
27+ public function __construct (
28+ ReflectionProvider $ reflectionProvider ,
29+ ) {
30+ $ this ->reflectionProvider = $ reflectionProvider ;
31+ }
32+
2733 public function getClass (): string
2834 {
2935 return ActiveRecord::class;
@@ -34,33 +40,52 @@ public function getClass(): string
3440 */
3541 public function isStaticMethodSupported (MethodReflection $ methodReflection ): bool
3642 {
37- $ returnType = ParametersAcceptorSelector::selectSingle ($ methodReflection ->getVariants ())->getReturnType ();
43+ $ variants = $ methodReflection ->getVariants ();
44+ if (count ($ variants ) === 0 ) {
45+ return false ;
46+ }
47+
48+ $ returnType = $ variants [0 ]->getReturnType ();
3849 if ($ returnType instanceof ThisType) {
3950 return true ;
4051 }
4152
4253 if ($ returnType instanceof UnionType) {
4354 foreach ($ returnType ->getTypes () as $ type ) {
44- if ($ type instanceof ObjectType) {
45- return is_a ($ type ->getClassName (), $ this ->getClass (), true );
55+ $ classNames = $ type ->getObjectClassNames ();
56+ if (count ($ classNames ) > 0 ) {
57+ $ className = $ classNames [0 ];
58+ if ($ this ->reflectionProvider ->hasClass ($ className )) {
59+ $ classReflection = $ this ->reflectionProvider ->getClass ($ className );
60+ return $ classReflection ->isSubclassOf ($ this ->getClass ());
61+ }
4662 }
4763 }
4864 }
4965
50- return $ returnType instanceof ObjectType &&
51- is_a ($ returnType ->getClassName (), ActiveQuery::class, true );
66+ $ classNames = $ returnType ->getObjectClassNames ();
67+ if (count ($ classNames ) > 0 ) {
68+ $ className = $ classNames [0 ];
69+ if ($ this ->reflectionProvider ->hasClass ($ className )) {
70+ $ classReflection = $ this ->reflectionProvider ->getClass ($ className );
71+ return $ classReflection ->isSubclassOf (ActiveQuery::class);
72+ }
73+ }
74+
75+ return false ;
5276 }
5377
54- /**
55- * @throws ShouldNotHappenException
56- */
5778 public function getTypeFromStaticMethodCall (
5879 MethodReflection $ methodReflection ,
5980 StaticCall $ methodCall ,
60- Scope $ scope
81+ Scope $ scope,
6182 ): Type {
6283 $ className = $ methodCall ->class ;
63- $ returnType = ParametersAcceptorSelector::selectSingle ($ methodReflection ->getVariants ())->getReturnType ();
84+ $ returnType = ParametersAcceptorSelector::selectFromArgs (
85+ $ scope ,
86+ $ methodCall ->getArgs (),
87+ $ methodReflection ->getVariants (),
88+ )->getReturnType ();
6489
6590 if (!$ className instanceof Name) {
6691 return $ returnType ;
@@ -75,7 +100,7 @@ public function getTypeFromStaticMethodCall(
75100 if ($ returnType instanceof UnionType) {
76101 return TypeCombinator::union (
77102 new NullType (),
78- new ActiveRecordObjectType ($ name )
103+ new ActiveRecordObjectType ($ name ),
79104 );
80105 }
81106
0 commit comments