Skip to content

Commit 66d3923

Browse files
Filter stack trace based on configured deprecation trigger functions/methods
1 parent 2058330 commit 66d3923

File tree

16 files changed

+360
-2
lines changed

16 files changed

+360
-2
lines changed

src/Runner/ErrorHandler.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use const E_USER_NOTICE;
2626
use const E_USER_WARNING;
2727
use const E_WARNING;
28+
use function array_keys;
2829
use function array_values;
2930
use function assert;
3031
use function debug_backtrace;
@@ -56,6 +57,11 @@ final class ErrorHandler
5657
private readonly Source $source;
5758
private readonly SourceFilter $sourceFilter;
5859

60+
/**
61+
* @psalm-var array{functions: list<non-empty-string>, methods: list<array{className: class-string, methodName: non-empty-string}>}
62+
*/
63+
private ?array $deprecationTriggers = null;
64+
5965
public static function instance(): self
6066
{
6167
return self::$instance ?? self::$instance = new self(Registry::get()->source());
@@ -218,6 +224,14 @@ public function useBaseline(Baseline $baseline): void
218224
$this->baseline = $baseline;
219225
}
220226

227+
/**
228+
* @psalm-param array{functions: list<non-empty-string>, methods: list<array{className: class-string, methodName: non-empty-string}>} $deprecationTriggers
229+
*/
230+
public function useDeprecationTriggers(array $deprecationTriggers): void
231+
{
232+
$this->deprecationTriggers = $deprecationTriggers;
233+
}
234+
221235
/**
222236
* @psalm-param non-empty-string $file
223237
* @psalm-param positive-int $line
@@ -274,6 +288,29 @@ private function cleanedTrace(): array
274288
// self::cleanedTrace(), self::trigger(), self::__invoke()
275289
unset($trace[0], $trace[1], $trace[2]);
276290

291+
foreach (array_keys($trace) as $frame) {
292+
foreach ($this->deprecationTriggers['functions'] as $function) {
293+
if (!isset($trace[$frame]['class']) &&
294+
isset($trace[$frame]['function']) &&
295+
$trace[$frame]['function'] === $function) {
296+
unset($trace[$frame]);
297+
298+
continue 2;
299+
}
300+
}
301+
302+
foreach ($this->deprecationTriggers['methods'] as $method) {
303+
if (isset($trace[$frame]['class']) &&
304+
$trace[$frame]['class'] === $method['className'] &&
305+
isset($trace[$frame]['function']) &&
306+
$trace[$frame]['function'] === $method['methodName']) {
307+
unset($trace[$frame]);
308+
309+
continue 2;
310+
}
311+
}
312+
}
313+
277314
return array_values($trace);
278315
}
279316
}

src/TextUI/Application.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public function run(array $argv): int
187187

188188
$baselineGenerator = $this->configureBaseline($configuration);
189189

190-
$this->validateDeprecationTriggers($configuration);
190+
$this->configureDeprecationTriggers($configuration);
191191

192192
EventFacade::instance()->seal();
193193

@@ -702,8 +702,13 @@ private function filteredTests(Configuration $configuration, TestSuite $suite):
702702
return $suite->collect();
703703
}
704704

705-
private function validateDeprecationTriggers(Configuration $configuration): void
705+
private function configureDeprecationTriggers(Configuration $configuration): void
706706
{
707+
$deprecationTriggers = [
708+
'functions' => [],
709+
'methods' => [],
710+
];
711+
707712
foreach ($configuration->source()->deprecationTriggers()['functions'] as $function) {
708713
if (!function_exists($function)) {
709714
EventFacade::emitter()->testRunnerTriggeredWarning(
@@ -712,7 +717,11 @@ private function validateDeprecationTriggers(Configuration $configuration): void
712717
$function,
713718
),
714719
);
720+
721+
continue;
715722
}
723+
724+
$deprecationTriggers['functions'][] = $function;
716725
}
717726

718727
foreach ($configuration->source()->deprecationTriggers()['methods'] as $method) {
@@ -737,7 +746,16 @@ private function validateDeprecationTriggers(Configuration $configuration): void
737746
$methodName,
738747
),
739748
);
749+
750+
continue;
740751
}
752+
753+
$deprecationTriggers['methods'][] = [
754+
'className' => $className,
755+
'methodName' => $methodName,
756+
];
741757
}
758+
759+
ErrorHandler::instance()->useDeprecationTriggers($deprecationTriggers);
742760
}
743761
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="../../../../../phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
>
6+
<testsuites>
7+
<testsuite name="default">
8+
<directory>tests</directory>
9+
</testsuite>
10+
</testsuites>
11+
12+
<source>
13+
<include>
14+
<directory>src</directory>
15+
</include>
16+
17+
<deprecationTrigger>
18+
<function>PHPUnit\TestFixture\SelfDirectIndirect\trigger_deprecation</function>
19+
</deprecationTrigger>
20+
</source>
21+
</phpunit>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TestFixture\SelfDirectIndirect;
11+
12+
use function trigger_error;
13+
14+
final class FirstPartyClass
15+
{
16+
public function method(): true
17+
{
18+
(new ThirdPartyClass)->method();
19+
20+
@trigger_error('deprecation in first-party code', E_USER_DEPRECATED);
21+
22+
return true;
23+
}
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TestFixture\SelfDirectIndirect;
11+
12+
use PHPUnit\Framework\TestCase;
13+
14+
final class FirstPartyClassTest extends TestCase
15+
{
16+
public function testOne(): void
17+
{
18+
$this->assertTrue((new FirstPartyClass)->method());
19+
}
20+
21+
public function testTwo(): void
22+
{
23+
$this->assertTrue((new ThirdPartyClass)->anotherMethod());
24+
}
25+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php declare(strict_types=1);
2+
namespace PHPUnit\TestFixture\SelfDirectIndirect;
3+
4+
final class ThirdPartyClass
5+
{
6+
public function method(): void
7+
{
8+
trigger_deprecation('deprecation in third-party code');
9+
}
10+
11+
public function anotherMethod(): true
12+
{
13+
return (new FirstPartyClass)->method();
14+
}
15+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php declare(strict_types=1);
2+
require __DIR__ . '/../src/FirstPartyClass.php';
3+
require __DIR__ . '/ThirdPartyClass.php';
4+
require __DIR__ . '/trigger_deprecation.php';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php declare(strict_types=1);
2+
namespace PHPUnit\TestFixture\SelfDirectIndirect;
3+
4+
function trigger_deprecation(string $message): void
5+
{
6+
@trigger_error($message, E_USER_DEPRECATED);
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="../../../../../phpunit.xsd"
4+
bootstrap="vendor/autoload.php"
5+
>
6+
<testsuites>
7+
<testsuite name="default">
8+
<directory>tests</directory>
9+
</testsuite>
10+
</testsuites>
11+
12+
<source>
13+
<include>
14+
<directory>src</directory>
15+
</include>
16+
17+
<deprecationTrigger>
18+
<method>PHPUnit\TestFixture\SelfDirectIndirect\DeprecationTrigger::triggerDeprecation</method>
19+
</deprecationTrigger>
20+
</source>
21+
</phpunit>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\TestFixture\SelfDirectIndirect;
11+
12+
use function trigger_error;
13+
14+
final class FirstPartyClass
15+
{
16+
public function method(): true
17+
{
18+
(new ThirdPartyClass)->method();
19+
20+
@trigger_error('deprecation in first-party code', E_USER_DEPRECATED);
21+
22+
return true;
23+
}
24+
}

0 commit comments

Comments
 (0)