Revert "Revert "bug #31730 [PhpUnitBridge] More accurate grouping (greg0ire)""
This reverts commit 4814fd3a4e
.
This commit is contained in:
parent
4814fd3a4e
commit
5797e7b2f2
@ -139,10 +139,13 @@ class DeprecationErrorHandler
|
|||||||
$group = 'unsilenced';
|
$group = 'unsilenced';
|
||||||
} elseif ($deprecation->isLegacy(self::$utilPrefix)) {
|
} elseif ($deprecation->isLegacy(self::$utilPrefix)) {
|
||||||
$group = 'legacy';
|
$group = 'legacy';
|
||||||
} elseif (!$deprecation->isSelf()) {
|
|
||||||
$group = $deprecation->isIndirect() ? 'remaining indirect' : 'remaining direct';
|
|
||||||
} else {
|
} else {
|
||||||
$group = 'remaining self';
|
$group = [
|
||||||
|
Deprecation::TYPE_SELF => 'remaining self',
|
||||||
|
Deprecation::TYPE_DIRECT => 'remaining direct',
|
||||||
|
Deprecation::TYPE_INDIRECT => 'remaining indirect',
|
||||||
|
Deprecation::TYPE_UNDETERMINED => 'other',
|
||||||
|
][$deprecation->getType()];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->getConfiguration()->shouldDisplayStackTrace($msg)) {
|
if ($this->getConfiguration()->shouldDisplayStackTrace($msg)) {
|
||||||
|
@ -18,6 +18,15 @@ use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor;
|
|||||||
*/
|
*/
|
||||||
class Deprecation
|
class Deprecation
|
||||||
{
|
{
|
||||||
|
const PATH_TYPE_VENDOR = 'path_type_vendor';
|
||||||
|
const PATH_TYPE_SELF = 'path_type_internal';
|
||||||
|
const PATH_TYPE_UNDETERMINED = 'path_type_undetermined';
|
||||||
|
|
||||||
|
const TYPE_SELF = 'type_self';
|
||||||
|
const TYPE_DIRECT = 'type_direct';
|
||||||
|
const TYPE_INDIRECT = 'type_indirect';
|
||||||
|
const TYPE_UNDETERMINED = 'type_undetermined';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@ -39,13 +48,21 @@ class Deprecation
|
|||||||
private $originMethod;
|
private $originMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var string one of the PATH_TYPE_* constants
|
||||||
*/
|
*/
|
||||||
private $self;
|
private $triggeringFilePathType;
|
||||||
|
|
||||||
/** @var string[] absolute paths to vendor directories */
|
/** @var string[] absolute paths to vendor directories */
|
||||||
private static $vendors;
|
private static $vendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[] absolute paths to source or tests of the project. This
|
||||||
|
* excludes cache directories, because it is based on
|
||||||
|
* autoloading rules and cache systems typically do not use
|
||||||
|
* those.
|
||||||
|
*/
|
||||||
|
private static $internalPaths;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @param string $file
|
* @param string $file
|
||||||
@ -59,7 +76,7 @@ class Deprecation
|
|||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
$line = $trace[$i];
|
$line = $trace[$i];
|
||||||
$this->self = !$this->pathOriginatesFromVendor($file);
|
$this->trigerringFilePathType = $this->getPathType($file);
|
||||||
if (isset($line['object']) || isset($line['class'])) {
|
if (isset($line['object']) || isset($line['class'])) {
|
||||||
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
|
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
|
||||||
$parsedMsg = unserialize($this->message);
|
$parsedMsg = unserialize($this->message);
|
||||||
@ -70,8 +87,9 @@ class Deprecation
|
|||||||
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
|
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
|
||||||
// then we need to use the serialized information to determine
|
// then we need to use the serialized information to determine
|
||||||
// if the error has been triggered from vendor code.
|
// if the error has been triggered from vendor code.
|
||||||
$this->self = isset($parsedMsg['triggering_file'])
|
if (isset($parsedMsg['triggering_file'])) {
|
||||||
&& $this->pathOriginatesFromVendor($parsedMsg['triggering_file']);
|
$this->trigerringFilePathType = $this->getPathType($parsedMsg['triggering_file']);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -101,14 +119,6 @@ class Deprecation
|
|||||||
return isset($this->originClass);
|
return isset($this->originClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isSelf()
|
|
||||||
{
|
|
||||||
return $this->self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -163,10 +173,16 @@ class Deprecation
|
|||||||
* Tells whether both the calling package and the called package are vendor
|
* Tells whether both the calling package and the called package are vendor
|
||||||
* packages.
|
* packages.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function isIndirect()
|
public function getType()
|
||||||
{
|
{
|
||||||
|
if (self::PATH_TYPE_SELF === $this->trigerringFilePathType) {
|
||||||
|
return self::TYPE_SELF;
|
||||||
|
}
|
||||||
|
if (self::PATH_TYPE_UNDETERMINED === $this->trigerringFilePathType) {
|
||||||
|
return self::TYPE_UNDETERMINED;
|
||||||
|
}
|
||||||
$erroringFile = $erroringPackage = null;
|
$erroringFile = $erroringPackage = null;
|
||||||
foreach ($this->trace as $line) {
|
foreach ($this->trace as $line) {
|
||||||
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
|
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
|
||||||
@ -179,13 +195,16 @@ class Deprecation
|
|||||||
if ('-' === $file || 'Standard input code' === $file || !realpath($file)) {
|
if ('-' === $file || 'Standard input code' === $file || !realpath($file)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!$this->pathOriginatesFromVendor($file)) {
|
if (self::PATH_TYPE_SELF === $this->getPathType($file)) {
|
||||||
return false;
|
return self::TYPE_DIRECT;
|
||||||
|
}
|
||||||
|
if (self::PATH_TYPE_UNDETERMINED === $this->getPathType($file)) {
|
||||||
|
return self::TYPE_UNDETERMINED;
|
||||||
}
|
}
|
||||||
if (null !== $erroringFile && null !== $erroringPackage) {
|
if (null !== $erroringFile && null !== $erroringPackage) {
|
||||||
$package = $this->getPackage($file);
|
$package = $this->getPackage($file);
|
||||||
if ('composer' !== $package && $package !== $erroringPackage) {
|
if ('composer' !== $package && $package !== $erroringPackage) {
|
||||||
return true;
|
return self::TYPE_INDIRECT;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -193,11 +212,11 @@ class Deprecation
|
|||||||
$erroringPackage = $this->getPackage($file);
|
$erroringPackage = $this->getPackage($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return self::TYPE_DIRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pathOriginatesFromVendor() should always be called prior to calling this method.
|
* getPathType() should always be called prior to calling this method.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*
|
*
|
||||||
@ -237,6 +256,15 @@ class Deprecation
|
|||||||
$v = \dirname(\dirname($r->getFileName()));
|
$v = \dirname(\dirname($r->getFileName()));
|
||||||
if (file_exists($v.'/composer/installed.json')) {
|
if (file_exists($v.'/composer/installed.json')) {
|
||||||
self::$vendors[] = $v;
|
self::$vendors[] = $v;
|
||||||
|
$loader = require $v.'/autoload.php';
|
||||||
|
$paths = self::getSourcePathsFromPrefixes(array_merge($loader->getPrefixes(), $loader->getPrefixesPsr4()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($paths as $path) {
|
||||||
|
foreach (self::$vendors as $vendor) {
|
||||||
|
if (0 !== strpos($path, $vendor)) {
|
||||||
|
self::$internalPaths[] = $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,24 +273,41 @@ class Deprecation
|
|||||||
return self::$vendors;
|
return self::$vendors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function getSourcePathsFromPrefixes(array $prefixesByNamespace)
|
||||||
|
{
|
||||||
|
foreach ($prefixesByNamespace as $prefixes) {
|
||||||
|
foreach ($prefixes as $prefix) {
|
||||||
|
if (false !== realpath($prefix)) {
|
||||||
|
yield realpath($prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function pathOriginatesFromVendor($path)
|
private function getPathType($path)
|
||||||
{
|
{
|
||||||
$realPath = realpath($path);
|
$realPath = realpath($path);
|
||||||
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
|
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
|
||||||
return true;
|
return self::PATH_TYPE_UNDETERMINED;
|
||||||
}
|
}
|
||||||
foreach (self::getVendors() as $vendor) {
|
foreach (self::getVendors() as $vendor) {
|
||||||
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
|
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
|
||||||
return true;
|
return self::PATH_TYPE_VENDOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
foreach (self::$internalPaths as $internalPath) {
|
||||||
|
if (0 === strpos($realPath, $internalPath)) {
|
||||||
|
return self::PATH_TYPE_SELF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::PATH_TYPE_UNDETERMINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,19 +326,4 @@ class Deprecation
|
|||||||
"\n".str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $exception->getTraceAsString()).
|
"\n".str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $exception->getTraceAsString()).
|
||||||
"\n";
|
"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getPackageFromLine(array $line)
|
|
||||||
{
|
|
||||||
if (!isset($line['file'])) {
|
|
||||||
return 'internal function';
|
|
||||||
}
|
|
||||||
if (!$this->pathOriginatesFromVendor($line['file'])) {
|
|
||||||
return 'source code';
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return $this->getPackage($line['file']);
|
|
||||||
} catch (\RuntimeException $e) {
|
|
||||||
return 'unknown';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class DeprecationTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
|
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
|
||||||
$this->assertTrue($deprecation->isSelf());
|
$this->assertSame(Deprecation::TYPE_SELF, $deprecation->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLegacyTestMethodIsDetectedAsSuch()
|
public function testLegacyTestMethodIsDetectedAsSuch()
|
||||||
@ -52,7 +52,7 @@ class DeprecationTest extends TestCase
|
|||||||
public function testItRulesOutFilesOutsideVendorsAsIndirect()
|
public function testItRulesOutFilesOutsideVendorsAsIndirect()
|
||||||
{
|
{
|
||||||
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
|
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
|
||||||
$this->assertFalse($deprecation->isIndirect());
|
$this->assertNotSame(Deprecation::TYPE_INDIRECT, $deprecation->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,15 +73,13 @@ Unsilenced deprecation notices (3)
|
|||||||
1x: unsilenced bar deprecation
|
1x: unsilenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Remaining self deprecation notices (1)
|
Legacy deprecation notices (1)
|
||||||
|
|
||||||
|
Other deprecation notices (2)
|
||||||
|
|
||||||
|
1x: root deprecation
|
||||||
|
|
||||||
1x: silenced bar deprecation
|
1x: silenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Legacy deprecation notices (1)
|
|
||||||
|
|
||||||
Other deprecation notices (1)
|
|
||||||
|
|
||||||
1x: root deprecation
|
|
||||||
|
|
||||||
I get precedence over any exit statements inside the deprecation error handler.
|
I get precedence over any exit statements inside the deprecation error handler.
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once __DIR__.'/composer/autoload_real.php';
|
require_once __DIR__.'/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInitFake::getLoader();
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
class ComposerLoaderFake
|
||||||
|
{
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ComposerAutoloaderInitFake
|
class ComposerAutoloaderInitFake
|
||||||
{
|
{
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
return new ComposerLoaderFake();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,14 +61,12 @@ Unsilenced deprecation notices (3)
|
|||||||
1x: unsilenced bar deprecation
|
1x: unsilenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Remaining self deprecation notices (1)
|
Legacy deprecation notices (1)
|
||||||
|
|
||||||
|
Other deprecation notices (2)
|
||||||
|
|
||||||
|
1x: root deprecation
|
||||||
|
|
||||||
1x: silenced bar deprecation
|
1x: silenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Legacy deprecation notices (1)
|
|
||||||
|
|
||||||
Other deprecation notices (1)
|
|
||||||
|
|
||||||
1x: root deprecation
|
|
||||||
|
|
||||||
|
@ -73,17 +73,15 @@ Unsilenced deprecation notices (3)
|
|||||||
1x: unsilenced bar deprecation
|
1x: unsilenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Remaining self deprecation notices (1)
|
Legacy deprecation notices (1)
|
||||||
|
|
||||||
|
Other deprecation notices (2)
|
||||||
|
|
||||||
|
1x: root deprecation
|
||||||
|
|
||||||
1x: silenced bar deprecation
|
1x: silenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Legacy deprecation notices (1)
|
|
||||||
|
|
||||||
Other deprecation notices (1)
|
|
||||||
|
|
||||||
1x: root deprecation
|
|
||||||
|
|
||||||
Shutdown-time deprecations:
|
Shutdown-time deprecations:
|
||||||
|
|
||||||
Other deprecation notices (1)
|
Other deprecation notices (1)
|
||||||
|
@ -61,14 +61,13 @@ Unsilenced deprecation notices (3)
|
|||||||
1x: unsilenced bar deprecation
|
1x: unsilenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Remaining self deprecation notices (1)
|
Legacy deprecation notices (1)
|
||||||
|
|
||||||
|
Other deprecation notices (2)
|
||||||
|
|
||||||
|
1x: root deprecation
|
||||||
|
|
||||||
1x: silenced bar deprecation
|
1x: silenced bar deprecation
|
||||||
1x in FooTestCase::testNonLegacyBar
|
1x in FooTestCase::testNonLegacyBar
|
||||||
|
|
||||||
Legacy deprecation notices (1)
|
|
||||||
|
|
||||||
Other deprecation notices (1)
|
|
||||||
|
|
||||||
1x: root deprecation
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user