Skip to content

Commit 805a078

Browse files
committed
rework
1 parent 08f3a7e commit 805a078

File tree

4 files changed

+122
-166
lines changed

4 files changed

+122
-166
lines changed

src/Reflection/BetterReflection/BetterReflectionSourceLocatorFactory.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@
3131
use PHPStan\Reflection\BetterReflection\SourceLocator\RewriteClassAliasSourceLocator;
3232
use PHPStan\Reflection\BetterReflection\SourceLocator\SkipClassAliasSourceLocator;
3333
use PHPStan\Reflection\BetterReflection\SourceLocator\SkipPolyfillSourceLocator;
34-
use PHPStan\Reflection\BetterReflection\SourceStubber\CachedPhpStormStubsSourceStubber;
3534
use function array_merge;
3635
use function array_unique;
3736
use function count;
3837
use function extension_loaded;
3938
use function is_dir;
4039
use function is_file;
40+
use function sprintf;
4141
use const PHP_VERSION_ID;
4242

4343
#[AutowiredService]
@@ -174,13 +174,13 @@ public function create(): SourceLocator
174174
new PhpInternalSourceLocator($astPhp8Locator, $this->phpstormStubsSourceStubber),
175175
$this->cache,
176176
$this->phpVersion,
177-
sprintf('phpstorm-stubs-php8-%s', $phpstormStubsVersion)
178-
)
177+
sprintf('phpstorm-stubs-php8-%s', $phpstormStubsVersion),
178+
),
179179
);
180180

181181
$locators[] = new AutoloadSourceLocator($this->fileNodesFetcher, true);
182-
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $cachedPhpstormSourceStubber);
183-
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $cachedPhpstormSourceStubber);
182+
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
183+
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
184184

185185
return new MemoizingSourceLocator(new AggregateSourceLocator($locators));
186186
}

src/Reflection/BetterReflection/SourceLocator/FileCachedSourceLocator.php

Lines changed: 116 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,31 @@
22

33
namespace PHPStan\Reflection\BetterReflection\SourceLocator;
44

