|
6 | 6 |
|
7 | 7 | use PhpParser\Node; |
8 | 8 | use PhpParser\Node\Expr\MethodCall; |
| 9 | +use PhpParser\Node\Expr\StaticCall; |
9 | 10 | use PhpParser\Node\Expr\Variable; |
10 | 11 | use PhpParser\Node\Stmt; |
11 | 12 | use PhpParser\Node\Stmt\ClassMethod; |
| 13 | +use PhpParser\Node\Stmt\Expression; |
12 | 14 | use PhpParser\Node\Stmt\Foreach_; |
13 | 15 | use Rector\PHPUnit\CodeQuality\NodeAnalyser\NullableObjectAssignCollector; |
14 | 16 | use Rector\PHPUnit\CodeQuality\NodeFactory\AssertMethodCallFactory; |
@@ -116,6 +118,19 @@ public function refactor(Node $node): ?Node |
116 | 118 |
|
117 | 119 | $next = 0; |
118 | 120 | foreach ($node->stmts as $key => $stmt) { |
| 121 | + // already asserted, e.g. in trait, where $this is not known as TestCase so the type is not narrowed |
| 122 | + $assertedVariableName = $this->matchAssertInstanceOfVariableName($stmt); |
| 123 | + if ($assertedVariableName !== null) { |
| 124 | + $assertedVariableNameToType = $variableNameToTypeCollection->matchByVariableName( |
| 125 | + $assertedVariableName |
| 126 | + ); |
| 127 | + if ($assertedVariableNameToType instanceof VariableNameToType) { |
| 128 | + $variableNameToTypeCollection->remove($assertedVariableNameToType); |
| 129 | + } |
| 130 | + |
| 131 | + continue; |
| 132 | + } |
| 133 | + |
119 | 134 | // has callable on nullable variables of already collected names? |
120 | 135 | // a single statement can use multiple nullable variables at once |
121 | 136 | $matchedNullableVariableNameToTypes = $this->matchNullableVariableNameToTypes( |
@@ -146,6 +161,33 @@ public function refactor(Node $node): ?Node |
146 | 161 | return $node; |
147 | 162 | } |
148 | 163 |
|
| 164 | + private function matchAssertInstanceOfVariableName(Stmt $stmt): ?string |
| 165 | + { |
| 166 | + if (! $stmt instanceof Expression) { |
| 167 | + return null; |
| 168 | + } |
| 169 | + |
| 170 | + $call = $stmt->expr; |
| 171 | + if (! $call instanceof MethodCall && ! $call instanceof StaticCall) { |
| 172 | + return null; |
| 173 | + } |
| 174 | + |
| 175 | + if (! $this->isName($call->name, 'assertInstanceOf')) { |
| 176 | + return null; |
| 177 | + } |
| 178 | + |
| 179 | + if ($call->isFirstClassCallable()) { |
| 180 | + return null; |
| 181 | + } |
| 182 | + |
| 183 | + $args = $call->getArgs(); |
| 184 | + if (! isset($args[1]) || ! $args[1]->value instanceof Variable) { |
| 185 | + return null; |
| 186 | + } |
| 187 | + |
| 188 | + return $this->getName($args[1]->value); |
| 189 | + } |
| 190 | + |
149 | 191 | /** |
150 | 192 | * @return VariableNameToType[] |
151 | 193 | */ |
|
0 commit comments