From f5b198c9801282d7002f5310d5ff5318eec54465 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Thu, 15 Feb 2024 06:56:04 +0000 Subject: [PATCH] ArrayFilterRule - tip message about `treatPhpDocTypesAsCertain` --- src/Rules/Functions/ArrayFilterRule.php | 51 ++++++++++++++----- .../Rules/Functions/ArrayFilterRuleTest.php | 6 +++ 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/Rules/Functions/ArrayFilterRule.php b/src/Rules/Functions/ArrayFilterRule.php index c34dde0687..69ad1282a5 100644 --- a/src/Rules/Functions/ArrayFilterRule.php +++ b/src/Rules/Functions/ArrayFilterRule.php @@ -57,11 +57,18 @@ public function processNode(Node $node, Scope $scope): array if ($arrayType->isIterableAtLeastOnce()->no()) { $message = 'Parameter #1 $array (%s) to function array_filter is empty, call has no effect.'; + $errorBuilder = RuleErrorBuilder::message(sprintf( + $message, + $arrayType->describe(VerbosityLevel::value()), + )); + if ($this->treatPhpDocTypesAsCertain) { + $nativeArrayType = $scope->getNativeType($args[0]->value); + if (!$nativeArrayType->isIterableAtLeastOnce()->no()) { + $errorBuilder->tip('Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'); + } + } return [ - RuleErrorBuilder::message(sprintf( - $message, - $arrayType->describe(VerbosityLevel::value()), - ))->build(), + $errorBuilder->build(), ]; } @@ -70,21 +77,41 @@ public function processNode(Node $node, Scope $scope): array if ($isSuperType->no()) { $message = 'Parameter #1 $array (%s) to function array_filter does not contain falsy values, the array will always stay the same.'; + $errorBuilder = RuleErrorBuilder::message(sprintf( + $message, + $arrayType->describe(VerbosityLevel::value()), + )); + + if ($this->treatPhpDocTypesAsCertain) { + $nativeArrayType = $scope->getNativeType($args[0]->value); + $isNativeSuperType = $falsyType->isSuperTypeOf($nativeArrayType->getIterableValueType()); + if (!$isNativeSuperType->no()) { + $errorBuilder->tip('Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'); + } + } + return [ - RuleErrorBuilder::message(sprintf( - $message, - $arrayType->describe(VerbosityLevel::value()), - ))->build(), + $errorBuilder->build(), ]; } if ($isSuperType->yes()) { $message = 'Parameter #1 $array (%s) to function array_filter contains falsy values only, the result will always be an empty array.'; + $errorBuilder = RuleErrorBuilder::message(sprintf( + $message, + $arrayType->describe(VerbosityLevel::value()), + )); + + if ($this->treatPhpDocTypesAsCertain) { + $nativeArrayType = $scope->getNativeType($args[0]->value); + $isNativeSuperType = $falsyType->isSuperTypeOf($nativeArrayType->getIterableValueType()); + if (!$isNativeSuperType->yes()) { + $errorBuilder->tip('Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'); + } + } + return [ - RuleErrorBuilder::message(sprintf( - $message, - $arrayType->describe(VerbosityLevel::value()), - ))->build(), + $errorBuilder->build(), ]; } diff --git a/tests/PHPStan/Rules/Functions/ArrayFilterRuleTest.php b/tests/PHPStan/Rules/Functions/ArrayFilterRuleTest.php index 1c62d47af2..95ac9ed295 100644 --- a/tests/PHPStan/Rules/Functions/ArrayFilterRuleTest.php +++ b/tests/PHPStan/Rules/Functions/ArrayFilterRuleTest.php @@ -20,6 +20,7 @@ protected function getRule(): Rule public function testFile(): void { + $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; $expectedErrors = [ [ 'Parameter #1 $array (array{1, 3}) to function array_filter does not contain falsy values, the array will always stay the same.', @@ -40,6 +41,7 @@ public function testFile(): void [ 'Parameter #1 $array (array) to function array_filter does not contain falsy values, the array will always stay the same.', 20, + $tipText, ], [ 'Parameter #1 $array (array{0}) to function array_filter contains falsy values only, the result will always be an empty array.', @@ -60,6 +62,7 @@ public function testFile(): void [ 'Parameter #1 $array (array) to function array_filter contains falsy values only, the result will always be an empty array.', 27, + $tipText, ], [ 'Parameter #1 $array (array{}) to function array_filter is empty, call has no effect.', @@ -72,10 +75,13 @@ public function testFile(): void public function testBug2065WithPhpDocTypesAsCertain(): void { + $tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting treatPhpDocTypesAsCertain: false in your %configurationFile%.'; + $expectedErrors = [ [ 'Parameter #1 $array (array) to function array_filter does not contain falsy values, the array will always stay the same.', 12, + $tipText, ], ];