5-
use Override;
6-
use PhpParser\Node\Arg;
7-
use PhpParser\Node\Expr\FuncCall;
8-
use PhpParser\Node\Name;
9-
use PhpParser\Node\Scalar\String_;
10-
use PhpParser\Node\Stmt\Const_;
115
use PHPStan\BetterReflection\Identifier\Identifier;
126
use PHPStan\BetterReflection\Identifier\IdentifierType;
137
use PHPStan\BetterReflection\Reflection\Reflection;
8+
use PHPStan\BetterReflection\Reflection\ReflectionClass;
149
use PHPStan\BetterReflection\Reflection\ReflectionConstant;
10+
use PHPStan\BetterReflection\Reflection\ReflectionEnum;
11+
use PHPStan\BetterReflection\Reflection\ReflectionFunction;
1512
use PHPStan\BetterReflection\Reflector\Reflector;
16-
use PHPStan\BetterReflection\SourceLocator\Ast\Strategy\NodeToReflection;
17-
use PHPStan\BetterReflection\SourceLocator\Located\LocatedSource;
1813
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
1914
use PHPStan\Cache\Cache;
2015
use PHPStan\Internal\ComposerHelper;
21-
use PHPStan\Node\Expr\TypeExpr;
2216
use PHPStan\Php\PhpVersion;
2317
use PHPStan\Reflection\ConstantNameHelper;
24-
use PHPStan\ShouldNotHappenException;
25-
use PHPStan\Type\ConstantTypeHelper;
26-
use ReflectionClass;
27-
use ReflectionFunction;
2818
use function array_key_exists;
29-
use function array_keys;
30-
use function class_exists;
31-
use function constant;
32-
use function count;
33-
use function defined;
34-
use function function_exists;
35-
use function interface_exists;
36-
use function is_file;
37-
use function is_string;
38-
use function opcache_invalidate;
39-
use function restore_error_handler;
40-
use function set_error_handler;
41-
use function spl_autoload_functions;
19+
use function register_shutdown_function;
20+
use function sprintf;
4221
use function strtolower;
43-
use function trait_exists;
44-
use const PHP_VERSION_ID;
45-
46-
/**
47-
* Use PHP's built in autoloader to locate a class, without actually loading.
48-
*
49-
* There are some prerequisites...
50-
* - we expect the autoloader to load classes from a file (i.e. using require/include)
51-
*
52-
* Modified code from Roave/BetterReflection, Copyright (c) 2017 Roave, LLC.
53-
*/
22+
5423
final class FileCachedSourceLocator implements SourceLocator
5524
{
56-
/** @var array<string, mixed> */
57-
private array $cached;
25+
26+
/** @var array{classes: array<string, ReflectionClass>, functions: array<string, ReflectionFunction>, constants: array<string, ReflectionConstant>}|null */
27+
private ?array $cachedSymbols = null;
28+
29+
private bool $storeOnShutdown = false;
5830

5931
public function __construct(
6032
private SourceLocator $locator,
@@ -63,45 +35,131 @@ public function __construct(
6335
private string $cacheKey,
6436
)
6537
{
66-
$variableCacheKey = $this->getVariableCacheKey();
67-
$this->cached = $this->cache->load($this->cacheKey, $variableCacheKey) ?? [];
6838
}
6939

70-
71-
public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?\PHPStan\BetterReflection\Reflection\Reflection
40+
public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection
7241
{
73-
$key = $identifier->getName();
42+
if ($this->cachedSymbols === null) {
43+
$this->cachedSymbols = $this->loadCache($reflector);
44+
}
45+
46+
if ($identifier->isClass()) {
47+
$className = strtolower($identifier->getName());
48+
49+
if (!array_key_exists($className, $this->cachedSymbols['classes'])) {
50+
$this->cachedSymbols['classes'][$className] ??= $this->locator->locateIdentifier($reflector, $identifier);
51+
$this->storeOnShutdown();
52+
}
53+
return $this->cachedSymbols['classes'][$className];
54+
}
55+
if ($identifier->isFunction()) {
56+
$className = strtolower($identifier->getName());
57+
58+
if (!array_key_exists($className, $this->cachedSymbols['functions'])) {
59+
$this->cachedSymbols['functions'][$className] ??= $this->locator->locateIdentifier($reflector, $identifier);
60+
$this->storeOnShutdown();
61+
}
62+
return $this->cachedSymbols['functions'][$className];
63+
}
64+
if ($identifier->isConstant()) {
65+
$constantName = ConstantNameHelper::normalize($identifier->getName());
7466

75-
$this->cached['identifier'] ??= [];
76-
if (!array_key_exists($key, $this->cached['identifier'])) {
77-
$this->cached['identifier'][$key] = $this->locator->locateIdentifier($reflector, $identifier);
78-
$this->storeCache();
67+
if (!array_key_exists($constantName, $this->cachedSymbols['constants'])) {
68+
$this->cachedSymbols['constants'][$constantName] ??= $this->locator->locateIdentifier($reflector, $identifier);
69+
$this->storeOnShutdown();
70+
}
71+
return $this->cachedSymbols['constants'][$constantName];
7972
}
8073

81-
return $this->cached['identifier'][$key];
74+
return null;
8275
}
8376

8477
public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
8578
{
86-
$key = $identifierType->getName();
79+
return $this->locator->locateIdentifiersByType($reflector, $identifierType);
80+
}
81+
82+
private function getVariableCacheKey(): string
83+
{
84+
return sprintf('v2-%s-%s', ComposerHelper::getBetterReflectionVersion(), $this->phpVersion->getVersionString());
85+
}
8786

88-
$this->cached['identifiersByType'] ??= [];
89-
if (!array_key_exists($key, $this->cached['identifiersByType'])) {
90-
$this->cached['identifiersByType'][$key] = $this->locator->locateIdentifiersByType($reflector, $identifierType);
91-
$this->storeCache();
87+
private function storeOnShutdown(): void
88+
{
89+
if ($this->storeOnShutdown) {
90+
return;
9291
}
9392

94-
return $this->cached['identifiersByType'][$key];
93+
$this->storeOnShutdown = true;
94+
register_shutdown_function([$this, 'storeCache']);
9595
}
9696

97-
private function getVariableCacheKey(): string
97+
/** @return array{classes: array<string, ReflectionClass>, functions: array<string, ReflectionFunction>, constants: array<string, ReflectionConstant>} */
98+
private function loadCache(Reflector $reflector): array
9899
{
99-
return sprintf('v1-%s-%s', ComposerHelper::getBetterReflectionVersion(), $this->phpVersion->getVersionString());
100+
$variableCacheKey = $this->getVariableCacheKey();
101+
$cached = $this->cache->load($this->cacheKey, $variableCacheKey);
102+
103+
$restored = [
104+
'classes' => [],
105+
'functions' => [],
106+
'constants' => [],
107+
];
108+
if ($cached === null) {
109+
return $restored;
110+
}
111+
112+
foreach ($cached['classes'] ?? [] as $class => $cachedReflection) {
113+
if ($cachedReflection === null) {
114+
$restored['classes'][$class] = null;
115+
continue;
116+
}
117+
118+
if (array_key_exists('backingType', $cachedReflection)) {
119+
$restored['classes'][$class] = ReflectionEnum::importFromCache($reflector, $cachedReflection);
120+
continue;
121+
}
122+
123+
$restored['classes'][$class] = ReflectionClass::importFromCache($reflector, $cachedReflection);
124+
}
125+
foreach ($cached['functions'] ?? [] as $class => $cachedReflection) {
126+
if ($cachedReflection === null) {
127+
$restored['functions'][$class] = null;
128+
continue;
129+
}
130+
$restored['functions'][$class] = ReflectionFunction::importFromCache($reflector, $cachedReflection);
131+
}
132+
foreach ($cached['constants'] ?? [] as $constantName => $cachedReflection) {
133+
if ($cachedReflection === null) {
134+
$restored['constants'][$constantName] = null;
135+
continue;
136+
}
137+
138+
$restored['constants'][$constantName] = ReflectionConstant::importFromCache($reflector, $cachedReflection);
139+
}
140+
return $restored;
100141
}
101142

102143
private function storeCache(): void
103144
{
104145
$variableCacheKey = $this->getVariableCacheKey();
105-
$this->cache->save($this->cacheKey, $variableCacheKey, $this->cached);
146+
147+
$exported = [
148+
'classes' => [],
149+
'functions' => [],
150+
'constants' => [],
151+
];
152+
foreach ($this->cachedSymbols ?? [] as $type => $data) {
153+
foreach ($data as $name => $reflection) {
154+
if ($reflection === null) {
155+
$exported[$type][$name] = $reflection;
156+
continue;
157+
}
158+
$exported[$type][$name] = $reflection->exportToCache();
159+
}
160+
}
161+
162+
$this->cache->save($this->cacheKey, $variableCacheKey, $exported);
106163
}
164+
107165
}

src/Reflection/BetterReflection/SourceLocator/PhpVersionBlacklistSourceLocator.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@
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;
1312

1413
final class PhpVersionBlacklistSourceLocator implements SourceLocator
1514
{
1615

1716
public function __construct(
1817
private SourceLocator $sourceLocator,
19-
private PhpStormStubsSourceStubber|CachedPhpStormStubsSourceStubber $phpStormStubsSourceStubber,
18+
private PhpStormStubsSourceStubber $phpStormStubsSourceStubber,
2019
)
2120
{
2221
}

src/Reflection/BetterReflection/SourceStubber/CachedPhpStormStubsSourceStubber.php

Lines changed: 0 additions & 101 deletions
This file was deleted.

0 commit comments

Comments
 (0)