From 49f6ba76e8a02c1f3152893c8b775bd95ae700ab Mon Sep 17 00:00:00 2001 From: Simon Podlipsky Date: Wed, 22 May 2024 16:14:34 +0200 Subject: [PATCH] fix: add AssertReturnDynamicFunctionReturnTypeExtension (#49) --- composer.json | 2 +- phpcs.xml.dist | 1 + phpstan-extension.neon | 5 ++ ...turnDynamicFunctionReturnTypeExtension.php | 52 +++++++++++++++++++ ...tReturnFunctionTypeSpecifyingExtension.php | 33 ++++++++---- tests/AssertTest.php | 3 +- 6 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 phpstan/AssertReturnDynamicFunctionReturnTypeExtension.php diff --git a/composer.json b/composer.json index 9ccb03b..40a4c68 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,7 @@ "infection/infection": "^0.28.0", "php-ds/php-ds": "^1.4", "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.3", + "phpstan/phpstan": "^1.11", "phpstan/phpstan-phpunit": "^1.0.0", "phpunit/phpunit": "^11.0", "shipmonk/composer-dependency-analyser": "^1.5" diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 6e33a03..566dc6a 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -8,6 +8,7 @@ composer-dependency-analyser.php + phpstan/ src/ tests/ diff --git a/phpstan-extension.neon b/phpstan-extension.neon index e4fde26..4e8865d 100644 --- a/phpstan-extension.neon +++ b/phpstan-extension.neon @@ -3,3 +3,8 @@ services: class: Cdn77\Functions\PHPStan\AssertReturnFunctionTypeSpecifyingExtension tags: - phpstan.typeSpecifier.functionTypeSpecifyingExtension + + - + class: Cdn77\Functions\PHPStan\AssertReturnDynamicFunctionReturnTypeExtension + tags: + - phpstan.broker.dynamicFunctionReturnTypeExtension diff --git a/phpstan/AssertReturnDynamicFunctionReturnTypeExtension.php b/phpstan/AssertReturnDynamicFunctionReturnTypeExtension.php new file mode 100644 index 0000000..c15fa2d --- /dev/null +++ b/phpstan/AssertReturnDynamicFunctionReturnTypeExtension.php @@ -0,0 +1,52 @@ +getName() === 'Cdn77\Functions\assert_return'; + } + + public function getTypeFromFunctionCall( + FunctionReflection $functionReflection, + FuncCall $functionCall, + Scope $scope, + ): Type|null { + $arg1 = $functionCall->getArgs()[1]->value; + assert($arg1 instanceof FuncCall, 'Second argument of assert_return must be a function call'); + + $call = new FuncCall($arg1->name, [$functionCall->getArgs()[0]], $arg1->getAttributes()); + + $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition( + $scope, + $call, + TypeSpecifierContext::createTruthy(), + ); + + return $specifiedTypes->getSureTypes()['$value'][1] ?? null; + } + + public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void + { + $this->typeSpecifier = $typeSpecifier; + } +} diff --git a/phpstan/AssertReturnFunctionTypeSpecifyingExtension.php b/phpstan/AssertReturnFunctionTypeSpecifyingExtension.php index 96e8286..c86b7b9 100644 --- a/phpstan/AssertReturnFunctionTypeSpecifyingExtension.php +++ b/phpstan/AssertReturnFunctionTypeSpecifyingExtension.php @@ -1,4 +1,6 @@ -getName() === 'Cdn77\Functions\assert_return'; -// && isset($node->getArgs()[0]); } - public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes - { + public function specifyTypes( + FunctionReflection $functionReflection, + FuncCall $node, + Scope $scope, + TypeSpecifierContext $context, + ): SpecifiedTypes { $arg1 = $node->getArgs()[1]->value; assert($arg1 instanceof FuncCall, 'Second argument of assert_return must be a function call'); - $new = new \PhpParser\Node\Expr\FuncCall($arg1->name, [$node->getArgs()[0]], $arg1->getAttributes()); - return $this->typeSpecifier->specifyTypesInCondition($scope, $new, TypeSpecifierContext::createTruthy()); + + $call = new FuncCall($arg1->name, [$node->getArgs()[0]], $arg1->getAttributes()); + + return $this->typeSpecifier->specifyTypesInCondition($scope, $call, TypeSpecifierContext::createTruthy()); } public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void { $this->typeSpecifier = $typeSpecifier; } - } diff --git a/tests/AssertTest.php b/tests/AssertTest.php index ca1edca..6f73512 100644 --- a/tests/AssertTest.php +++ b/tests/AssertTest.php @@ -25,8 +25,9 @@ public function testAssertReturn(): void public function phpstanType(mixed $value): void { - $_ = assert_return($value, is_int(...)); + $return = assert_return($value, is_int(...)); assertType('int', $value); + assertType('int', $return); } }