-
-
Notifications
You must be signed in to change notification settings - Fork 439
Expand file tree
/
Copy pathUselessIfCondBeforeForeachDetector.php
More file actions
129 lines (104 loc) · 3.24 KB
/
UselessIfCondBeforeForeachDetector.php
File metadata and controls
129 lines (104 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
declare(strict_types=1);
namespace Rector\DeadCode;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\BinaryOp\NotEqual;
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Empty_;
use PhpParser\Node\Stmt\If_;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Analyser\Scope;
use Rector\PhpParser\Comparing\NodeComparator;
final readonly class UselessIfCondBeforeForeachDetector
{
public function __construct(
private NodeComparator $nodeComparator
) {
}
/**
* Matches:
* empty($values)
*/
public function isMatchingEmptyAndForeachedExpr(If_ $if, Expr $foreachExpr): bool
{
if (! $if->cond instanceof Empty_) {
return false;
}
$empty = $if->cond;
if (! $this->nodeComparator->areNodesEqual($empty->expr, $foreachExpr)) {
return false;
}
if ($if->stmts === []) {
return true;
}
if (count($if->stmts) !== 1) {
return false;
}
$stmt = $if->stmts[0];
return $stmt instanceof Return_ && ! $stmt->expr instanceof Expr;
}
/**
* Matches:
* !empty($values)
*/
public function isMatchingNotEmpty(If_ $if, Expr $foreachExpr, Scope $scope): bool
{
$cond = $if->cond;
if (! $cond instanceof BooleanNot) {
return false;
}
if (! $cond->expr instanceof Empty_) {
return false;
}
$empty = $cond->expr;
return $this->areCondExprAndForeachExprSame($empty, $foreachExpr, $scope);
}
/**
* Matches:
* $values !== []
* $values != []
* [] !== $values
* [] != $values
*/
public function isMatchingNotIdenticalEmptyArray(If_ $if, Expr $foreachExpr): bool
{
if (! $if->cond instanceof NotIdentical && ! $if->cond instanceof NotEqual) {
return false;
}
$notIdentical = $if->cond;
return $this->isMatchingNotBinaryOp($notIdentical, $foreachExpr);
}
private function isMatchingNotBinaryOp(NotIdentical | NotEqual $binaryOp, Expr $foreachExpr): bool
{
if ($this->isEmptyArrayAndForeachedVariable($binaryOp->left, $binaryOp->right, $foreachExpr)) {
return true;
}
return $this->isEmptyArrayAndForeachedVariable($binaryOp->right, $binaryOp->left, $foreachExpr);
}
private function isEmptyArrayAndForeachedVariable(Expr $leftExpr, Expr $rightExpr, Expr $foreachExpr): bool
{
if (! $this->isEmptyArray($leftExpr)) {
return false;
}
return $this->nodeComparator->areNodesEqual($foreachExpr, $rightExpr);
}
private function isEmptyArray(Expr $expr): bool
{
if (! $expr instanceof Array_) {
return false;
}
return $expr->items === [];
}
private function areCondExprAndForeachExprSame(Empty_ $empty, Expr $foreachExpr, Scope $scope): bool
{
if (! $this->nodeComparator->areNodesEqual($empty->expr, $foreachExpr)) {
return false;
}
// is array though?
$arrayType = $scope->getType($empty->expr);
return $arrayType->isArray()
->yes();
}
}