diff --git a/library/Exceptions/ValidationException.php b/library/Exceptions/ValidationException.php index 970c8605b..7343cc10a 100644 --- a/library/Exceptions/ValidationException.php +++ b/library/Exceptions/ValidationException.php @@ -11,6 +11,8 @@ use InvalidArgumentException; +use function realpath; + final class ValidationException extends InvalidArgumentException implements Exception { /** @param array $messages */ @@ -19,6 +21,10 @@ public function __construct( private readonly string $fullMessage, private readonly array $messages, ) { + if (realpath($this->file) === realpath(__DIR__ . '/../Validator.php')) { + $this->file = $this->getTrace()[0]['file'] ?? $this->file; + $this->line = $this->getTrace()[0]['line'] ?? $this->line; + } parent::__construct($message); } diff --git a/tests/feature/ValidationExceptionStackTraceTest.php b/tests/feature/ValidationExceptionStackTraceTest.php new file mode 100644 index 000000000..6238111fe --- /dev/null +++ b/tests/feature/ValidationExceptionStackTraceTest.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +use Respect\Validation\Exceptions\ValidationException; + +test('Should overwrite stack trace when in Validator', function (): void { + try { + v::intType()->assert('string'); + } catch (ValidationException $e) { + expect($e->getFile())->toBe(__FILE__); + expect($e->getLine())->toBe(__LINE__ - 3); + } +}); + +test('Should not overwrite stack trace when created manually', function (): void { + try { + throw new ValidationException('message', 'fullMessage', ['id' => 'message']); + } catch (ValidationException $e) { + expect($e->getFile())->toBe(__FILE__); + expect($e->getLine())->toBe(__LINE__ - 3); + } +});