Skip to content

Commit e668664

Browse files
xificurkclaude
andcommitted
Remove Reflector from StubFilesExtensionLoader, replace with version checks
The loader previously used BetterReflection's Reflector to check whether InputBag existed before loading its stubs. This triggered SourceLocator initialization (an expensive cache-populating operation) on every analysis run. Replace the reflectClass() call with an isInstalledVersionBelow() version check (InputBag was introduced in symfony/http-foundation 5.1). Add a test that wires a ThrowingSourceLocator into the DI container's betterReflectionSourceLocator service, so any future regression that causes getFiles() to touch BetterReflection will fail the test explicitly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 809c1e6 commit e668664

4 files changed

Lines changed: 57 additions & 15 deletions

File tree

src/Stubs/Symfony/StubFilesExtensionLoader.php

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
use Composer\InstalledVersions;
66
use OutOfBoundsException;
7-
use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
8-
use PHPStan\BetterReflection\Reflector\Reflector;
97
use PHPStan\PhpDoc\StubFilesExtension;
108
use function class_exists;
119
use function dirname;
@@ -14,15 +12,6 @@
1412
class StubFilesExtensionLoader implements StubFilesExtension
1513
{
1614

17-
private Reflector $reflector;
18-
19-
public function __construct(
20-
Reflector $reflector
21-
)
22-
{
23-
$this->reflector = $reflector;
24-
}
25-
2615
public function getFiles(): array
2716
{
2817
$stubsDir = dirname(dirname(dirname(__DIR__))) . '/stubs';
@@ -82,12 +71,9 @@ public function getFiles(): array
8271
if ($this->isInstalledVersionBelow('symfony/http-foundation', '7.4.0.0')) {
8372
$files[] = $stubsDir . '/Symfony/Component/HttpFoundation/ParameterBag.stub';
8473

85-
try {
86-
$this->reflector->reflectClass('Symfony\Component\HttpFoundation\InputBag');
74+
if (!$this->isInstalledVersionBelow('symfony/http-foundation', '5.1.0.0')) {
8775
$files[] = $stubsDir . '/Symfony/Component/HttpFoundation/InputBag.stub';
8876
$files[] = $stubsDir . '/Symfony/Component/HttpFoundation/Request.stub';
89-
} catch (IdentifierNotFound $e) {
90-
// Don't load the InputBag and the associated Request stubs for older Symfony versions that did not have InputBag yet to avoid breaking the Request.
9177
}
9278
}
9379

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Stubs\Symfony;
4+
5+
use PHPStan\Testing\PHPStanTestCase;
6+
7+
final class StubFilesExtensionLoaderTest extends PHPStanTestCase
8+
{
9+
10+
public function testGetFilesDoesNotUseSourceLocator(): void
11+
{
12+
$loader = self::getContainer()->getByType(StubFilesExtensionLoader::class);
13+
foreach ($loader->getFiles() as $file) {
14+
self::assertFileExists($file);
15+
}
16+
}
17+
18+
public static function getAdditionalConfigFiles(): array
19+
{
20+
return [
21+
__DIR__ . '/../../../extension.neon',
22+
__DIR__ . '/stub-loader-test.neon',
23+
];
24+
}
25+
26+
}
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+
namespace PHPStan\Stubs\Symfony;
4+
5+
use PHPStan\BetterReflection\Identifier\Identifier;
6+
use PHPStan\BetterReflection\Identifier\IdentifierType;
7+
use PHPStan\BetterReflection\Reflection\Reflection;
8+
use PHPStan\BetterReflection\Reflector\Reflector;
9+
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
10+
use PHPUnit\Framework\Assert;
11+
12+
final class ThrowingSourceLocator implements SourceLocator
13+
{
14+
15+
public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection
16+
{
17+
Assert::fail('SourceLocator::locateIdentifier must not be called during getFiles()');
18+
}
19+
20+
public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
21+
{
22+
Assert::fail('SourceLocator::locateIdentifiersByType must not be called during getFiles()');
23+
}
24+
25+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
services:
2+
betterReflectionSourceLocator:
3+
class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator
4+
factory: PHPStan\Stubs\Symfony\ThrowingSourceLocator
5+
autowired: false

0 commit comments

Comments
 (0)