From bf9f7218ce50868cfbb1c317ea8077a5d8aa42cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kucha=C5=99?= <honza.kuchar@grifart.cz> Date: Mon, 11 Mar 2019 11:31:35 +0100 Subject: [PATCH] print suppressed exceptions & their parents information into exception message, as this is supported by all debugging tools --- src/SuppressedExceptions.php | 42 +++++++++++++++++++++++++++++- tests/nested.phpt | 32 +++++++++++++++++++++++ tests/nested_exception-message.txt | 12 +++++++++ tests/simple.phpt | 14 ++++++---- tests/simple_exception-message.txt | 9 +++++++ 5 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 tests/nested.phpt create mode 100644 tests/nested_exception-message.txt create mode 100644 tests/simple_exception-message.txt diff --git a/src/SuppressedExceptions.php b/src/SuppressedExceptions.php index 40fde3b..3fb078f 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 0000000..8bb5382 --- /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 0000000..af012b4 --- /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 48c9459..2573cc2 100644 --- a/tests/simple.phpt +++ b/tests/simple.phpt @@ -19,15 +19,19 @@ $previous = new TestingSuppressedExceptionsException('previous', -1, new Runtime $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 0000000..e82674a --- /dev/null +++ b/tests/simple_exception-message.txt @@ -0,0 +1,9 @@ +message +Suppressed exceptions: +- simple.phpt:21 - RuntimeException +- simple.phpt:22 - This is message (LogicException) +- simple.phpt:23 - Error +- simple.phpt:24 - With previous (Exception) + previous: simple.phpt:18 - previous (Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException) + previous: simple.phpt:18 - Symfony\Component\Console\Exception\RuntimeException +- simple.phpt:25 - Grifart\SuppressedExceptions\__tests\TestingSuppressedExceptionsException -- GitLab