From 75f0458a7d82d1daff8d30939fef3ca10563bace Mon Sep 17 00:00:00 2001 From: ondrejmirtes <104888+ondrejmirtes@users.noreply.github.com> Date: Tue, 20 Aug 2024 00:03:16 +0000 Subject: [PATCH 1/8] Update PhpStorm stubs --- composer.json | 2 +- composer.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/composer.json b/composer.json index 9c2e3570b9..3a722a9282 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "hoa/compiler": "3.17.08.08", "hoa/exception": "^1.0", "hoa/file": "1.17.07.11", - "jetbrains/phpstorm-stubs": "dev-master#bdc8acd7c04c0c87197849c7cdd27e44b67b56c7", + "jetbrains/phpstorm-stubs": "dev-master#5686f9ceebde3d9338bea53b78d70ebde5fb5710", "nette/bootstrap": "^3.0", "nette/di": "^3.1.4", "nette/neon": "3.3.3", diff --git a/composer.lock b/composer.lock index cbfc81e3da..7039f2bc07 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b8e13e2eb99acb0933ff8956a498ffe4", + "content-hash": "8d65a8ad1ba3923e57e72376e8dfefed", "packages": [ { "name": "clue/ndjson-react", @@ -1434,19 +1434,19 @@ "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "bdc8acd7c04c0c87197849c7cdd27e44b67b56c7" + "reference": "5686f9ceebde3d9338bea53b78d70ebde5fb5710" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/bdc8acd7c04c0c87197849c7cdd27e44b67b56c7", - "reference": "bdc8acd7c04c0c87197849c7cdd27e44b67b56c7", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/5686f9ceebde3d9338bea53b78d70ebde5fb5710", + "reference": "5686f9ceebde3d9338bea53b78d70ebde5fb5710", "shasum": "" }, "require-dev": { - "friendsofphp/php-cs-fixer": "v3.46.0", - "nikic/php-parser": "v5.0.0", - "phpdocumentor/reflection-docblock": "5.3.0", - "phpunit/phpunit": "10.5.5" + "friendsofphp/php-cs-fixer": "v3.61.1", + "nikic/php-parser": "v5.1.0", + "phpdocumentor/reflection-docblock": "5.4.1", + "phpunit/phpunit": "11.3.0" }, "default-branch": true, "type": "library", @@ -1474,7 +1474,7 @@ "support": { "source": "https://github.com/JetBrains/phpstorm-stubs/tree/master" }, - "time": "2024-07-05T11:52:49+00:00" + "time": "2024-07-24T19:11:43+00:00" }, { "name": "nette/bootstrap", From a08ba6452d151fb9b28185fb70d7d89113f15fa7 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 10:35:56 +0200 Subject: [PATCH 2/8] Fix tests --- .../CallToMethodStatementWithoutSideEffectsRuleTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php index f1d3d5902d..50cc964e00 100644 --- a/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php @@ -20,10 +20,6 @@ protected function getRule(): Rule public function testRule(): void { $this->analyse([__DIR__ . '/data/method-call-statement-no-side-effects.php'], [ - [ - 'Call to method DateTimeImmutable::modify() on a separate line has no effect.', - 15, - ], [ 'Call to static method DateTimeImmutable::createFromFormat() on a separate line has no effect.', 16, From 126684aab9af951a97138caf112d6d19ee89765b Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 13:12:34 +0200 Subject: [PATCH 3/8] Rewrite rule --- ...lToMethodStatementWithoutSideEffectsRule.php | 17 +++++++++-------- ...ethodStatementWithoutSideEffectsRuleTest.php | 4 ++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index ed78c46f17..ab84c82ad8 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -5,6 +5,7 @@ use PhpParser\Node; use PHPStan\Analyser\NullsafeOperatorHelper; use PHPStan\Analyser\Scope; +use PHPStan\Node\NoopExpressionNode; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; @@ -14,7 +15,7 @@ use function sprintf; /** - * @implements Rule + * @implements Rule */ final class CallToMethodStatementWithoutSideEffectsRule implements Rule { @@ -25,18 +26,18 @@ public function __construct(private RuleLevelHelper $ruleLevelHelper) public function getNodeType(): string { - return Node\Stmt\Expression::class; + return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope): array { - if ($node->expr instanceof Node\Expr\NullsafeMethodCall) { - $scope = $scope->filterByTruthyValue(new Node\Expr\BinaryOp\NotIdentical($node->expr->var, new Node\Expr\ConstFetch(new Node\Name('null')))); - } elseif (!$node->expr instanceof Node\Expr\MethodCall) { + $methodCall = $node->getOriginalExpr(); + if ($methodCall instanceof Node\Expr\NullsafeMethodCall) { + $scope = $scope->filterByTruthyValue(new Node\Expr\BinaryOp\NotIdentical($methodCall->var, new Node\Expr\ConstFetch(new Node\Name('null')))); + } elseif (!$methodCall instanceof Node\Expr\MethodCall) { return []; } - $methodCall = $node->expr; if (!$methodCall->name instanceof Node\Identifier) { return []; } @@ -61,8 +62,8 @@ public function processNode(Node $node, Scope $scope): array } $method = $calledOnType->getMethod($methodName, $scope); - if ($method->hasSideEffects()->no() || $node->expr->isFirstClassCallable()) { - if (!$node->expr->isFirstClassCallable()) { + if ($method->hasSideEffects()->no() || $methodCall->isFirstClassCallable()) { + if (!$methodCall->isFirstClassCallable()) { $throwsType = $method->getThrowType(); if ($throwsType !== null && !$throwsType->isVoid()->yes()) { return []; diff --git a/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php index 50cc964e00..f1d3d5902d 100644 --- a/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToMethodStatementWithoutSideEffectsRuleTest.php @@ -20,6 +20,10 @@ protected function getRule(): Rule public function testRule(): void { $this->analyse([__DIR__ . '/data/method-call-statement-no-side-effects.php'], [ + [ + 'Call to method DateTimeImmutable::modify() on a separate line has no effect.', + 15, + ], [ 'Call to static method DateTimeImmutable::createFromFormat() on a separate line has no effect.', 16, From 4fa1fe5d62a13e52b4d3e511c975a3d4a709bb94 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 13:19:43 +0200 Subject: [PATCH 4/8] Improve rewriting --- ...oMethodStatementWithoutSideEffectsRule.php | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index ab84c82ad8..f64b393e4c 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -62,30 +62,15 @@ public function processNode(Node $node, Scope $scope): array } $method = $calledOnType->getMethod($methodName, $scope); - if ($method->hasSideEffects()->no() || $methodCall->isFirstClassCallable()) { - if (!$methodCall->isFirstClassCallable()) { - $throwsType = $method->getThrowType(); - if ($throwsType !== null && !$throwsType->isVoid()->yes()) { - return []; - } - } - $methodResult = $scope->getType($methodCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { - return []; - } - - return [ - RuleErrorBuilder::message(sprintf( - 'Call to %s %s::%s() on a separate line has no effect.', - $method->isStatic() ? 'static method' : 'method', - $method->getDeclaringClass()->getDisplayName(), - $method->getName(), - ))->identifier('method.resultUnused')->build(), - ]; - } - - return []; + return [ + RuleErrorBuilder::message(sprintf( + 'Call to %s %s::%s() on a separate line has no effect.', + $method->isStatic() ? 'static method' : 'method', + $method->getDeclaringClass()->getDisplayName(), + $method->getName(), + ))->identifier('method.resultUnused')->build(), + ]; } } From 69a984460160d00be6b47df06a5d55059753e076 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 13:24:20 +0200 Subject: [PATCH 5/8] Rewrite more rules --- ...tructorStatementWithoutSideEffectsRule.php | 38 ++++++----------- ...oMethodStatementWithoutSideEffectsRule.php | 1 - ...cMethodStatementWithoutSideEffectsRule.php | 42 ++++++------------- 3 files changed, 25 insertions(+), 56 deletions(-) diff --git a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php index 00a2352c99..5b214e42dc 100644 --- a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php @@ -4,14 +4,14 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; +use PHPStan\Node\NoopExpressionNode; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\NeverType; use function sprintf; /** - * @implements Rule + * @implements Rule */ final class CallToConstructorStatementWithoutSideEffectsRule implements Rule { @@ -25,16 +25,16 @@ public function __construct( public function getNodeType(): string { - return Node\Stmt\Expression::class; + return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope): array { - if (!$node->expr instanceof Node\Expr\New_) { + $instantiation = $node->getOriginalExpr(); + if (!$instantiation instanceof Node\Expr\New_) { return []; } - $instantiation = $node->expr; if (!$instantiation->class instanceof Node\Name) { return []; } @@ -59,27 +59,13 @@ public function processNode(Node $node, Scope $scope): array } $constructor = $classReflection->getConstructor(); - if ($constructor->hasSideEffects()->no()) { - $throwsType = $constructor->getThrowType(); - if ($throwsType !== null && !$throwsType->isVoid()->yes()) { - return []; - } - - $methodResult = $scope->getType($instantiation); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { - return []; - } - - return [ - RuleErrorBuilder::message(sprintf( - 'Call to %s::%s() on a separate line has no effect.', - $classReflection->getDisplayName(), - $constructor->getName(), - ))->identifier('new.resultUnused')->build(), - ]; - } - - return []; + return [ + RuleErrorBuilder::message(sprintf( + 'Call to %s::%s() on a separate line has no effect.', + $classReflection->getDisplayName(), + $constructor->getName(), + ))->identifier('new.resultUnused')->build(), + ]; } } diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index f64b393e4c..8ce6574283 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -10,7 +10,6 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\Type; use function sprintf; diff --git a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php index 8f1828cbe4..7e663eb978 100644 --- a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php @@ -5,19 +5,19 @@ use PhpParser\Node; use PHPStan\Analyser\NullsafeOperatorHelper; use PHPStan\Analyser\Scope; +use PHPStan\Node\NoopExpressionNode; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use function sprintf; use function strtolower; /** - * @implements Rule + * @implements Rule */ final class CallToStaticMethodStatementWithoutSideEffectsRule implements Rule { @@ -31,16 +31,16 @@ public function __construct( public function getNodeType(): string { - return Node\Stmt\Expression::class; + return NoopExpressionNode::class; } public function processNode(Node $node, Scope $scope): array { - if (!$node->expr instanceof Node\Expr\StaticCall) { + $staticCall = $node->getOriginalExpr(); + if (!$staticCall instanceof Node\Expr\StaticCall) { return []; } - $staticCall = $node->expr; if (!$staticCall->name instanceof Node\Identifier) { return []; } @@ -84,30 +84,14 @@ public function processNode(Node $node, Scope $scope): array return []; } - if ($method->hasSideEffects()->no() || $node->expr->isFirstClassCallable()) { - if (!$node->expr->isFirstClassCallable()) { - $throwsType = $method->getThrowType(); - if ($throwsType !== null && !$throwsType->isVoid()->yes()) { - return []; - } - } - - $methodResult = $scope->getType($staticCall); - if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { - return []; - } - - return [ - RuleErrorBuilder::message(sprintf( - 'Call to %s %s::%s() on a separate line has no effect.', - $method->isStatic() ? 'static method' : 'method', - $method->getDeclaringClass()->getDisplayName(), - $method->getName(), - ))->identifier('staticMethod.resultUnused')->build(), - ]; - } - - return []; + return [ + RuleErrorBuilder::message(sprintf( + 'Call to %s %s::%s() on a separate line has no effect.', + $method->isStatic() ? 'static method' : 'method', + $method->getDeclaringClass()->getDisplayName(), + $method->getName(), + ))->identifier('staticMethod.resultUnused')->build(), + ]; } } From ff5c55222919dfe21e00b708977b3ab6ce962eb1 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 13:39:08 +0200 Subject: [PATCH 6/8] Add back one check --- .../CallToConstructorStatementWithoutSideEffectsRule.php | 7 +++++++ .../CallToMethodStatementWithoutSideEffectsRule.php | 6 ++++++ .../CallToStaticMethodStatementWithoutSideEffectsRule.php | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php index 5b214e42dc..21613e74e5 100644 --- a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php @@ -8,6 +8,8 @@ use PHPStan\Reflection\ReflectionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; +use PHPStan\Type\NeverType; + use function sprintf; /** @@ -59,6 +61,11 @@ public function processNode(Node $node, Scope $scope): array } $constructor = $classReflection->getConstructor(); + $methodResult = $scope->getType($instantiation); + if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + return []; + } + return [ RuleErrorBuilder::message(sprintf( 'Call to %s::%s() on a separate line has no effect.', diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index 8ce6574283..c8ead1d217 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -10,6 +10,7 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; +use PHPStan\Type\NeverType; use PHPStan\Type\Type; use function sprintf; @@ -60,6 +61,11 @@ public function processNode(Node $node, Scope $scope): array return []; } + $methodResult = $scope->getType($methodCall); + if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + return []; + } + $method = $calledOnType->getMethod($methodName, $scope); return [ diff --git a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php index 7e663eb978..550ea9e019 100644 --- a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php @@ -11,6 +11,7 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; use PHPStan\Type\ErrorType; +use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; use function sprintf; @@ -84,6 +85,11 @@ public function processNode(Node $node, Scope $scope): array return []; } + $methodResult = $scope->getType($staticCall); + if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { + return []; + } + return [ RuleErrorBuilder::message(sprintf( 'Call to %s %s::%s() on a separate line has no effect.', From 035eb8b4fab6f4478ef7a23bb242cc625e0e4e53 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 13:57:44 +0200 Subject: [PATCH 7/8] Fix --- .../CallToStaticMethodStatementWithoutSideEffectsRuleTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php index 03cbdaa49d..953ca5f982 100644 --- a/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php @@ -28,10 +28,6 @@ public function testRule(): void 'Call to static method DateTimeImmutable::createFromFormat() on a separate line has no effect.', 12, ], - [ - 'Call to static method DateTimeImmutable::createFromFormat() on a separate line has no effect.', - 13, - ], [ 'Call to method DateTime::format() on a separate line has no effect.', 23, From 8a0594c34cc42b2b37a2dcca7c2c19e76b42b0ec Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 31 Aug 2024 14:02:43 +0200 Subject: [PATCH 8/8] Fix cs --- .../Methods/CallToConstructorStatementWithoutSideEffectsRule.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php index 21613e74e5..c50d21d878 100644 --- a/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToConstructorStatementWithoutSideEffectsRule.php @@ -9,7 +9,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\NeverType; - use function sprintf; /**