8
8
use PHPStan \Analyser \Scope ;
9
9
use PHPStan \DependencyInjection \AutowiredParameter ;
10
10
use PHPStan \DependencyInjection \AutowiredService ;
11
+ use PHPStan \DependencyInjection \Type \DynamicParameterTypeExtensionProvider ;
11
12
use PHPStan \Reflection \ExtendedParameterReflection ;
13
+ use PHPStan \Reflection \FunctionReflection ;
14
+ use PHPStan \Reflection \MethodReflection ;
12
15
use PHPStan \Reflection \ParameterReflection ;
13
16
use PHPStan \Reflection \ParametersAcceptor ;
14
17
use PHPStan \Reflection \ResolvedFunctionVariant ;
@@ -46,6 +49,7 @@ public function __construct(
46
49
private NullsafeCheck $ nullsafeCheck ,
47
50
private UnresolvableTypeHelper $ unresolvableTypeHelper ,
48
51
private PropertyReflectionFinder $ propertyReflectionFinder ,
52
+ private DynamicParameterTypeExtensionProvider $ dynamicParameterTypeExtensionProvider ,
49
53
#[AutowiredParameter(ref: '%checkFunctionArgumentTypes% ' )]
50
54
private bool $ checkArgumentTypes ,
51
55
#[AutowiredParameter]
@@ -66,6 +70,7 @@ public function check(
66
70
ParametersAcceptor $ parametersAcceptor ,
67
71
Scope $ scope ,
68
72
bool $ isBuiltin ,
73
+ MethodReflection |FunctionReflection |null $ calleeReflection ,
69
74
Node \Expr \FuncCall |Node \Expr \MethodCall |Node \Expr \StaticCall |Node \Expr \New_ $ funcCall ,
70
75
string $ nodeType ,
71
76
TrinaryLogic $ acceptsNamedArguments ,
@@ -349,6 +354,13 @@ public function check(
349
354
if ($ this ->checkArgumentTypes ) {
350
355
$ parameterType = TypeUtils::resolveLateResolvableTypes ($ parameter ->getType ());
351
356
357
+ if (! $ funcCall instanceof Node \Expr \New_) {
358
+ $ overriddenType = $ this ->getParameterTypeFromDynamicExtension ($ funcCall , $ calleeReflection , $ parameter , $ scope );
359
+ if ($ overriddenType !== null ) {
360
+ $ parameterType = $ overriddenType ;
361
+ }
362
+ }
363
+
352
364
if (
353
365
!$ parameter ->passedByReference ()->createsNewVariable ()
354
366
|| (!$ isBuiltin && !$ argumentValueType instanceof ErrorType)
@@ -681,4 +693,50 @@ private function describeParameter(ParameterReflection $parameter, int|string|nu
681
693
return implode (' ' , $ parts );
682
694
}
683
695
696
+ private function getParameterTypeFromDynamicExtension (
697
+ Node \Expr \FuncCall |Node \Expr \MethodCall |Node \Expr \StaticCall $ funcCall ,
698
+ MethodReflection |FunctionReflection |null $ calleeReflection ,
699
+ ParameterReflection $ parameter ,
700
+ Scope $ scope ,
701
+ ): ?Type
702
+ {
703
+ if ($ calleeReflection === null ) {
704
+ return null ;
705
+ }
706
+
707
+ if ($ funcCall instanceof Node \Expr \FuncCall && $ calleeReflection instanceof FunctionReflection) {
708
+ foreach ($ this ->dynamicParameterTypeExtensionProvider ->getDynamicFunctionParameterTypeExtensions () as $ extension ) {
709
+ if (!$ extension ->isFunctionSupported ($ calleeReflection , $ parameter )) {
710
+ continue ;
711
+ }
712
+ $ type = $ extension ->getTypeFromFunctionCall ($ calleeReflection , $ funcCall , $ parameter , $ scope );
713
+ if ($ type !== null ) {
714
+ return $ type ;
715
+ }
716
+ }
717
+ } elseif ($ funcCall instanceof Node \Expr \StaticCall && $ calleeReflection instanceof MethodReflection) {
718
+ foreach ($ this ->dynamicParameterTypeExtensionProvider ->getDynamicStaticMethodParameterTypeExtensions () as $ extension ) {
719
+ if (!$ extension ->isStaticMethodSupported ($ calleeReflection , $ parameter )) {
720
+ continue ;
721
+ }
722
+ $ type = $ extension ->getTypeFromStaticMethodCall ($ calleeReflection , $ funcCall , $ parameter , $ scope );
723
+ if ($ type !== null ) {
724
+ return $ type ;
725
+ }
726
+ }
727
+ } elseif ($ funcCall instanceof Node \Expr \MethodCall && $ calleeReflection instanceof MethodReflection) {
728
+ foreach ($ this ->dynamicParameterTypeExtensionProvider ->getDynamicMethodParameterTypeExtensions () as $ extension ) {
729
+ if (!$ extension ->isMethodSupported ($ calleeReflection , $ parameter )) {
730
+ continue ;
731
+ }
732
+ $ type = $ extension ->getTypeFromMethodCall ($ calleeReflection , $ funcCall , $ parameter , $ scope );
733
+ if ($ type !== null ) {
734
+ return $ type ;
735
+ }
736
+ }
737
+ }
738
+
739
+ return null ;
740
+ }
741
+
684
742
}
0 commit comments