Deprecate things that prevent \Throwable from bubbling down

This commit is contained in:
Thomas Calvet 2019-08-08 18:27:37 +02:00 committed by Nicolas Grekas
parent 4cd3dc8d7f
commit abef506e89
35 changed files with 158 additions and 21 deletions

View File

@ -5,12 +5,15 @@ Cache
-----
* Added argument `$prefix` to `AdapterInterface::clear()`
* Marked the `CacheDataCollector` class as `@final`.
Console
-------
* Deprecated finding hidden commands using an abbreviation, use the full name instead
* Deprecated returning `null` from `Command::execute()`, return `0` instead
* Deprecated the `Application::renderException()` and `Application::doRenderException()` methods,
use `renderThrowable()` and `doRenderThrowable()` instead.
Debug
-----
@ -65,6 +68,7 @@ DoctrineBridge
* Deprecated `RegistryInterface`, use `Doctrine\Common\Persistence\ManagerRegistry`.
* Added a new `getMetadataDriverClass` method to replace class parameters in `AbstractDoctrineExtension`. This method
will be abstract in Symfony 5 and must be declared in extending classes.
* Marked the `DoctrineDataCollector` class as `@final`.
Filesystem
----------
@ -91,6 +95,7 @@ FrameworkBundle
* Deprecated `routing.loader.service`, use `routing.loader.container` instead.
* Not tagging service route loaders with `routing.route_loader` has been deprecated.
* Overriding the methods `KernelTestCase::tearDown()` and `WebTestCase::tearDown()` without the `void` return-type is deprecated.
* Marked the `RouterDataCollector` class as `@final`.
HttpClient
----------
@ -144,6 +149,12 @@ HttpKernel
current directory or with a glob pattern. The fallback directories have never been advocated
so you likely do not use those in any app based on the SF Standard or Flex edition.
* Getting the container from a non-booted kernel is deprecated
* Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`,
`ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`,
`RequestDataCollector` and `TimeDataCollector` classes as `@final`.
* Marked the `RouterDataCollector::collect()` method as `@final`.
* The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature
will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0.
Lock
----
@ -164,6 +175,7 @@ Messenger
* [BC BREAK] Removed `$retryStrategyLocator` argument from `ConsumeMessagesCommand::__construct`.
* [BC BREAK] Removed `$senderClassOrAlias` argument from `RedeliveryStamp::__construct`.
* [BC BREAK] Removed `UnknownSenderException`.
* Marked the `MessengerDataCollector` class as `@final`.
Mime
----
@ -216,6 +228,11 @@ Security
) {}
```
SecurityBundle
--------------
* Marked the `SecurityDataCollector` class as `@final`.
Serializer
----------
@ -231,6 +248,7 @@ Translation
* Deprecated support for using `null` as the locale in `Translator`.
* Deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
* Marked the `TranslationDataCollector` class as `@final`.
TwigBridge
----------
@ -238,6 +256,7 @@ TwigBridge
* Deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the
`DebugCommand::__construct()` method, swap the variables position.
* Deprecated accepting STDIN implicitly when using the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit.
* Marked the `TwigDataCollector` class as `@final`.
TwigBundle
----------
@ -342,6 +361,7 @@ Validator
* deprecated `ValidatorBuilder::setMetadataCache`, use `ValidatorBuilder::setMappingCache` instead.
* The `Range` constraint has a new message option `notInRangeMessage` that is used when both `min` and `max` values are set.
In case you are using custom translations make sure to add one for this new message.
* Marked the `ValidatorDataCollector` class as `@final`.
WebProfilerBundle
-----------------

View File

@ -8,6 +8,7 @@ CHANGELOG
* deprecated `RegistryInterface`, use `Doctrine\Common\Persistence\ManagerRegistry`
* added support for invokable event listeners
* added `getMetadataDriverClass` method to deprecate class parameters in service configuration files
* Marked the `DoctrineDataCollector` class as `@final`.
4.3.0
-----

View File

