From 3f681bff2edfd3ec06672be945577f0545c26268 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Sat, 21 Feb 2026 04:09:08 +0700 Subject: [PATCH] [CodeQuality] Skip custom exception param order flipped on no namespace on ThrowWithPreviousExceptionRector --- ...n_param_order_flipped_no_namespace.php.inc | 33 +++++++++++++++++++ .../ThrowWithPreviousExceptionRector.php | 14 ++++---- 2 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_custom_exception_param_order_flipped_no_namespace.php.inc diff --git a/rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_custom_exception_param_order_flipped_no_namespace.php.inc b/rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_custom_exception_param_order_flipped_no_namespace.php.inc new file mode 100644 index 00000000000..7638dc2667f --- /dev/null +++ b/rules-tests/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector/Fixture/skip_custom_exception_param_order_flipped_no_namespace.php.inc @@ -0,0 +1,33 @@ +statusCode = $statusCode; + $this->headers = $headers; + + parent::__construct($message, $code, $previous); + } +} + +class BadGatewayHttpException extends HttpException +{ + public function __construct(string $message = '', ?Throwable $previous = null, array $headers = [], int $code = 0) + { + parent::__construct(Response::HTTP_BAD_GATEWAY, $message, $previous, $headers, $code); + } +} + + +try { + // do sth +} catch (\Throwable $exception) { + throw new BadGatewayHttpException('test exception', $exception); +} diff --git a/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php b/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php index b534616713f..fd14c099856 100644 --- a/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php +++ b/rules/CodeQuality/Rector/Catch_/ThrowWithPreviousExceptionRector.php @@ -17,6 +17,7 @@ use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ObjectType; +use PHPStan\Type\TypeCombinator; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Rector\AbstractRector; use Rector\StaticTypeMapper\Resolver\ClassNameFromObjectTypeResolver; @@ -186,12 +187,6 @@ private function refactorThrow(Throw_ $throw, Variable $caughtThrowableVariable) private function resolveExceptionArgumentPosition(Name $exceptionName): ?int { $className = $this->getName($exceptionName); - - // is native exception? - if (! \str_contains($className, '\\')) { - return self::DEFAULT_EXCEPTION_ARGUMENT_POSITION; - } - if (! $this->reflectionProvider->hasClass($className)) { return self::DEFAULT_EXCEPTION_ARGUMENT_POSITION; } @@ -211,11 +206,16 @@ private function resolveExceptionArgumentPosition(Name $exceptionName): ?int $parameterType = $extendedParameterReflection->getType(); $className = ClassNameFromObjectTypeResolver::resolve($extendedParameterReflection->getType()); + $objectType = new ObjectType('Throwable'); if ($className === null) { + $parameterType = TypeCombinator::removeNull($parameterType); + if ($objectType->isSuperTypeOf($parameterType)->yes()) { + return $position; + } + continue; } - $objectType = new ObjectType('Throwable'); if ($objectType->isSuperTypeOf($parameterType)->no()) { continue; }