Skip to content

Commit 64ba1b3

Browse files
authored
[CodeQuality] Skip with custom param in previous position on ThrowWithPreviousExceptionRector (#7919)
* [CodeQuality] Skip with custom param in previous position on ThrowWithPreviousExceptionRector * [CodeQuality] Skip with custom param in previous position on ThrowWithPreviousExceptionRector * final touch: add on purpose comment for future reference
1 parent 44a8dfc commit 64ba1b3

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Catch_\ThrowWithPreviousExceptionRector\Fixture;
4+
5+
/**
6+
* This direct use new ExceptionWithCustomParam() inside the class is on purpose to reproduce the issue
7+
*/
8+
final class ExceptionWithCustomParam extends \RuntimeException
9+
{
10+
public function __construct(
11+
public readonly bool $flag,
12+
string $message,
13+
int $code = 0,
14+
?\Throwable $previous = null,
15+
) {
16+
parent::__construct($message, $code, $previous);
17+
}
18+
19+
public function run(): void
20+
{
21+
try {
22+
throw new \RuntimeException('root');
23+
} catch (\Throwable $e) {
24+
throw new ExceptionWithCustomParam(flag: true, message: $e->getMessage(), previous: $e);
25+
}
26+
}
27+
}

rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable)
158158
}
159159

160160
if (! isset($new->getArgs()[1])) {
161-
if ($this->hasCodeParameter($new->class)) {
161+
if ($this->hasParameter($new, 'code') && ! $this->hasArgument($new, 'code')) {
162162
// get previous code
163163
$new->args[1] = new Arg(
164164
new MethodCall($caughtThrowableVariable, 'getCode'),
@@ -173,7 +173,7 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable)
173173
/** @var Arg $arg1 */
174174
$arg1 = $new->args[1];
175175
if ($arg1->name instanceof Identifier && $arg1->name->toString() === 'previous') {
176-
if ($this->hasCodeParameter($new->class)) {
176+
if ($this->hasParameter($new, 'code') && ! $this->hasArgument($new, 'code')) {
177177
$new->args[1] = new Arg(
178178
new MethodCall($caughtThrowableVariable, 'getCode'),
179179
name: $shouldUseNamedArguments ? new Identifier('code') : null
@@ -183,11 +183,14 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable)
183183
} elseif (! $hasChanged) {
184184
return null;
185185
}
186-
} else {
186+
} elseif ($this->hasParameter($new, 'previous') && ! $this->hasArgument($new, 'previous')) {
187187
$new->args[$exceptionArgumentPosition] = new Arg(
188188
$caughtThrowableVariable,
189189
name: $shouldUseNamedArguments ? new Identifier('previous') : null
190190
);
191+
$hasChanged = true;
192+
} elseif (! $hasChanged) {
193+
return null;
191194
}
192195

193196
// null the node, to fix broken format preserving printers, see https://github.com/rectorphp/rector/issues/5576
@@ -197,9 +200,13 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable)
197200
return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN;
198201
}
199202

200-
private function hasCodeParameter(Name $exceptionName): bool
203+
private function hasParameter(New_ $new, string $parameterName): bool
201204
{
202-
$className = $this->getName($exceptionName);
205+
$className = $this->getName($new->class);
206+
if ($className === null) {
207+
return false;
208+
}
209+
203210
if (! $this->reflectionProvider->hasClass($className)) {
204211
return false;
205212
}
@@ -217,7 +224,18 @@ private function hasCodeParameter(Name $exceptionName): bool
217224
);
218225

219226
foreach ($extendedParametersAcceptor->getParameters() as $extendedParameterReflection) {
220-
if ($extendedParameterReflection->getName() === 'code') {
227+
if ($extendedParameterReflection->getName() === $parameterName) {
228+
return true;
229+
}
230+
}
231+
232+
return false;
233+
}
234+
235+
private function hasArgument(New_ $new, string $argumentName): bool
236+
{
237+
foreach ($new->getArgs() as $arg) {
238+
if ($arg->name instanceof Identifier && $arg->name->toString() === $argumentName) {
221239
return true;
222240
}
223241
}

0 commit comments

Comments
 (0)