diff --git a/rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_with_custom_param_in_previous_position.php.inc b/rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_with_custom_param_in_previous_position.php.inc new file mode 100644 index 00000000000..9e0768e5ff0 --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_with_custom_param_in_previous_position.php.inc @@ -0,0 +1,27 @@ +getMessage(), previous: $e); + } + } +} diff --git a/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php b/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php index c53fce5269a..ba36f610026 100644 --- a/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php +++ b/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php @@ -158,7 +158,7 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable) } if (! isset($new->getArgs()[1])) { - if ($this->hasCodeParameter($new->class)) { + if ($this->hasParameter($new, 'code') && ! $this->hasArgument($new, 'code')) { // get previous code $new->args[1] = new Arg( new MethodCall($caughtThrowableVariable, 'getCode'), @@ -173,7 +173,7 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable) /** @var Arg $arg1 */ $arg1 = $new->args[1]; if ($arg1->name instanceof Identifier && $arg1->name->toString() === 'previous') { - if ($this->hasCodeParameter($new->class)) { + if ($this->hasParameter($new, 'code') && ! $this->hasArgument($new, 'code')) { $new->args[1] = new Arg( new MethodCall($caughtThrowableVariable, 'getCode'), name: $shouldUseNamedArguments ? new Identifier('code') : null @@ -183,11 +183,14 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable) } elseif (! $hasChanged) { return null; } - } else { + } elseif ($this->hasParameter($new, 'previous') && ! $this->hasArgument($new, 'previous')) { $new->args[$exceptionArgumentPosition] = new Arg( $caughtThrowableVariable, name: $shouldUseNamedArguments ? new Identifier('previous') : null ); + $hasChanged = true; + } elseif (! $hasChanged) { + return null; } // 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) return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; } - private function hasCodeParameter(Name $exceptionName): bool + private function hasParameter(New_ $new, string $parameterName): bool { - $className = $this->getName($exceptionName); + $className = $this->getName($new->class); + if ($className === null) { + return false; + } + if (! $this->reflectionProvider->hasClass($className)) { return false; } @@ -217,7 +224,18 @@ private function hasCodeParameter(Name $exceptionName): bool ); foreach ($extendedParametersAcceptor->getParameters() as $extendedParameterReflection) { - if ($extendedParameterReflection->getName() === 'code') { + if ($extendedParameterReflection->getName() === $parameterName) { + return true; + } + } + + return false; + } + + private function hasArgument(New_ $new, string $argumentName): bool + { + foreach ($new->getArgs() as $arg) { + if ($arg->name instanceof Identifier && $arg->name->toString() === $argumentName) { return true; } }