10000 [PhpunitBridge][HttpKernel] Read compiler deprecations from file when… · symfony/symfony@bf17514 · GitHub
[go: up one dir, main page]

Skip to content

Commit bf17514

Browse files
committed
[PhpunitBridge][HttpKernel] Read compiler deprecations from file when the container is already built
1 parent bf765c0 commit bf17514

File tree

5 files changed

+90
-18
lines changed

5 files changed

+90
-18
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public function handleError($type, $msg, $file, $line, $context = [])
133133
if ($deprecation->originatesFromAnObject()) {
134134
$class = $deprecation->originatingClass();
135135
$method = $deprecation->originatingMethod();
136+
$msg = $deprecation->getMessage();
136137

137138
if (0 !== error_reporting()) {
138139
$group = 'unsilenced';

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
1313

1414
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor;
15+
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
1516

1617
/**
1718
* @internal
@@ -43,6 +44,11 @@ class Deprecation
4344
*/
4445
private $self;
4546

47+
/**
48+
* @var bool
49+
*/
50+
private $isContainerDeprecation;
51+
4652
/** @var string[] absolute paths to vendor directories */
4753
private static $vendors;
4854

@@ -60,18 +66,23 @@ public function __construct($message, array $trace, $file)
6066
}
6167
$line = $trace[$i];
6268
$this->self = !$this->pathOriginatesFromVendor($file);
69+
$this->isContainerDeprecation = false;
6370
if (isset($line['object']) || isset($line['class'])) {
64-
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
71+
if (
72+
isset($line['class'])
73+
&& ($this->isFromTestListeners($line) || ($fromKernelTestCase = $this->isFromKernelTestCase($line)))
74+
) {
6575
$parsedMsg = unserialize($this->message);
76+
$this->isContainerDeprecation = isset($fromKernelTestCase) && $fromKernelTestCase && $parsedMsg;
6677
$this->message = $parsedMsg['deprecation'];
6778
$this->originClass = $parsedMsg['class'];
6879
$this->originMethod = $parsedMsg['method'];
6980
// If the deprecation has been triggered via
7081
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
7182
// then we need to use the serialized information to determine
7283
// if the error has been triggered from vendor code.
73-
$this->self = isset($parsedMsg['triggering_file'])
74-
&& $this->pathOriginatesFromVendor($parsedMsg['triggering_file']);
84+
$this->self = !isset($parsedMsg['triggering_file'])
85+
|| !$this->pathOriginatesFromVendor($parsedMsg['triggering_file']);
7586

7687
return;
7788
}
@@ -80,6 +91,18 @@ public function __construct($message, array $trace, $file)
8091
}
8192
}
8293

94+
private function isFromTestListeners(array $line): bool
95+
{
96+
return 0 === strpos($line['class'], SymfonyTestsListenerFor::class);
97+
}
98+
99+
private function isFromKernelTestCase(array $line): bool
100+
{
101+
return 0 === strpos($line['class'], KernelTestCase::class)
102+
&& isset($line['function'])
103+
&& 'tearDownAfterClass' == $line['function'];
104+
}
105+
83106
/**
84107
* @return bool
85108
*/
@@ -133,6 +156,11 @@ public function originatingMethod()
133156
return $this->originMethod;
134157
}
135158

159+
public function getMessage(): string
160+
{
161+
return $this->message;
162+
}
163+
136164
/**
137165
* @param string $utilPrefix
138166
*
@@ -188,6 +216,11 @@ public function isIndirect()
188216
return false;
189217
}
190218

219+
public function isContainerDeprecation(): bool
220+
{
221+
return $this->isContainerDeprecation;
222+
}
223+
191224
/**
192225
* pathOriginatesFromVendor() should always be called prior to calling this method.
193226
*

src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ abstract class KernelTestCase extends TestCase
3737
*/
3838
protected static $container;
3939

40+
private static $compilerDeprecationsTriggered = false;
41+
4042
protected function doTearDown(): void
4143
{
4244
static::ensureKernelShutdown();
@@ -132,4 +134,18 @@ protected static function ensureKernelShutdown()
132134
}
133135
static::$container = null;
134136
}
137+
138+
public static function tearDownAfterClass()
139+
{
140+
if (!self::$compilerDeprecationsTriggered) {
141+
$compilerDeprecated = getenv('SYMFONY_COMPILER_DEPRECATIONS');
142+
if ($compilerDeprecated && file_exists($compilerDeprecated)) {
143+
foreach (unserialize(file_get_contents($compilerDeprecated)) as $log) {
144+
@trigger_error(serialize($log), E_USER_DEPRECATED);
145+
}
146+
self::$compilerDeprecationsTriggered = true;
147+
}
148+
}
149+
parent::tearDownAfterClass();
150+
}
135151
}

