Skip to content

Commit e3b29a5

Browse files
committed
Cache PHPStorm stubs
1 parent afa988b commit e3b29a5

File tree

3 files changed

+112
-5
lines changed

3 files changed

+112
-5
lines changed

src/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
1414
use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
1515
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
16+
use PHPStan\Cache\Cache;
1617
use PHPStan\DependencyInjection\AutowiredParameter;
1718
use PHPStan\DependencyInjection\AutowiredService;
1819
use PHPStan\Php\PhpVersion;
@@ -28,6 +29,7 @@
2829
use PHPStan\Reflection\BetterReflection\SourceLocator\RewriteClassAliasSourceLocator;
2930
use PHPStan\Reflection\BetterReflection\SourceLocator\SkipClassAliasSourceLocator;
3031
use PHPStan\Reflection\BetterReflection\SourceLocator\SkipPolyfillSourceLocator;
32+
use PHPStan\Reflection\BetterReflection\SourceStubber\CachedPhpStormStubsSourceStubber;
3133
use function array_merge;
3234
use function array_unique;
3335
use function count;
@@ -74,6 +76,7 @@ public function __construct(
7476
private bool $playgroundMode, // makes all PHPStan classes in the PHAR discoverable with PSR-4
7577
#[AutowiredParameter]
7678
private ?string $singleReflectionFile,
79+
private Cache $cache,
7780
)
7881
{
7982
}
@@ -160,13 +163,18 @@ public function create(): SourceLocator
160163
);
161164
}
162165
}
166+
$cachedPhpstormSourceStubber = new CachedPhpStormStubsSourceStubber(
167+
$this->phpstormStubsSourceStubber,
168+
$this->cache,
169+
$this->phpVersion,
170+
);
163171

164172
$locators[] = new RewriteClassAliasSourceLocator(new AggregateSourceLocator($fileLocators));
165-
$locators[] = new SkipClassAliasSourceLocator(new PhpInternalSourceLocator($astPhp8Locator, $this->phpstormStubsSourceStubber));
173+
$locators[] = new SkipClassAliasSourceLocator(new PhpInternalSourceLocator($astPhp8Locator, $cachedPhpstormSourceStubber));
166174

167175
$locators[] = new AutoloadSourceLocator($this->fileNodesFetcher, true);
168-
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
169-
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
176+
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $cachedPhpstormSourceStubber);
177+
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $cachedPhpstormSourceStubber);
170178

171179
return new MemoizingSourceLocator(new AggregateSourceLocator($locators));
172180
}

src/Reflection/BetterReflection/SourceLocator/PhpVersionBlacklistSourceLocator.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99
use PHPStan\BetterReflection\Reflector\Reflector;
1010
use PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
1111
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
12+
use PHPStan\Reflection\BetterReflection\SourceStubber\CachedPhpStormStubsSourceStubber;
1213

1314
final class PhpVersionBlacklistSourceLocator implements SourceLocator
1415
{
1516

1617
public function __construct(
17-
private SourceLocator $sourceLocator,
18-
private PhpStormStubsSourceStubber $phpStormStubsSourceStubber,
18+
private SourceLocator $sourceLocator,
19+
private PhpStormStubsSourceStubber|CachedPhpStormStubsSourceStubber $phpStormStubsSourceStubber,
1920
)
2021
{
2122
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Reflection\BetterReflection\SourceStubber;
4+
5+
use PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
6+
use PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber;
7+
use PHPStan\BetterReflection\SourceLocator\SourceStubber\StubData;
8+
use PHPStan\Cache\Cache;
9+
use PHPStan\Internal\ComposerHelper;
10+
use PHPStan\Php\PhpVersion;
11+
use function array_key_exists;
12+
use function sprintf;
13+
14+
final class CachedPhpStormStubsSourceStubber implements SourceStubber
15+
{
16+
17+
/** @var array<string, mixed> */
18+
private array $cached;
19+
20+
public function __construct(
21+
private PhpStormStubsSourceStubber $sourceStubber,
22+
private Cache $cache,
23+
private PhpVersion $phpVersion,
24+
)
25+
{
26+
[$cacheKey, $variableCacheKey] = $this->getCacheKeys();
27+
$this->cached = $this->cache->load($cacheKey, $variableCacheKey) ?? [];
28+
}
29+
30+
/**
31+
* @return array{non-empty-string, string}
32+
*/
33+
private function getCacheKeys(): array
34+
{
35+
$stubsVersion = 'dev-master#5fd9e4ef2b4c2a00848ea62d78bf3aa81f43e038';
36+
$cacheKey = 'phpstorm-stubs';
37+
$variableCacheKey = sprintf('v1-%s-%s-%s', ComposerHelper::getBetterReflectionVersion(), $this->phpVersion->getVersionString(), $stubsVersion);
38+
39+
return [$cacheKey, $variableCacheKey];
40+
}
41+
42+
public function generateClassStub(string $className): ?StubData
43+
{
44+
$this->cached['classes'] ??= [];
45+
if (!array_key_exists($className, $this->cached['classes'])) {
46+
$this->cached['classes'][$className] = $this->sourceStubber->generateClassStub($className);
47+
$this->storeCache();
48+
}
49+
return $this->cached['classes'][$className];
50+
}
51+
52+
public function generateFunctionStub(string $functionName): ?StubData
53+
{
54+
$this->cached['functions'] ??= [];
55+
if (!array_key_exists($functionName, $this->cached['functions'])) {
56+
$this->cached['functions'][$functionName] = $this->sourceStubber->generateFunctionStub($functionName);
57+
$this->storeCache();
58+
}
59+
return $this->cached['functions'][$functionName];
60+
}
61+
62+
public function generateConstantStub(string $constantName): ?StubData
63+
{
64+
$this->cached['constants'] ??= [];
65+
if (!array_key_exists($constantName, $this->cached['constants'])) {
66+
$this->cached['constants'][$constantName] = $this->sourceStubber->generateConstantStub($constantName);
67+
$this->storeCache();
68+
}
69+
return $this->cached['constants'][$constantName];
70+
}
71+
72+
public function isPresentClass(string $className): ?bool
73+
{
74+
$this->cached['isPresentClass'] ??= [];
75+
if (!array_key_exists($className, $this->cached['isPresentClass'])) {
76+
$this->cached['isPresentClass'][$className] = $this->sourceStubber->isPresentClass($className);
77+
$this->storeCache();
78+
}
79+
return $this->cached['isPresentClass'][$className];
80+
}
81+
82+
public function isPresentFunction(string $functionName): ?bool
83+
{
84+
$this->cached['isPresentFunction'] ??= [];
85+
if (!array_key_exists($functionName, $this->cached['isPresentFunction'])) {
86+
$this->cached['isPresentFunction'][$functionName] = $this->sourceStubber->isPresentFunction($functionName);
87+
$this->storeCache();
88+
}
89+
return $this->cached['isPresentFunction'][$functionName];
90+
}
91+
92+
private function storeCache(): void
93+
{
94+
[$cacheKey, $variableCacheKey] = $this->getCacheKeys();
95+
$this->cache->save($cacheKey, $variableCacheKey, $this->cached);
96+
}
97+
98+
}

0 commit comments

Comments
 (0)