diff --git a/src/SuppressedExceptions.php b/src/SuppressedExceptions.php index 40fde3bc006ad4c6626feac035a451757948baa8..3fb078f57332da29ee09a7a20c0ff89c283d5c95 100644 --- a/src/SuppressedExceptions.php +++ b/src/SuppressedExceptions.php @@ -14,6 +14,7 @@ trait SuppressedExceptions /* implements WithSuppressedExceptions */ public function addSuppressed(\Throwable ...$exceptions): void { foreach($exceptions as $exception) { + $this->addTextVersionOfExceptionToMessage($exception); $this->suppressedExceptions[] = $exception; } } @@ -23,4 +24,43 @@ trait SuppressedExceptions /* implements WithSuppressedExceptions */ return $this->suppressedExceptions; } -} \ No newline at end of file + private function addTextVersionOfExceptionToMessage(\Throwable $throwable): void + { + if ($this->suppressedExceptions === []) { + $this->message .= "\nSuppressed exceptions:\n"; + } + + $moveRight = function(string $textToMoveRight, int $offset): string { + $replaceWith = "\n" . \str_repeat(' ', $offset); + return str_replace( + ["\r\n","\n","\r"], + $replaceWith, + $textToMoveRight + ); + }; + + $renderSingle = function(\Throwable $throwable): string { + $message = $throwable->getMessage(); + $type = \get_class($throwable); + $message = + $message === '' + ? $type + : "{$message} ({$type})"; + + $fileRelativePath = str_replace(\getcwd() . DIRECTORY_SEPARATOR, '', $throwable->getFile()); + return "{$fileRelativePath}:{$throwable->getLine()} - {$message}"; + }; + + $renderTree = function(\Throwable $throwable) use ($moveRight, $renderSingle): string { + $string = $renderSingle($throwable); + $previous = $throwable; + while (($previous = $previous->getPrevious()) !== NULL) { + $string .= "\n previous: {$moveRight($renderSingle($previous), 12)}"; + } + return $string; + }; + + $this->message .= "- {$moveRight($renderTree($throwable), 2)}\n"; + } + +} diff --git a/tests/nested.phpt b/tests/nested.phpt new file mode 100644 index 0000000000000000000000000000000000000000..8bb53827d4faade25a83b1af9cb3003765e67d01 --- /dev/null +++ b/tests/nested.phpt @@ -0,0 +1,32 @@ +<?php declare(strict_types=1); + +namespace Grifart\SuppressedExceptions\__tests; + +use Grifart\SuppressedExceptions\SuppressedExceptions; +use Grifart\SuppressedExceptions\WithSuppressedExceptions; +use Symfony\Component\Console\Exception\RuntimeException; +use Tester\Assert; + +require __DIR__ . '/bootstrap.php'; + +class TestingSuppressedExceptionsException extends \RuntimeException implements WithSuppressedExceptions +{ + use SuppressedExceptions; + +} + +$previous = new TestingSuppressedExceptionsException('previous', -1, new RuntimeException()); +$exception1 = new TestingSuppressedExceptionsException('message', 42, $previous); +$exception1->addSuppressed(new RuntimeException('message', 0, $previous)); + +$exception2 = new TestingSuppressedExceptionsException('message2', 42); +$exception2->addSuppressed($previous); +$exception2->addSuppressed($exception1); + +Assert::exception( + function() use ($exception2) { + throw $exception2; + }, + TestingSuppressedExceptionsException::class, + \file_get_contents(__DIR__ . '/nested_exception-message.txt') +); diff --git a/tests/nested_exception-message.txt b/tests/nested_exception-message.txt new file mode 100644 index 0000000000000000000000000000000000000000..af012b40e14fedee68b84d7e3440fb10f147a2a3 --- /dev/null +++ b/tests/nested_exception-message.txt @@ -0,0 +1,12 @@ +message2 +Suppressed exceptions: +- nested.phpt:18 - previous (Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException) + previous: nested.phpt:18 - Symfony\Component\Console\Exception\RuntimeException +- nested.phpt:19 - message + Suppressed exceptions: + - nested.phpt:20 - message (Symfony\Component\Console\Exception\RuntimeException) + previous: nested.phpt:18 - previous (Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException) + previous: nested.phpt:18 - Symfony\Component\Console\Exception\RuntimeException + (Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException) + previous: nested.phpt:18 - previous (Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException) + previous: nested.phpt:18 - Symfony\Component\Console\Exception\RuntimeException diff --git a/tests/simple.phpt b/tests/simple.phpt index 48c94593292452dae7076ceb298e07d7ad774320..baa9075300cafd2f847dd2f6926c2760f828aade 100644 --- a/tests/simple.phpt +++ b/tests/simple.phpt @@ -4,7 +4,6 @@ namespace Grifart\SuppressedExceptions\__tests; use Grifart\SuppressedExceptions\SuppressedExceptions; use Grifart\SuppressedExceptions\WithSuppressedExceptions; -use Symfony\Component\Console\Exception\RuntimeException; use Tester\Assert; require __DIR__ . '/bootstrap.php'; @@ -15,19 +14,23 @@ class TestingSuppressedExceptionsException extends \RuntimeException implements } -$previous = new TestingSuppressedExceptionsException('previous', -1, new RuntimeException()); +$previous = new TestingSuppressedExceptionsException('previous', -1, new \RuntimeException()); $exception = new TestingSuppressedExceptionsException('message', 42, $previous); $exception->addSuppressed($suppressed1 = new \RuntimeException()); -$exception->addSuppressed($suppressed2 = new \LogicException()); +$exception->addSuppressed($suppressed2 = new \LogicException('This is message')); $exception->addSuppressed($suppressed3 = new \Error()); -$exception->addSuppressed($suppressed4 = new \Exception()); +$exception->addSuppressed($suppressed4 = new \Exception('With previous', 0, $previous)); $exception->addSuppressed($suppressed5 = new TestingSuppressedExceptionsException()); // test that can be thrown -Assert::exception(function() use ($exception) { - throw $exception; -}, TestingSuppressedExceptionsException::class); +Assert::exception( + function() use ($exception) { + throw $exception; + }, + TestingSuppressedExceptionsException::class, + \file_get_contents(__DIR__ . '/simple_exception-message.txt') +); // previous Assert::same($previous, $exception->getPrevious()); diff --git a/tests/simple_exception-message.txt b/tests/simple_exception-message.txt new file mode 100644 index 0000000000000000000000000000000000000000..7512541023f18f163e539284e111f958a79e0a88 --- /dev/null +++ b/tests/simple_exception-message.txt @@ -0,0 +1,9 @@ +message +Suppressed exceptions: +- simple.phpt:20 - RuntimeException +- simple.phpt:21 - This is message (LogicException) +- simple.phpt:22 - Error +- simple.phpt:23 - With previous (Exception) + previous: simple.phpt:17 - previous (Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException) + previous: simple.phpt:17 - RuntimeException +- simple.phpt:24 - Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException