Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 116907f

Browse files
committed
Put undetermined deprecations in the "other" group
Sometimes, you cannot easily know if code was written by a vendor or directly in the application, for instance if the code comes from a file in the cache. In that case, it is better not to classify the deprecation as direct or indirect.
1 parent ada3fdb commit 116907f

File tree

9 files changed

+113
-54
lines changed

9 files changed

+113
-54
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,13 @@ public function handleError($type, $msg, $file, $line, $context = [])
139139
$group = 'unsilenced';
140140
} elseif ($deprecation->isLegacy(self::$utilPrefix)) {
141141
$group = 'legacy';
142-
} elseif (!$deprecation->isSelf()) {
143-
$group = $deprecation->isIndirect() ? 'remaining indirect' : 'remaining direct';
144142
} else {
145-
$group = 'remaining self';
143+
$group = [
144+
Deprecation::TYPE_SELF => 'remaining self',
145+
Deprecation::TYPE_DIRECT => 'remaining direct',
146+
Deprecation::TYPE_INDIRECT => 'remaining indirect',
147+
Deprecation::TYPE_UNDETERMINED => 'other',
148+
][$deprecation->getType()];
146149
}
147150

148151
if ($this->getConfiguration()->shouldDisplayStackTrace($msg)) {

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

Lines changed: 69 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
*/
1919
class Deprecation
2020
{
21+
private const PATH_TYPE_VENDOR = 'path_type_vendor';
22+
private const PATH_TYPE_SELF = 'path_type_internal';
23+
private const PATH_TYPE_UNDETERMINED = 'path_type_undetermined';
24+
25+
public const TYPE_SELF = 'type_self';
26+
public const TYPE_DIRECT = 'type_direct';
27+
public const TYPE_INDIRECT = 'type_indirect';
28+
public const TYPE_UNDETERMINED = 'type_undetermined';
29+
2130
/**
2231
* @var array
2332
*/
@@ -39,13 +48,20 @@ class Deprecation
3948
private $originMethod;
4049

4150
/**
42-
* @var bool
51+
* @var string one of the PATH_TYPE_* constants
4352
*/
44-
private $self;
53+
private $triggeringFilePathType;
4554

4655
/** @var string[] absolute paths to vendor directories */
4756
private static $vendors;
4857

58+
/**
59+
* @var string[] absolute paths to source or tests of the project. This
60+
* excludes cache directories, because it is based on autoloading rules and
61+
* cache systems typically do not use those.
62+
*/
63+
private static $internalPaths;
64+
4965
/**
5066
* @param string $message
5167
* @param string $file
@@ -59,7 +75,7 @@ public function __construct($message, array $trace, $file)
5975
// No-op
6076
}
6177
$line = $trace[$i];
62-
$this->self = !$this->pathOriginatesFromVendor($file);
78+
$this->trigerringFilePathType = $this->getPathType($file);
6379
if (isset($line['object']) || isset($line['class'])) {
6480
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
6581
$parsedMsg = unserialize($this->message);
@@ -70,8 +86,9 @@ public function __construct($message, array $trace, $file)
7086
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
7187
// then we need to use the serialized information to determine
7288
// if the error has been triggered from vendor code.
73-
$this->self = isset($parsedMsg['triggering_file'])
74-
&& $this->pathOriginatesFromVendor($parsedMsg['triggering_file']);
89+
if (isset($parsedMsg['triggering_file'])) {
90+
$this->trigerringFilePathType = $this->getPathType($parsedMsg['triggering_file']);
91+
}
7592

7693
return;
7794
}
@@ -101,14 +118,6 @@ public function originatesFromAnObject()
101118
return isset($this->originClass);
102119
}
103120

104-
/**
105-
* @return bool
106-
*/
107-
public function isSelf()
108-
{
109-
return $this->self;
110-
}
111-
112121
/**
113122
* @return string
114123
*/
@@ -163,10 +172,16 @@ public function isLegacy($utilPrefix)
163172
* Tells whether both the calling package and the called package are vendor
164173
* packages.
165174
*
166-
* @return bool
175+
* @return string
167176
*/
168-
public function isIndirect()
177+
public function getType()
169178
{
179+
if (self::PATH_TYPE_SELF === $this->trigerringFilePathType) {
180+
return self::TYPE_SELF;
181+
}
182+
if (self::PATH_TYPE_UNDETERMINED === $this->trigerringFilePathType) {
183+
return self::TYPE_UNDETERMINED;
184+
}
170185
$erroringFile = $erroringPackage = null;
171186
foreach ($this->trace as $line) {
172187
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
@@ -179,25 +194,28 @@ public function isIndirect()
179194
if ('-' === $file || 'Standard input code' === $file || !realpath($file)) {
180195
continue;
181196
}
182-
if (!$this->pathOriginatesFromVendor($file)) {
183-
return false;
197+
if (self::PATH_TYPE_SELF === $this->getPathType($file)) {
198+
return self::TYPE_DIRECT;
199+
}
200+
if (self::PATH_TYPE_UNDETERMINED === $this->getPathType($file)) {
201+
return self::TYPE_UNDETERMINED;
184202
}
185203
if (null !== $erroringFile && null !== $erroringPackage) {
186204
$package = $this->getPackage($file);
187205
if ('composer' !== $package && $package !== $erroringPackage) {
188-
return true;
206+
return self::TYPE_INDIRECT;
189207
}
190208
continue;
191209
}
192210
$erroringFile = $file;
193211
$erroringPackage = $this->getPackage($file);
194212
}
195213

196-
return false;
214+
return self::TYPE_DIRECT;
197215
}
198216

199217
/**
200-
* pathOriginatesFromVendor() should always be called prior to calling this method.
218+
* getPathType() should always be called prior to calling this method.
201219
*
202220
* @param string $path
203221
*
@@ -237,6 +255,15 @@ private static function getVendors()
237255
$v = \dirname(\dirname($r->getFileName()));
238256
if (file_exists($v.'/composer/installed.json')) {
239257
self::$vendors[] = $v;
258+
$loader = require $v.'/autoload.php';
259+
$paths = self::getSourcePathsFromPrefixes(array_merge($loader->getPrefixes(), $loader->getPrefixesPsr4()));
260+
}
261+
}
262+
}
263+
foreach ($paths as $path) {
264+
foreach (self::$vendors as $vendor) {
265+
if (0 !== strpos($path, $vendor)) {
266+
self::$internalPaths[] = $path;
240267
}
241268
}
242269
}
@@ -245,24 +272,41 @@ private static function getVendors()
245272
return self::$vendors;
246273
}
247274

275+
private static function getSourcePathsFromPrefixes(array $prefixesByNamespace)
276+
{
277+
foreach ($prefixesByNamespace as $prefixes) {
278+
foreach ($prefixes as $prefix) {
279+
if (false !== realpath($prefix)) {
280+
yield realpath($prefix);
281+
}
282+
}
283+
}
284+
}
285+
248286
/**
249287
* @param string $path
250288
*
251-
* @return bool
289+
* @return string
252290
*/
253-
private function pathOriginatesFromVendor($path)
291+
private function getPathType($path)
254292
{
255293
$realPath = realpath($path);
256294
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
257-
return true;
295+
return self::PATH_TYPE_UNDETERMINED;
258296
}
259297
foreach (self::getVendors() as $vendor) {
260298
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
261-
return true;
299+
return self::PATH_TYPE_VENDOR;
300+
}
301+
}
302+
303+
foreach (self::$internalPaths as $internalPath) {
304+
if (0 === strpos($realPath, $internalPath)) {
305+
return self::PATH_TYPE_SELF;
262306
}
263307
}
264308

265-
return false;
309+
return self::PATH_TYPE_UNDETERMINED;
266310
}
267311

268312
/**

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function testItCanDetermineTheClassWhereTheDeprecationHappened()
2727
public function testItCanTellWhetherItIsInternal()
2828
{
2929
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
30-
$this->assertTrue($deprecation->isSelf());
30+
$this->assertSame(Deprecation::TYPE_SELF, $deprecation->getType());
3131
}
3232

3333
public function testLegacyTestMethodIsDetectedAsSuch()
@@ -46,7 +46,7 @@ public function testItCanBeConvertedToAString()
4646
public function testItRulesOutFilesOutsideVendorsAsIndirect()
4747
{
4848
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
49-
$this->assertFalse($deprecation->isIndirect());
49+
$this->assertNotSame(Deprecation::TYPE_INDIRECT, $deprecation->getType());
5050
}
5151

5252
/**

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,13 @@ Unsilenced deprecation notices (3)
7373
1x: unsilenced bar deprecation
7474
1x in FooTestCase::testNonLegacyBar
7575

76-
Remaining self deprecation notices (1)
77-
78-
1x: silenced bar deprecation
79-
1x in FooTestCase::testNonLegacyBar
80-
8176
Legacy deprecation notices (1)
8277

83-
Other deprecation notices (1)
78+
Other deprecation notices (2)
8479

8580
1x: root deprecation
8681

82+
1x: silenced bar deprecation
83+
1x in FooTestCase::testNonLegacyBar
84+
8785
I get precedence over any exit statements inside the deprecation error handler.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
<?php
22

33
require_once __DIR__.'/composer/autoload_real.php';
4+
5+
return ComposerAutoloaderInitFake::getLoader();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
<?php
22

3+
class ComposerLoaderFake
4+
{
5+
public function getPrefixes()
6+
{
7+
return [];
8+
}
9+
10+
public function getPrefixesPsr4()
11+
{
12+
return [];
13+
}
14+
}
15+
316
class ComposerAutoloaderInitFake
417
{
18+
public static function getLoader()
19+
{
20+
return new ComposerLoaderFake();
21+
}
522
}

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/self_on_non_vendor.phpt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,12 @@ Unsilenced deprecation notices (3)
6161
1x: unsilenced bar deprecation
6262
1x in FooTestCase::testNonLegacyBar
6363

64-
Remaining self deprecation notices (1)
65-
66-
1x: silenced bar deprecation
67-
1x in FooTestCase::testNonLegacyBar
68-
6964
Legacy deprecation notices (1)
7065

71-
Other deprecation notices (1)
66+
Other deprecation notices (2)
7267

7368
1x: root deprecation
7469

70+
1x: silenced bar deprecation
71+
1x in FooTestCase::testNonLegacyBar
72+

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/shutdown_deprecations.phpt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,15 @@ Unsilenced deprecation notices (3)
7373
1x: unsilenced bar deprecation
7474
1x in FooTestCase::testNonLegacyBar
7575

76-
Remaining self deprecation notices (1)
77-
78-
1x: silenced bar deprecation
79-
1x in FooTestCase::testNonLegacyBar
80-
8176
Legacy deprecation notices (1)
8277

83-
Other deprecation notices (1)
78+
Other deprecation notices (2)
8479

8580
1x: root deprecation
8681

82+
1x: silenced bar deprecation
83+
1x in FooTestCase::testNonLegacyBar
84+
8785
Shutdown-time deprecations:
8886

8987
Other deprecation notices (1)

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_non_vendor.phpt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,13 @@ Unsilenced deprecation notices (3)
6161
1x: unsilenced bar deprecation
6262
1x in FooTestCase::testNonLegacyBar
6363

64-
Remaining self deprecation notices (1)
65-
66-
1x: silenced bar deprecation
67-
1x in FooTestCase::testNonLegacyBar
68-
6964
Legacy deprecation notices (1)
7065

71-
Other deprecation notices (1)
66+
Other deprecation notices (2)
7267

7368
1x: root deprecation
7469

70+
1x: silenced bar deprecation
71+
1x in FooTestCase::testNonLegacyBar
72+
73+

0 commit comments

Comments
 (0)