From 67f9420cba9fa45501cdca87770d50c5c22bd508 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 13 Mar 2024 10:34:36 +0100 Subject: [PATCH] Check conditional types in `@param-out` --- .../PhpDoc/ConditionalReturnTypeRuleHelper.php | 14 ++++++++++++-- .../PhpDoc/MethodConditionalReturnTypeRuleTest.php | 4 ++++ .../PhpDoc/data/method-conditional-return-type.php | 12 ++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php b/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php index b3ff188e60..deceb4cc58 100644 --- a/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php +++ b/src/Rules/PhpDoc/ConditionalReturnTypeRuleHelper.php @@ -2,7 +2,7 @@ namespace PHPStan\Rules\PhpDoc; -use PHPStan\Reflection\ParametersAcceptor; +use PHPStan\Reflection\ParametersAcceptorWithPhpDocs; use PHPStan\Rules\RuleError; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\ConditionalType; @@ -23,7 +23,7 @@ class ConditionalReturnTypeRuleHelper /** * @return RuleError[] */ - public function check(ParametersAcceptor $acceptor): array + public function check(ParametersAcceptorWithPhpDocs $acceptor): array { $conditionalTypes = []; $parametersByName = []; @@ -36,6 +36,16 @@ public function check(ParametersAcceptor $acceptor): array return $traverse($type); }); + if ($parameter->getOutType() !== null) { + TypeTraverser::map($parameter->getOutType(), static function (Type $type, callable $traverse) use (&$conditionalTypes): Type { + if ($type instanceof ConditionalType || $type instanceof ConditionalTypeForParameter) { + $conditionalTypes[] = $type; + } + + return $traverse($type); + }); + } + $parametersByName[$parameter->getName()] = $parameter; } diff --git a/tests/PHPStan/Rules/PhpDoc/MethodConditionalReturnTypeRuleTest.php b/tests/PHPStan/Rules/PhpDoc/MethodConditionalReturnTypeRuleTest.php index 56feeb7ae5..48258202dc 100644 --- a/tests/PHPStan/Rules/PhpDoc/MethodConditionalReturnTypeRuleTest.php +++ b/tests/PHPStan/Rules/PhpDoc/MethodConditionalReturnTypeRuleTest.php @@ -63,6 +63,10 @@ public function testRule(): void 'Condition "array{foo: string} is array{foo: int}" in conditional return type is always false.', 156, ], + [ + 'Condition "int is int" in conditional return type is always true.', + 185, + ], ]); } diff --git a/tests/PHPStan/Rules/PhpDoc/data/method-conditional-return-type.php b/tests/PHPStan/Rules/PhpDoc/data/method-conditional-return-type.php index c8f0cb05fd..7829e8c71a 100644 --- a/tests/PHPStan/Rules/PhpDoc/data/method-conditional-return-type.php +++ b/tests/PHPStan/Rules/PhpDoc/data/method-conditional-return-type.php @@ -175,3 +175,15 @@ public function foo(): bool } } + +class ParamOut +{ + + /** + * @param-out ($i is int ? 1 : 2) $out + */ + public function doFoo(int $i, &$out) { + + } + +}