src/Symfony/Component/BrowserKit/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* Marked `Response` final.
1111
* Deprecated `Response::buildHeader()`
1212
* Deprecated `Response::getStatus()`, use `Response::getStatusCode()` instead
13+
* Allowed to always display container deprecations
1314

1415
4.2.0
1516
-----

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ protected function initializeContainer()
483483
$cacheDir = $this->warmupDir ?: $this->getCacheDir();
484484
$cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug);
485485
$oldContainer = null;
486+
$deprecationsFilename = $cacheDir.'/'.$class.'Deprecations.log';
486487
if ($fresh = $cache->isFresh()) {
487488
// Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors
488489
$errorLevel = error_reporting(\E_ALL ^ \E_WARNING);
@@ -501,13 +502,16 @@ protected function initializeContainer()
501502
}
502503

503504
if ($fresh) {
505+
if ($this->debug) {
506+
putenv("SYMFONY_COMPILER_DEPRECATIONS=$deprecationsFilename");
507+
}
508+
504509
return;
505510
}
506511

507512
if ($this->debug) {
508513
$collectedLogs = [];
509-
$previousHandler = \defined('PHPUNIT_COMPOSER_INSTALL');
510-
$previousHandler = $previousHandler ?: set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
514+
$previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
511515
if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
512516
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
513517
}
@@ -518,27 +522,44 @@ protected function initializeContainer()
518522
return;
519523
}
520524

521-
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
522-
// Clean the trace by removing first frames added by the error handler itself.
523-
for ($i = 0; isset($backtrace[$i]); ++$i) {
524-
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
525-
$backtrace = \array_slice($backtrace, 1 + $i);
526-
break;
525+
if (\defined('PHPUNIT_COMPOSER_INSTALL')) {
526+
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
527+
$i = \count($backtrace);
528+
while (1 < $i && (!isset($backtrace[--$i]['class']) || ('ReflectionMethod' === $backtrace[$i]['class'] || 0 === strpos($backtrace[$i]['class'], 'PHPUnit_') || 0 === strpos($backtrace[$i]['class'], 'PHPUnit\\')))) {
529+
// No-op
527530
}
528-
}
529-
// Remove frames added by DebugClassLoader.
530-
for ($i = \count($backtrace) - 2; 0 < $i; --$i) {
531-
if (DebugClassLoader::class === ($backtrace[$i]['class'] ?? null)) {
532-
$backtrace = [$backtrace[$i + 1]];
533-
break;
531+
$backtrace = \array_slice($backtrace, $i);
532+
} else {
533+
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
534+
// Clean the trace by removing first frames added by the error handler itself.
535+
for ($i = 0; isset($backtrace[$i]); ++$i) {
536+
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
537+
$backtrace = \array_slice($backtrace, 1 + $i);
538+
break;
539+
}
540+
}
541+
542+
// Remove frames added by DebugClassLoader.
543+
for ($i = \count($backtrace) - 2; 0 < $i; --$i) {
544+
if (DebugClassLoader::class === ($backtrace[$i]['class'] ?? null)) {
545+
$backtrace = [$backtrace[$i + 1]];
546+
break;
547+
}
534548
}
535549
}
536550

551+
$class = $backtrace[0]['class'];
552+
$function = $backtrace[0]['function'];
553+
537554
$collectedLogs[$message] = [
538555
'type' => $type,
539556
'message' => $message,
557+
'deprecation' => $message,
540558
'file' => $file,
559+
'triggering_file' => $file,
541560
'line' => $line,
561+
'class' => $class,
562+
'method' => $function,
542563
'trace' => [$backtrace[0]],
543564
'count' => 1,
544565
];
@@ -553,7 +574,7 @@ protected function initializeContainer()
553574
if ($this->debug && true !== $previousHandler) {
554575
restore_error_handler();
555576

556-
file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
577+
file_put_contents($deprecationsFilename, serialize(array_values($collectedLogs)));
557578
file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
558579
}
559580
}

0 commit comments

Comments
 (0)
0