@ -23,6 +23,8 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector;
* DoctrineDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class DoctrineDataCollector extends DataCollector
{

View File

@ -11,6 +11,7 @@ CHANGELOG
* deprecated accepting STDIN implicitly when using the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit.
* added `--show-deprecations` option to the `lint:twig` command
* added support for Bootstrap4 switches, use `switch-custom` as `label_attr` in a `CheckboxType`
* Marked the `TwigDataCollector` class as `@final`.
4.3.0
-----

View File

@ -25,6 +25,8 @@ use Twig\Profiler\Profile;
* TwigDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class TwigDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -20,6 +20,7 @@ CHANGELOG
* [BC Break] The `framework.messenger.routing.senders` config key is not deep merged anymore.
* Added `secrets:*` commands and `%env(secret:...)%` processor to deal with secrets seamlessly.
* Made `framework.session.handler_id` accept a DSN
* Marked the `RouterDataCollector` class as `@final`.
4.3.0
-----

View File

@ -207,11 +207,15 @@ class Application extends BaseApplication
(new SymfonyStyle($input, $output))->warning('Some commands could not be registered:');
foreach ($this->registrationErrors as $error) {
if (!$error instanceof \Exception) {
$error = new ErrorException($error);
}
if (method_exists($this, 'doRenderThrowable')) {
$this->doRenderThrowable($error, $output);
} else {
if (!$error instanceof \Exception) {
$error = new ErrorException($error);
}
$this->doRenderException($error, $output);
$this->doRenderException($error, $output);
}
}
}
}

View File

