Skip to content

Commit 93ddb53

Browse files
[Php71] Skip Type from @param doc on BinaryOpBetweenNumberAndStringRector (#1386)
* [Php71] Skip fType from @param doc on BinaryOpBetweenNumberAndStringRector * final touch: from typed param * [ci-review] Rector Rectify * [ci-review] Rector Rectify * [ci-review] Rector Rectify * [ci-review] Rector Rectify Co-authored-by: GitHub Action <action@github.com>
1 parent 00af33a commit 93ddb53

6 files changed

Lines changed: 116 additions & 22 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php71\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector\Fixture;
4+
5+
class FromTypedParam
6+
{
7+
public function run(?int $id)
8+
{
9+
return $id !== null && $id !== 'null';
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\Php71\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector\Fixture;
18+
19+
class FromTypedParam
20+
{
21+
public function run(?int $id)
22+
{
23+
return $id !== null && $id !== 0;
24+
}
25+
}
26+
27+
?>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php71\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector\Fixture;
4+
5+
class SkipTypeByParamDoc
6+
{
7+
/**
8+
* @param int|null $id
9+
*/
10+
public function run($id)
11+
{
12+
return $id !== null && $id !== 'null';
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php71\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector\Fixture;
4+
5+
class SkipTypeByParamDoc2
6+
{
7+
/**
8+
* @param int|null $id
9+
*/
10+
public function run($id)
11+
{
12+
return $id !== null && 'null' !== $id;
13+
}
14+
}

rules/DeadCode/Rector/Cast/RecastingRemovalRector.php

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use PhpParser\Node\Expr\Cast\String_;
1616
use PhpParser\Node\Expr\PropertyFetch;
1717
use PhpParser\Node\Expr\StaticPropertyFetch;
18-
use PhpParser\Node\FunctionLike;
1918
use PHPStan\Reflection\Php\PhpPropertyReflection;
2019
use PHPStan\Type\ArrayType;
2120
use PHPStan\Type\BooleanType;
@@ -26,6 +25,7 @@
2625
use PHPStan\Type\StringType;
2726
use PHPStan\Type\Type;
2827
use PHPStan\Type\UnionType;
28+
use Rector\Core\NodeAnalyzer\ExprAnalyzer;
2929
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
3030
use Rector\Core\Rector\AbstractRector;
3131
use Rector\Core\Reflection\ReflectionResolver;
@@ -51,7 +51,8 @@ final class RecastingRemovalRector extends AbstractRector
5151

5252
public function __construct(
5353
private readonly PropertyFetchAnalyzer $propertyFetchAnalyzer,
54-
private readonly ReflectionResolver $reflectionResolver
54+
private readonly ReflectionResolver $reflectionResolver,
55+
private readonly ExprAnalyzer $exprAnalyzer
5556
) {
5657
}
5758

@@ -116,7 +117,7 @@ public function refactor(Node $node): ?Node
116117
private function shouldSkip(Expr $expr): bool
117118
{
118119
if (! $this->propertyFetchAnalyzer->isPropertyFetch($expr)) {
119-
return $this->isNonTypedFromParam($expr);
120+
return $this->exprAnalyzer->isNonTypedFromParam($expr);
120121
}
121122

122123
/** @var PropertyFetch|StaticPropertyFetch $expr */
@@ -135,23 +136,4 @@ private function shouldSkip(Expr $expr): bool
135136
$nativeType = $phpPropertyReflection->getNativeType();
136137
return $nativeType instanceof MixedType;
137138
}
138-
139-
private function isNonTypedFromParam(Expr $expr): bool
140-
{
141-
$functionLike = $this->betterNodeFinder->findParentType($expr, FunctionLike::class);
142-
if (! $functionLike instanceof FunctionLike) {
143-
return false;
144-
}
145-
146-
$params = $functionLike->getParams();
147-
foreach ($params as $param) {
148-
if (! $this->nodeComparator->areNodesEqual($param->var, $expr)) {
149-
continue;
150-
}
151-
152-
return $param->type === null;
153-
}
154-
155-
return false;
156-
}
157139
}

rules/Php71/Rector/BinaryOp/BinaryOpBetweenNumberAndStringRector.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use PhpParser\Node\Scalar\MagicConst\Line;
1616
use PhpParser\Node\Scalar\String_;
1717
use PHPStan\Type\Constant\ConstantStringType;
18+
use Rector\Core\NodeAnalyzer\ExprAnalyzer;
1819
use Rector\Core\Rector\AbstractRector;
1920
use Rector\Core\ValueObject\PhpVersionFeature;
2021
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
@@ -28,6 +29,11 @@
2829
*/
2930
final class BinaryOpBetweenNumberAndStringRector extends AbstractRector implements MinPhpVersionInterface
3031
{
32+
public function __construct(
33+
private readonly ExprAnalyzer $exprAnalyzer
34+
) {
35+
}
36+
3137
public function provideMinPhpVersion(): int
3238
{
3339
return PhpVersionFeature::BINARY_OP_NUMBER_STRING;
@@ -86,6 +92,14 @@ public function refactor(Node $node): ?Node
8692
return null;
8793
}
8894

95+
if ($this->exprAnalyzer->isNonTypedFromParam($node->left)) {
96+
return null;
97+
}
98+
99+
if ($this->exprAnalyzer->isNonTypedFromParam($node->right)) {
100+
return null;
101+
}
102+
89103
if ($this->isStringOrStaticNonNumbericString($node->left) && $this->nodeTypeResolver->isNumberType(
90104
$node->right
91105
)) {

src/NodeAnalyzer/ExprAnalyzer.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Core\NodeAnalyzer;
6+
7+
use PhpParser\Node\Expr;
8+
use PhpParser\Node\Expr\Variable;
9+
use PhpParser\Node\FunctionLike;
10+
use Rector\Core\PhpParser\Comparing\NodeComparator;
11+
use Rector\Core\PhpParser\Node\BetterNodeFinder;
12+
13+
final class ExprAnalyzer
14+
{
15+
public function __construct(
16+
private readonly NodeComparator $nodeComparator,
17+
private readonly BetterNodeFinder $betterNodeFinder,
18+
) {
19+
}
20+
21+
public function isNonTypedFromParam(Expr $expr): bool
22+
{
23+
if (! $expr instanceof Variable) {
24+
return false;
25+
}
26+
27+
$functionLike = $this->betterNodeFinder->findParentType($expr, FunctionLike::class);
28+
if (! $functionLike instanceof FunctionLike) {
29+
return false;
30+
}
31+
32+
$params = $functionLike->getParams();
33+
foreach ($params as $param) {
34+
if (! $this->nodeComparator->areNodesEqual($param->var, $expr)) {
35+
continue;
36+
}
37+
38+
return $param->type === null;
39+
}
40+
41+
return false;
42+
}
43+
}

0 commit comments

Comments
 (0)