6565use PHPStan \DependencyInjection \Reflection \ClassReflectionExtensionRegistryProvider ;
6666use PHPStan \DependencyInjection \Type \DynamicThrowTypeExtensionProvider ;
6767use PHPStan \DependencyInjection \Type \ParameterClosureTypeExtensionProvider ;
68+ use PHPStan \DependencyInjection \Type \DynamicParameterTypeExtensionProvider ;
6869use PHPStan \DependencyInjection \Type \ParameterOutTypeExtensionProvider ;
6970use PHPStan \File \FileHelper ;
7071use PHPStan \File \FileReader ;
@@ -262,6 +263,7 @@ public function __construct(
262263 private readonly DynamicThrowTypeExtensionProvider $ dynamicThrowTypeExtensionProvider ,
263264 private readonly ReadWritePropertiesExtensionProvider $ readWritePropertiesExtensionProvider ,
264265 private readonly ParameterClosureTypeExtensionProvider $ parameterClosureTypeExtensionProvider ,
266+ private readonly DynamicParameterTypeExtensionProvider $ dynamicParameterTypeExtensionProvider ,
265267 private readonly ScopeFactory $ scopeFactory ,
266268 private readonly bool $ polluteScopeWithLoopInitialAssignments ,
267269 private readonly bool $ polluteScopeWithAlwaysIterableForeach ,
@@ -5002,6 +5004,12 @@ private function processArgs(
50025004
50035005 if ($ overwritingParameterType !== null ) {
50045006 $ parameterType = $ overwritingParameterType ;
5007+ } else {
5008+ $ overwritingParameterType = $ this ->getDynamicParameterTypeFromParameterTypeExtension ($ callLike , $ calleeReflection , $ parameter , $ scopeToPass );
5009+
5010+ if ($ overwritingParameterType !== null ) {
5011+ $ parameterType = $ overwritingParameterType ;
5012+ }
50055013 }
50065014 }
50075015
@@ -5054,6 +5062,12 @@ private function processArgs(
50545062
50555063 if ($ overwritingParameterType !== null ) {
50565064 $ parameterType = $ overwritingParameterType ;
5065+ } else {
5066+ $ overwritingParameterType = $ this ->getDynamicParameterTypeFromParameterTypeExtension ($ callLike , $ calleeReflection , $ parameter , $ scopeToPass );
5067+
5068+ if ($ overwritingParameterType !== null ) {
5069+ $ parameterType = $ overwritingParameterType ;
5070+ }
50575071 }
50585072 }
50595073
@@ -5065,6 +5079,15 @@ private function processArgs(
50655079 }
50665080 } else {
50675081 $ exprType = $ scope ->getType ($ arg ->value );
5082+
5083+ if ($ parameter !== null ) {
5084+ $ overwritingParameterType = $ this ->getDynamicParameterTypeFromParameterTypeExtension ($ callLike , $ calleeReflection , $ parameter , $ scopeToPass );
5085+
5086+ if ($ overwritingParameterType !== null ) {
5087+ $ exprType = $ overwritingParameterType ;
5088+ }
5089+ }
5090+
50685091 $ exprResult = $ this ->processExprNode ($ stmt , $ arg ->value , $ scopeToPass , $ nodeCallback , $ context ->enterDeep ());
50695092 $ throwPoints = array_merge ($ throwPoints , $ exprResult ->getThrowPoints ());
50705093 $ impurePoints = array_merge ($ impurePoints , $ exprResult ->getImpurePoints ());
@@ -5225,6 +5248,36 @@ private function getParameterTypeFromParameterClosureTypeExtension(CallLike $cal
52255248 return null ;
52265249 }
52275250
5251+ /**
5252+ * @param MethodReflection|FunctionReflection|null $calleeReflection
5253+ */
5254+ private function getDynamicParameterTypeFromParameterTypeExtension (CallLike $ callLike , $ calleeReflection , ParameterReflection $ parameter , MutatingScope $ scope ): ?Type
5255+ {
5256+ if ($ callLike instanceof FuncCall && $ calleeReflection instanceof FunctionReflection) {
5257+ foreach ($ this ->dynamicParameterTypeExtensionProvider ->getFunctionDynamicParameterTypeExtensions () as $ functionDynamicParameterTypeExtension ) {
5258+ if ($ functionDynamicParameterTypeExtension ->isFunctionSupported ($ calleeReflection , $ parameter )) {
5259+ return $ functionDynamicParameterTypeExtension ->getTypeFromFunctionCall ($ calleeReflection , $ callLike , $ parameter , $ scope );
5260+ }
5261+ }
5262+ } elseif ($ calleeReflection instanceof MethodReflection) {
5263+ if ($ callLike instanceof StaticCall) {
5264+ foreach ($ this ->dynamicParameterTypeExtensionProvider ->getStaticMethodDynamicParameterTypeExtensions () as $ staticMethodDynamicParameterTypeExtension ) {
5265+ if ($ staticMethodDynamicParameterTypeExtension ->isStaticMethodSupported ($ calleeReflection , $ parameter )) {
5266+ return $ staticMethodDynamicParameterTypeExtension ->getTypeFromStaticMethodCall ($ calleeReflection , $ callLike , $ parameter , $ scope );
5267+ }
5268+ }
5269+ } elseif ($ callLike instanceof MethodCall) {
5270+ foreach ($ this ->dynamicParameterTypeExtensionProvider ->getMethodDynamicParameterTypeExtensions () as $ methodDynamicParameterTypeExtension ) {
5271+ if ($ methodDynamicParameterTypeExtension ->isMethodSupported ($ calleeReflection , $ parameter )) {
5272+ return $ methodDynamicParameterTypeExtension ->getTypeFromMethodCall ($ calleeReflection , $ callLike , $ parameter , $ scope );
5273+ }
5274+ }
5275+ }
5276+ }
5277+
5278+ return null ;
5279+ }
5280+
52285281 /**
52295282 * @param MethodReflection|FunctionReflection|null $calleeReflection
52305283 */
0 commit comments