88use PhpParser \Node \Name ;
99use PHPStan \Analyser \Scope ;
1010use PHPStan \Reflection \MethodReflection ;
11+ use PHPStan \Reflection \ParametersAcceptorSelector ;
1112use PHPStan \Type \DynamicStaticMethodReturnTypeExtension ;
1213use PHPStan \Type \NullType ;
14+ use PHPStan \Type \ObjectType ;
15+ use PHPStan \Type \ThisType ;
1316use PHPStan \Type \Type ;
1417use PHPStan \Type \TypeCombinator ;
18+ use PHPStan \Type \UnionType ;
19+ use yii \db \ActiveQuery ;
20+ use yii \db \ActiveRecord ;
1521
1622final class ActiveRecordDynamicStaticMethodReturnTypeExtension implements DynamicStaticMethodReturnTypeExtension
1723{
1824 public function getClass (): string
1925 {
20- return ' yii\db\ ActiveRecord' ;
26+ return ActiveRecord::class ;
2127 }
2228
2329 public function isStaticMethodSupported (MethodReflection $ methodReflection ): bool
2430 {
25- return \in_array ($ methodReflection ->getName (), ['findOne ' , 'find ' ], true );
31+ $ returnType = ParametersAcceptorSelector::selectSingle ($ methodReflection ->getVariants ())->getReturnType ();
32+ if ($ returnType instanceof ThisType) {
33+ return true ;
34+ }
35+
36+ if ($ returnType instanceof UnionType) {
37+ foreach ($ returnType ->getTypes () as $ type ) {
38+ if ($ type instanceof ObjectType) {
39+ return \is_a ($ type ->getClassName (), $ this ->getClass (), true );
40+ }
41+ }
42+ }
43+
44+ return $ returnType instanceof ObjectType && \is_a ($ returnType ->getClassName (), ActiveQuery::class, true );
2645 }
2746
2847 public function getTypeFromStaticMethodCall (MethodReflection $ methodReflection , StaticCall $ methodCall , Scope $ scope ): Type
@@ -31,8 +50,12 @@ public function getTypeFromStaticMethodCall(MethodReflection $methodReflection,
3150 $ className = $ methodCall ->class ;
3251 $ name = $ scope ->resolveName ($ className );
3352
34- $ methodName = $ methodReflection ->getName ();
35- if ($ methodName === 'findOne ' ) {
53+ $ returnType = ParametersAcceptorSelector::selectSingle ($ methodReflection ->getVariants ())->getReturnType ();
54+ if ($ returnType instanceof ThisType) {
55+ return new ActiveRecordObjectType ($ name );
56+ }
57+
58+ if ($ returnType instanceof UnionType) {
3659 return TypeCombinator::union (
3760 new NullType (),
3861 new ActiveRecordObjectType ($ name )
0 commit comments