|
42 | 42 | use ShipMonk\PHPStan\DeadCode\Provider\VendorUsageProvider;
|
43 | 43 | use ShipMonk\PHPStan\DeadCode\Provider\VirtualUsageData;
|
44 | 44 | use ShipMonk\PHPStan\DeadCode\Transformer\FileSystem;
|
| 45 | +use Throwable; |
| 46 | +use Traversable; |
| 47 | +use function array_merge; |
| 48 | +use function error_reporting; |
45 | 49 | use function file_get_contents;
|
46 | 50 | use function is_array;
|
| 51 | +use function iterator_to_array; |
| 52 | +use function ob_end_clean; |
| 53 | +use function ob_start; |
47 | 54 | use function preg_replace;
|
48 | 55 | use function str_replace;
|
49 | 56 | use function strpos;
|
| 57 | +use const E_ALL; |
| 58 | +use const E_DEPRECATED; |
50 | 59 | use const PHP_VERSION_ID;
|
51 | 60 |
|
52 | 61 | /**
|
@@ -126,6 +135,53 @@ public function testDeadWithGroups($files, bool $requirementsMet = true): void
|
126 | 135 | $this->doTestDead($files, $requirementsMet);
|
127 | 136 | }
|
128 | 137 |
|
| 138 | + /** |
| 139 | + * Ensure we test real PHP code |
| 140 | + * - mainly targets invalid class/trait/iface compositions |
| 141 | + * |
| 142 | + * @runInSeparateProcess |
| 143 | + */ |
| 144 | + public function testNoFatalError(): void |
| 145 | + { |
| 146 | + if (PHP_VERSION_ID < 8_04_00) { |
| 147 | + self::markTestSkipped('Requires PHP 8.4+ to allow any PHP feature in test code'); |
| 148 | + } |
| 149 | + |
| 150 | + // when lowest versions are installed, we get "Implicitly marking parameter xxx as nullable is deprecated" for symfony deps |
| 151 | + error_reporting(E_ALL & ~E_DEPRECATED); |
| 152 | + |
| 153 | + $required = []; |
| 154 | + |
| 155 | + $fileProviders = array_merge( |
| 156 | + iterator_to_array(self::provideFiles(), false), |
| 157 | + iterator_to_array(self::provideGroupingFiles(), false), |
| 158 | + iterator_to_array(self::provideAutoRemoveFiles(), false), |
| 159 | + ); |
| 160 | + |
| 161 | + foreach ($fileProviders as $args) { |
| 162 | + $files = is_array($args[0]) ? $args[0] : [$args[0]]; |
| 163 | + |
| 164 | + foreach ($files as $file) { |
| 165 | + if (isset($required[$file])) { |
| 166 | + continue; |
| 167 | + } |
| 168 | + |
| 169 | + try { |
| 170 | + ob_start(); |
| 171 | + require $file; |
| 172 | + ob_end_clean(); |
| 173 | + |
| 174 | + } catch (Throwable $e) { |
| 175 | + self::fail("Fatal error in {$e->getFile()}:{$e->getLine()}:\n {$e->getMessage()}"); |
| 176 | + } |
| 177 | + |
| 178 | + $required[$file] = true; |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + $this->expectNotToPerformAssertions(); |
| 183 | + } |
| 184 | + |
129 | 185 | /**
|
130 | 186 | * @param string|non-empty-list<string> $files
|
131 | 187 | */
|
@@ -371,9 +427,9 @@ public function testGrouping($files, array $expectedErrors): void
|
371 | 427 | }
|
372 | 428 |
|
373 | 429 | /**
|
374 |
| - * @return iterable<string, array{0: string|list<string>, 1: list<array{0: string, 1: int, 2?: string|null}>}> |
| 430 | + * @return Traversable<string, array{0: string|list<string>, 1: list<array{0: string, 1: int, 2?: string|null}>}> |
375 | 431 | */
|
376 |
| - public static function provideGroupingFiles(): iterable |
| 432 | + public static function provideGroupingFiles(): Traversable |
377 | 433 | {
|
378 | 434 | yield 'default' => [
|
379 | 435 | __DIR__ . '/data/grouping/default.php',
|
@@ -454,9 +510,9 @@ public static function provideGroupingFiles(): iterable
|
454 | 510 | }
|
455 | 511 |
|
456 | 512 | /**
|
457 |
| - * @return array<string, array{0: string|list<string>, 1?: bool}> |
| 513 | + * @return Traversable<string, array{0: string|list<string>, 1?: bool}> |
458 | 514 | */
|
459 |
| - public static function provideFiles(): iterable |
| 515 | + public static function provideFiles(): Traversable |
460 | 516 | {
|
461 | 517 | // methods
|
462 | 518 | yield 'method-anonym' => [__DIR__ . '/data/methods/anonym.php'];
|
@@ -572,9 +628,9 @@ public static function provideFiles(): iterable
|
572 | 628 | }
|
573 | 629 |
|
574 | 630 | /**
|
575 |
| - * @return iterable<string, array{0: string}> |
| 631 | + * @return Traversable<string, array{0: string}> |
576 | 632 | */
|
577 |
| - public function provideAutoRemoveFiles(): iterable |
| 633 | + public static function provideAutoRemoveFiles(): Traversable |
578 | 634 | {
|
579 | 635 | yield 'sample' => [__DIR__ . '/data/removing/sample.php'];
|
580 | 636 | yield 'no-namespace' => [__DIR__ . '/data/removing/no-namespace.php'];
|
|
0 commit comments