Skip to content

Commit acf13e2

Browse files
committed
rework
1 parent 08f3a7e commit acf13e2

File tree

4 files changed

+124
-166
lines changed

4 files changed

+124
-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: 118 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,105 +3,165 @@
33
namespace PHPStan\Reflection\BetterReflection\SourceLocator;
44

55
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_;
116
use PHPStan\BetterReflection\Identifier\Identifier;
127
use PHPStan\BetterReflection\Identifier\IdentifierType;
138
use PHPStan\BetterReflection\Reflection\Reflection;
9+
use PHPStan\BetterReflection\Reflection\ReflectionClass;
1410
use PHPStan\BetterReflection\Reflection\ReflectionConstant;
11+
use PHPStan\BetterReflection\Reflection\ReflectionEnum;
12+
use PHPStan\BetterReflection\Reflection\ReflectionFunction;
1513
use PHPStan\BetterReflection\Reflector\Reflector;
16-
use PHPStan\BetterReflection\SourceLocator\Ast\Strategy\NodeToReflection;
17-
use PHPStan\BetterReflection\SourceLocator\Located\LocatedSource;
1814
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
1915
use PHPStan\Cache\Cache;
2016
use PHPStan\Internal\ComposerHelper;
21-
use PHPStan\Node\Expr\TypeExpr;
2217
use PHPStan\Php\PhpVersion;
2318
use PHPStan\Reflection\ConstantNameHelper;
2419
use PHPStan\ShouldNotHappenException;
25-
use PHPStan\Type\ConstantTypeHelper;
26-
use ReflectionClass;
27-
use ReflectionFunction;
2820
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;
21+
use function sprintf;
4222
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-
*/
23+
5424
final class FileCachedSourceLocator implements SourceLocator
5525
{
56-
/** @var array<string, mixed> */
57-
private array $cached;
5826

27+
/** @var array{classes: array<string, ?Reflection>, functions: array<string, ?Reflection>, constants: array<string, ?Reflection>}|null */
28+
private ?array $cachedSymbols = null;
29+
30+
/**
31+
* @param non-empty-string $cacheKey
32+
*/
5933
public function __construct(
6034
private SourceLocator $locator,
6135
private Cache $cache,
6236
private PhpVersion $phpVersion,
6337
private string $cacheKey,
6438
)
6539
{
66-
$variableCacheKey = $this->getVariableCacheKey();
67-
$this->cached = $this->cache->load($this->cacheKey, $variableCacheKey) ?? [];
6840
}
6941

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

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();
68+
if (!array_key_exists($constantName, $this->cachedSymbols['constants'])) {
69+
$this->cachedSymbols['constants'][$constantName] = $this->locator->locateIdentifier($reflector, $identifier);
70+
$this->storeCache();
71+
}
72+
return $this->cachedSymbols['constants'][$constantName];
7973
}
8074

81-
return $this->cached['identifier'][$key];
75+
return null;
8276
}
8377

78+
#[Override]
8479
public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
8580
{
86-
$key = $identifierType->getName();
87-
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();
92-
}
93-
94-
return $this->cached['identifiersByType'][$key];
81+
return $this->locator->locateIdentifiersByType($reflector, $identifierType);
9582
}
9683

84+
/** @return non-empty-string */
9785
private function getVariableCacheKey(): string
9886
{
99-
return sprintf('v1-%s-%s', ComposerHelper::getBetterReflectionVersion(), $this->phpVersion->getVersionString());
87+
return sprintf('v2-%s-%s', ComposerHelper::getBetterReflectionVersion(), $this->phpVersion->getVersionString());
88+
}
89+
90+
/** @return array{classes: array<string, ReflectionClass|null>, functions: array<string, ReflectionFunction|null>, constants: array<string, ReflectionConstant|null>} */
91+
private function loadCache(Reflector $reflector): array
92+
{
93+
$variableCacheKey = $this->getVariableCacheKey();
94+
$cached = $this->cache->load($this->cacheKey, $variableCacheKey);
95+
96+
$restored = [
97+
'classes' => [],
98+
'functions' => [],
99+
'constants' => [],
100+
];
101+
if ($cached === null) {
102+
return $restored;
103+
}
104+
105+
foreach ($cached['classes'] ?? [] as $class => $cachedReflection) {
106+
if ($cachedReflection === null) {
107+
$restored['classes'][$class] = null;
108+
continue;
109+
}
110+
111+
if (array_key_exists('backingType', $cachedReflection)) {
112+
$restored['classes'][$class] = ReflectionEnum::importFromCache($reflector, $cachedReflection);
113+
continue;
114+
}
115+
116+
$restored['classes'][$class] = ReflectionClass::importFromCache($reflector, $cachedReflection);
117+
}
118+
foreach ($cached['functions'] ?? [] as $class => $cachedReflection) {
119+
if ($cachedReflection === null) {
120+
$restored['functions'][$class] = null;
121+
continue;
122+
}
123+
$restored['functions'][$class] = ReflectionFunction::importFromCache($reflector, $cachedReflection);
124+
}
125+
foreach ($cached['constants'] ?? [] as $constantName => $cachedReflection) {
126+
if ($cachedReflection === null) {
127+
$restored['constants'][$constantName] = null;
128+
continue;
129+
}
130+
131+
$restored['constants'][$constantName] = ReflectionConstant::importFromCache($reflector, $cachedReflection);
132+
}
133+
return $restored;
100134
}
101135

102136
private function storeCache(): void
103137
{
104138
$variableCacheKey = $this->getVariableCacheKey();
105-
$this->cache->save($this->cacheKey, $variableCacheKey, $this->cached);
139+
140+
$exported = [
141+
'classes' => [],
142+
'functions' => [],
143+
'constants' => [],
144+
];
145+
foreach ($this->cachedSymbols ?? [] as $type => $data) {
146+
foreach ($data as $name => $reflection) {
147+
if ($reflection === null) {
148+
$exported[$type][$name] = $reflection;
149+
continue;
150+
}
151+
152+
if (
153+
!$reflection instanceof ReflectionClass
154+
&& !$reflection instanceof ReflectionFunction
155+
&& !$reflection instanceof ReflectionConstant
156+
) {
157+
throw new ShouldNotHappenException();
158+
}
159+
160+
$exported[$type][$name] = $reflection->exportToCache();
161+
}
162+
}
163+
164+
$this->cache->save($this->cacheKey, $variableCacheKey, $exported);
106165
}
166+
107167
}

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)