From 5c5011842b5b278b4b40e2087312e1af195e2143 Mon Sep 17 00:00:00 2001 From: schlndh Date: Sun, 7 Jan 2024 13:32:45 +0100 Subject: [PATCH] optimize repeated container creation in tests --- src/Testing/TestCase.neon | 3 ++ src/Testing/TestCaseSourceLocatorFactory.php | 30 ++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Testing/TestCase.neon b/src/Testing/TestCase.neon index 6f03c38e63..cfa21959b9 100644 --- a/src/Testing/TestCase.neon +++ b/src/Testing/TestCase.neon @@ -9,6 +9,9 @@ services: arguments: phpParser: @phpParserDecorator php8Parser: @php8PhpParser + fileExtensions: %fileExtensions% + obsoleteExcludesAnalyse: %excludes_analyse% + excludePaths: %excludePaths% cacheStorage: class: PHPStan\Cache\MemoryCacheStorage diff --git a/src/Testing/TestCaseSourceLocatorFactory.php b/src/Testing/TestCaseSourceLocatorFactory.php index faeaaea61b..fccedd9ec1 100644 --- a/src/Testing/TestCaseSourceLocatorFactory.php +++ b/src/Testing/TestCaseSourceLocatorFactory.php @@ -12,6 +12,7 @@ use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator; use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator; use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator; +use PHPStan\Php\PhpVersion; use PHPStan\Reflection\BetterReflection\SourceLocator\AutoloadSourceLocator; use PHPStan\Reflection\BetterReflection\SourceLocator\ComposerJsonAndInstalledJsonSourceLocatorMaker; use PHPStan\Reflection\BetterReflection\SourceLocator\FileNodesFetcher; @@ -19,10 +20,20 @@ use ReflectionClass; use function dirname; use function is_file; +use function serialize; +use function sha1; class TestCaseSourceLocatorFactory { + /** @var array> */ + private static array $composerSourceLocatorsCache = []; + + /** + * @param string[] $fileExtensions + * @param string[] $obsoleteExcludesAnalyse + * @param array{analyse?: array, analyseAndScan?: array}|null $excludePaths + */ public function __construct( private ComposerJsonAndInstalledJsonSourceLocatorMaker $composerJsonAndInstalledJsonSourceLocatorMaker, private Parser $phpParser, @@ -30,6 +41,10 @@ public function __construct( private FileNodesFetcher $fileNodesFetcher, private PhpStormStubsSourceStubber $phpstormStubsSourceStubber, private ReflectionSourceStubber $reflectionSourceStubber, + private PhpVersion $phpVersion, + private array $fileExtensions, + private array $obsoleteExcludesAnalyse, + private ?array $excludePaths, ) { } @@ -38,8 +53,14 @@ public function create(): SourceLocator { $classLoaders = ClassLoader::getRegisteredLoaders(); $classLoaderReflection = new ReflectionClass(ClassLoader::class); - $locators = []; - if ($classLoaderReflection->hasProperty('vendorDir')) { + $cacheKey = sha1(serialize([ + $this->phpVersion->getVersionId(), + $this->fileExtensions, + $this->obsoleteExcludesAnalyse, + $this->excludePaths, + ])); + if ($classLoaderReflection->hasProperty('vendorDir') && ! isset(self::$composerSourceLocatorsCache[$cacheKey])) { + $composerLocators = []; $vendorDirProperty = $classLoaderReflection->getProperty('vendorDir'); $vendorDirProperty->setAccessible(true); foreach ($classLoaders as $classLoader) { @@ -52,10 +73,13 @@ public function create(): SourceLocator if ($composerSourceLocator === null) { continue; } - $locators[] = $composerSourceLocator; + $composerLocators[] = $composerSourceLocator; } + + self::$composerSourceLocatorsCache[$cacheKey] = $composerLocators; } + $locators = self::$composerSourceLocatorsCache[$cacheKey] ?? []; $astLocator = new Locator($this->phpParser); $astPhp8Locator = new Locator($this->php8Parser);