From 6a33cc292a8f7c25725e2ed3bedbe3376832cfd7 Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Wed, 23 Apr 2025 17:30:42 +0300 Subject: [PATCH 1/3] add enums to in_array rule --- src/PhpStan/FunctionStrictModeRule.php | 2 +- tests/PhpStan/FunctionStrictModeRuleTest.php | 12 ++++++---- .../Resources/function-strict-mode.php | 23 +++++++++++++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/PhpStan/FunctionStrictModeRule.php b/src/PhpStan/FunctionStrictModeRule.php index 40c5fd7..7cfe378 100644 --- a/src/PhpStan/FunctionStrictModeRule.php +++ b/src/PhpStan/FunctionStrictModeRule.php @@ -100,7 +100,7 @@ private function analyzeArgs(Node\Expr\FuncCall $node, Scope $scope): array private function isSafeToCompareNonStrict(Type $argType): bool { - if ($argType->isObject()->yes()) { + if ($argType->isObject()->yes() && $argType->isEnum()->no()) { return false; } diff --git a/tests/PhpStan/FunctionStrictModeRuleTest.php b/tests/PhpStan/FunctionStrictModeRuleTest.php index 3fe2ef7..179b4e0 100644 --- a/tests/PhpStan/FunctionStrictModeRuleTest.php +++ b/tests/PhpStan/FunctionStrictModeRuleTest.php @@ -31,11 +31,13 @@ public function shouldSuccessProcess(): void $this->analyse( [__DIR__.'/Resources/function-strict-mode.php'], [ - ['The function in_array must be used in strict mode.', 16], - ['The function in_array must be used in strict mode.', 17], - ['The function in_array must be used in strict mode.', 18], - ['The function in_array must be used in strict mode.', 21], - ['The function in_array must be used in strict mode.', 23], + ['The function in_array must be used in strict mode.', 26], + ['The function in_array must be used in strict mode.', 27], + ['The function in_array must be used in strict mode.', 28], + ['The function in_array must be used in strict mode.', 31], + ['The function in_array must be used in strict mode.', 33], + ['The function in_array must be used in strict mode.', 35], + ['The function in_array must be used in strict mode.', 55], ], ); } diff --git a/tests/PhpStan/Resources/function-strict-mode.php b/tests/PhpStan/Resources/function-strict-mode.php index ebd750d..09ae750 100644 --- a/tests/PhpStan/Resources/function-strict-mode.php +++ b/tests/PhpStan/Resources/function-strict-mode.php @@ -1,5 +1,15 @@ foo, [SomeEnum::Foo, SomeEnum::Bar]); + } +} From 7402e402ff9782054fa9bc9d7003004b4772ebbd Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Thu, 24 Apr 2025 11:39:50 +0300 Subject: [PATCH 2/3] add check third parameter for objects --- src/PhpStan/FunctionStrictModeRule.php | 68 ++++++++----------- tests/PhpStan/FunctionStrictModeRuleTest.php | 3 +- .../Resources/function-strict-mode.php | 3 +- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/PhpStan/FunctionStrictModeRule.php b/src/PhpStan/FunctionStrictModeRule.php index 7cfe378..8792d2f 100644 --- a/src/PhpStan/FunctionStrictModeRule.php +++ b/src/PhpStan/FunctionStrictModeRule.php @@ -15,7 +15,6 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; -use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\Type; @@ -48,14 +47,30 @@ public function processNode(Node $node, Scope $scope): array return []; } - if (3 === \count($node->args)) { - if (!$node->args[2] instanceof Node\Arg) { - return []; - } + if (!$node->args[0] instanceof Node\Arg || !$node->args[1] instanceof Node\Arg) { + return []; + } + + $isThreeArgs = 3 === \count($node->args); + $needleType = $scope->getType($node->args[0]->value); + $isNeedleScalarType = $this->isSafeToCompareNonStrict($needleType); + + if ($isThreeArgs && !$node->args[2] instanceof Node\Arg) { + return []; + } + if (!$isThreeArgs && $isNeedleScalarType) { + return [ + RuleErrorBuilder::message('The function in_array must be used in strict mode.') + ->identifier('functionCall.strictMode') + ->build(), + ]; + } + + if ($isThreeArgs) { $modeType = $scope->getType($node->args[2]->value); - if ($modeType->isFalse()->yes()) { + if ($isNeedleScalarType && $modeType->isFalse()->yes()) { return [ RuleErrorBuilder::message('The function in_array must be used in strict mode.') ->identifier('functionCall.strictMode') @@ -63,44 +78,21 @@ public function processNode(Node $node, Scope $scope): array ]; } - return []; - } - - return $this->analyzeArgs($node, $scope); - } - - /** - * Analyze function arguments types - * - * @param Node\Expr\FuncCall $node - * @param Scope $scope - * - * @return list - */ - private function analyzeArgs(Node\Expr\FuncCall $node, Scope $scope): array - { - if (!$node->args[0] instanceof Node\Arg || !$node->args[1] instanceof Node\Arg) { - return []; - } - - $needleType = $scope->getType($node->args[0]->value); - $isNeedleScalarType = $this->isSafeToCompareNonStrict($needleType); - - if (!$isNeedleScalarType) { - return []; + if (!$isNeedleScalarType && $modeType->isTrue()->yes()) { + return [ + RuleErrorBuilder::message('You don\'t need to use strict mode when comparison objects.') + ->identifier('functionCall.strictMode') + ->build(), + ]; + } } - return [ - RuleErrorBuilder::message('The function in_array must be used in strict mode.') - ->identifier('functionCall.strictMode') - ->build(), - ]; - + return []; } private function isSafeToCompareNonStrict(Type $argType): bool { - if ($argType->isObject()->yes() && $argType->isEnum()->no()) { + if ($argType->isObject()->yes()) { return false; } diff --git a/tests/PhpStan/FunctionStrictModeRuleTest.php b/tests/PhpStan/FunctionStrictModeRuleTest.php index 179b4e0..721eec1 100644 --- a/tests/PhpStan/FunctionStrictModeRuleTest.php +++ b/tests/PhpStan/FunctionStrictModeRuleTest.php @@ -37,7 +37,8 @@ public function shouldSuccessProcess(): void ['The function in_array must be used in strict mode.', 31], ['The function in_array must be used in strict mode.', 33], ['The function in_array must be used in strict mode.', 35], - ['The function in_array must be used in strict mode.', 55], + ['You don\'t need to use strict mode when comparison objects.', 36], + ['You don\'t need to use strict mode when comparison objects.', 56], ], ); } diff --git a/tests/PhpStan/Resources/function-strict-mode.php b/tests/PhpStan/Resources/function-strict-mode.php index 09ae750..2f0d92d 100644 --- a/tests/PhpStan/Resources/function-strict-mode.php +++ b/tests/PhpStan/Resources/function-strict-mode.php @@ -33,6 +33,7 @@ public function foo() : bool $res = \in_array(rand(0, 1) ? 1 : '1', [1, 2, 3]); $res = \in_array('a', [SomeEnum::Foo, SomeEnum::Bar]); +$res = \in_array([new stdClass()], [new stdClass(), new stdClass()], true); // ignore $strict = rand(0, 1) === 1; @@ -52,6 +53,6 @@ class Some23 { function baz() : void { - $res = \in_array($this->foo, [SomeEnum::Foo, SomeEnum::Bar]); + $res = \in_array($this->foo, [SomeEnum::Foo, SomeEnum::Bar], true); } } From bad6c0bd99563773f350d087c85db4678b4248ab Mon Sep 17 00:00:00 2001 From: Anastasiia Sherekina Date: Thu, 24 Apr 2025 11:42:49 +0300 Subject: [PATCH 3/3] add check third parameter for objects --- src/PhpStan/FunctionStrictModeRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PhpStan/FunctionStrictModeRule.php b/src/PhpStan/FunctionStrictModeRule.php index 8792d2f..d0f7f8c 100644 --- a/src/PhpStan/FunctionStrictModeRule.php +++ b/src/PhpStan/FunctionStrictModeRule.php @@ -67,7 +67,7 @@ public function processNode(Node $node, Scope $scope): array ]; } - if ($isThreeArgs) { + if ($isThreeArgs && $node->args[2] instanceof Node\Arg) { $modeType = $scope->getType($node->args[2]->value); if ($isNeedleScalarType && $modeType->isFalse()->yes()) {