diff --git a/extension.neon b/extension.neon index c0851f4..caab1d1 100644 --- a/extension.neon +++ b/extension.neon @@ -43,6 +43,16 @@ services: - phpstan.broker.propertiesClassReflectionExtension - phpstan.broker.methodsClassReflectionExtension + - + class: PHPStan\Type\Nette\CachingFallbacksDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + + - + class: PHPStan\Type\Nette\CachingSaveDynamicReturnTypeExtension + tags: + - phpstan.broker.dynamicMethodReturnTypeExtension + - class: PHPStan\Type\Nette\ComponentModelArrayAccessDynamicReturnTypeExtension tags: diff --git a/src/Type/Nette/CachingFallbacksDynamicReturnTypeExtension.php b/src/Type/Nette/CachingFallbacksDynamicReturnTypeExtension.php new file mode 100644 index 0000000..73c1a02 --- /dev/null +++ b/src/Type/Nette/CachingFallbacksDynamicReturnTypeExtension.php @@ -0,0 +1,52 @@ + */ + private $fallbackMethods = [ + 'load' => 1, + 'call' => 0, + 'wrap' => 0, + ]; + + public function getClass(): string + { + return 'Nette\Caching\Cache'; + } + + public function isMethodSupported(MethodReflection $methodReflection): bool + { + return array_key_exists($methodReflection->getName(), $this->fallbackMethods); + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type + { + $fallbackParameterIndex = $this->fallbackMethods[$methodReflection->getName()]; + + if ($fallbackParameterIndex >= count($methodCall->args)) { + return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + } + + $fallbackParameterType = $scope->getType($methodCall->args[$fallbackParameterIndex]->value); + if (!$fallbackParameterType->isCallable()->yes()) { + return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + } + + return ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->args, $fallbackParameterType->getCallableParametersAcceptors($scope))->getReturnType(); + } + +} diff --git a/src/Type/Nette/CachingSaveDynamicReturnTypeExtension.php b/src/Type/Nette/CachingSaveDynamicReturnTypeExtension.php new file mode 100644 index 0000000..f4e3024 --- /dev/null +++ b/src/Type/Nette/CachingSaveDynamicReturnTypeExtension.php @@ -0,0 +1,38 @@ +getName() === 'save'; + } + + public function getTypeFromMethodCall( + MethodReflection $methodReflection, + MethodCall $methodCall, + Scope $scope + ): Type + { + if (count($methodCall->args) < 2) { + return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + } + + return $scope->getType($methodCall->args[1]->value); + } + +}