@ -19,6 +19,8 @@ use Symfony\Component\HttpKernel\DataCollector\RouterDataCollector as BaseRouter
* RouterDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class RouterDataCollector extends BaseRouterDataCollector
{

View File

@ -6,6 +6,7 @@ CHANGELOG
* Added new `argon2id` encoder, undeprecated the `bcrypt` and `argon2i` ones (using `auto` is still recommended by default.)
* Deprecated the usage of "query_string" without a "search_dn" and a "search_password" config key in Ldap factories.
* Marked the `SecurityDataCollector` class as `@final`.
4.3.0
-----

View File

@ -34,6 +34,8 @@ use Symfony\Component\VarDumper\Cloner\Data;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class SecurityDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -11,6 +11,7 @@ CHANGELOG
* added `DeflateMarshaller` to compress serialized values
* removed support for phpredis 4 `compression`
* [BC BREAK] `RedisTagAwareAdapter` is not compatible with `RedisCluster` from `Predis` anymore, use `phpredis` instead
* Marked the `CacheDataCollector` class as `@final`.
4.3.0
-----

View File

@ -21,6 +21,8 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
/**
* @author Aaron Scherer <aequasi@gmail.com>
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*
* @final since Symfony 4.4
*/
class CacheDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -128,13 +128,10 @@ class Application implements ResetInterface
}
$renderException = function (\Throwable $e) use ($output) {
if (!$e instanceof \Exception) {
$e = class_exists(ErrorException::class) ? new ErrorException($e) : (class_exists(LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()));
}
if ($output instanceof ConsoleOutputInterface) {
$this->renderException($e, $output->getErrorOutput());
$this->renderThrowable($e, $output->getErrorOutput());
} else {
$this->renderException($e, $output);
$this->renderThrowable($e, $output);
}
};
if ($phpHandler = set_exception_handler($renderException)) {
@ -792,20 +789,77 @@ class Application implements ResetInterface
/**
* Renders a caught exception.
*
* @deprecated since Symfony 4.4, use "renderThrowable()" instead
*/
public function renderException(\Exception $e, OutputInterface $output)
{
@trigger_error(sprintf('The "%s::renderException()" method is deprecated since Symfony 4.4, use "renderThrowable()" instead.', __CLASS__), E_USER_DEPRECATED);
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
$this->doRenderException($e, $output);
$this->finishRenderThrowableOrException($output);
}
public function renderThrowable(\Throwable $e, OutputInterface $output): void
{
if (__CLASS__ !== \get_class($this) && __CLASS__ === (new \ReflectionMethod($this, 'renderThrowable'))->getDeclaringClass()->getName() && __CLASS__ !== (new \ReflectionMethod($this, 'renderException'))->getDeclaringClass()->getName()) {
@trigger_error(sprintf('The "%s::renderException()" method is deprecated since Symfony 4.4, use "renderThrowable()" instead.', __CLASS__), E_USER_DEPRECATED);
if (!$e instanceof \Exception) {
$e = class_exists(ErrorException::class) ? new ErrorException($e) : (class_exists(LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()));
}
$this->renderException($e, $output);
return;
}
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
$this->doRenderThrowable($e, $output);
$this->finishRenderThrowableOrException($output);
}
private function finishRenderThrowableOrException(OutputInterface $output): void
{
if (null !== $this->runningCommand) {
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
$output->writeln('', OutputInterface::VERBOSITY_QUIET);
}
}
/**
* @deprecated since Symfony 4.4, use "doRenderThrowable()" instead
*/
protected function doRenderException(\Exception $e, OutputInterface $output)
{
@trigger_error(sprintf('The "%s::doRenderException()" method is deprecated since Symfony 4.4, use "doRenderThrowable()" instead.', __CLASS__), E_USER_DEPRECATED);
$this->doActuallyRenderThrowable($e, $output);
}
protected function doRenderThrowable(\Throwable $e, OutputInterface $output): void
{
if (__CLASS__ !== \get_class($this) && __CLASS__ === (new \ReflectionMethod($this, 'doRenderThrowable'))->getDeclaringClass()->getName() && __CLASS__ !== (new \ReflectionMethod($this, 'doRenderException'))->getDeclaringClass()->getName()) {
@trigger_error(sprintf('The "%s::doRenderException()" method is deprecated since Symfony 4.4, use "doRenderThrowable()" instead.', __CLASS__), E_USER_DEPRECATED);
if (!$e instanceof \Exception) {
$e = class_exists(ErrorException::class) ? new ErrorException($e) : (class_exists(LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()));
}
$this->doRenderException($e, $output);
return;
}
$this->doActuallyRenderThrowable($e, $output);
}
private function doActuallyRenderThrowable(\Throwable $e, OutputInterface $output): void
{
do {
$message = trim($e->getMessage());

View File

@ -11,6 +11,8 @@ CHANGELOG
* marked all dispatched event classes as `@final`
* added support for displaying table horizontally
* deprecated returning `null` from `Command::execute()`, return `0` instead
* Deprecated the `Application::renderException()` and `Application::doRenderException()` methods,
use `renderThrowable()` and `doRenderThrowable()` instead.
4.3.0
-----

View File

@ -15,6 +15,12 @@ CHANGELOG
* Marked all dispatched event classes as `@final`
* Added `ErrorController` to enable the preview and error rendering mechanism
* Getting the container from a non-booted kernel is deprecated.
* Marked the `AjaxDataCollector`, `ConfigDataCollector`, `EventDataCollector`,
`ExceptionDataCollector`, `LoggerDataCollector`, `MemoryDataCollector`,
`RequestDataCollector` and `TimeDataCollector` classes as `@final`.
* Marked the `RouterDataCollector::collect()` method as `@final`.
* The `DataCollectorInterface::collect()` and `Profiler::collect()` methods third parameter signature
will be `\Throwable $exception = null` instead of `\Exception $exception = null` in Symfony 5.0.
4.3.0
-----

View File

@ -18,6 +18,8 @@ use Symfony\Component\HttpFoundation\Response;
* AjaxDataCollector.
*
* @author Bart van den Burg <bart@burgov.nl>
*
* @final since Symfony 4.4
*/
class AjaxDataCollector extends DataCollector
{

View File

@ -19,6 +19,8 @@ use Symfony\Component\VarDumper\Caster\LinkStub;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -23,6 +23,8 @@ use Symfony\Contracts\Service\ResetInterface;
* EventDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class EventDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -19,6 +19,8 @@ use Symfony\Component\HttpFoundation\Response;
* ExceptionDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class ExceptionDataCollector extends DataCollector
{

View File

@ -21,6 +21,8 @@ use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
* LogDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -18,6 +18,8 @@ use Symfony\Component\HttpFoundation\Response;
* MemoryDataCollector.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -22,6 +22,8 @@ use Symfony\Component\HttpKernel\KernelEvents;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface
{

View File

@ -33,6 +33,8 @@ class RouterDataCollector extends DataCollector
/**
* {@inheritdoc}
*
* @final since Symfony 4.4
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
{

View File

@ -19,6 +19,8 @@ use Symfony\Component\Stopwatch\StopwatchEvent;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.4
*/
class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -126,11 +126,15 @@ class DebugHandlersListener implements EventSubscriberInterface
$output = $output->getErrorOutput();
}
$this->exceptionHandler = static function (\Throwable $e) use ($app, $output) {
if (!$e instanceof \Exception) {
$e = new ErrorException($e);
}
if (method_exists($app, 'renderThrowable')) {
$app->renderThrowable($e, $output);
} else {
if (!$e instanceof \Exception) {
$e = new ErrorException($e);
}
$app->renderException($e, $output);
$app->renderException($e, $output);
}
};
}
}

View File

@ -76,7 +76,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
throw $e;
}
return $this->handleException($e, $request, $type);
return $this->handleThrowable($e, $request, $type);
}
}
@ -91,13 +91,13 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
/**
* @internal
*/
public function terminateWithException(\Exception $exception, Request $request = null)
public function terminateWithException(\Throwable $exception, Request $request = null)
{
if (!$request = $request ?: $this->requestStack->getMasterRequest()) {
throw $exception;
}
$response = $this->handleException($exception, $request, self::MASTER_REQUEST);
$response = $this->handleThrowable($exception, $request, self::MASTER_REQUEST);
$response->sendHeaders();
$response->sendContent();
@ -197,11 +197,11 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
}
/**
* Handles an exception by trying to convert it to a Response.
* Handles a throwable by trying to convert it to a Response.
*
* @throws \Exception
*/
private function handleException(\Exception $e, Request $request, int $type): Response
private function handleThrowable(\Throwable $e, Request $request, int $type): Response
{
$event = new ExceptionEvent($this, $request, $type, $e);
$this->dispatcher->dispatch($event, KernelEvents::EXCEPTION);

View File

@ -138,10 +138,14 @@ class Profiler implements ResetInterface
/**
* Collects data for the given Response.
*
* @param \Throwable|null $exception
*
* @return Profile|null A Profile instance or null if the profiler is disabled
*/
public function collect(Request $request, Response $response, \Exception $exception = null)
public function collect(Request $request, Response $response/*, \Throwable $exception = null*/)
{
$exception = 2 < \func_num_args() ? func_get_arg(2) : null;
if (false === $this->enabled) {
return null;
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener;
use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleEvent;
@ -123,7 +124,7 @@ class DebugHandlersListenerTest extends TestCase
$this->assertInstanceOf('Closure', $xHandler);
$app->expects($this->once())
->method('renderException');
->method(method_exists(Application::class, 'renderThrowable') ? 'renderThrowable' : 'renderException');
$xHandler(new \Exception());
}

View File

@ -20,7 +20,7 @@ use Symfony\Component\Mailer\EventListener\MessageLoggerListener;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
class MessageDataCollector extends DataCollector
final class MessageDataCollector extends DataCollector
{
private $events;

View File

@ -17,6 +17,7 @@ CHANGELOG
* [BC BREAK] Removed `$senderClassOrAlias` argument from `RedeliveryStamp::__construct`.
* [BC BREAK] Removed `UnknownSenderException`.
* The component is not marked as `@experimental` anymore.
* Marked the `MessengerDataCollector` class as `@final`.
4.3.0
-----

View File

@ -20,6 +20,8 @@ use Symfony\Component\VarDumper\Caster\ClassStub;
/**
* @author Samuel Roze <samuel.roze@gmail.com>
*
* @final since Symfony 4.4
*/
class MessengerDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -6,6 +6,7 @@ CHANGELOG
* deprecated support for using `null` as the locale in `Translator`
* deprecated accepting STDIN implicitly when using the `lint:xliff` command, use `lint:xliff -` (append a dash) instead to make it explicit.
* Marked the `TranslationDataCollector` class as `@final`.
4.3.0
-----

View File

@ -19,6 +19,8 @@ use Symfony\Component\Translation\DataCollectorTranslator;
/**
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
*
* @final since Symfony 4.4
*/
class TranslationDataCollector extends DataCollector implements LateDataCollectorInterface
{

View File

@ -25,6 +25,7 @@ CHANGELOG
* Overriding the methods `ConstraintValidatorTestCase::setUp()` and `ConstraintValidatorTestCase::tearDown()` without the `void` return-type is deprecated.
* deprecated `Symfony\Component\Validator\Mapping\Cache\CacheInterface` in favor of PSR-6.
* deprecated `ValidatorBuilder::setMetadataCache`, use `ValidatorBuilder::setMappingCache` instead.
* Marked the `ValidatorDataCollector` class as `@final`.
4.3.0
-----

View File

@ -24,6 +24,8 @@ use Symfony\Component\VarDumper\Cloner\Stub;
/**
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*
* @final since Symfony 4.4
*/
class ValidatorDataCollector extends DataCollector implements LateDataCollectorInterface
{