Skip to content

Commit 7688036

Browse files
tomasfejfarondrejmirtes
authored andcommitted
locateIdentifiersByType returns all located classes or functions
1 parent 0a96fca commit 7688036

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

src/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocator.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,57 @@ private function findSymbols(string $file): array
246246
];
247247
}
248248

249+
/**
250+
* @return array<int, Reflection>
251+
*/
249252
public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
250253
{
251-
return [];
254+
if ($this->classToFile === null || $this->functionToFiles === null) {
255+
$this->init();
256+
if ($this->classToFile === null || $this->functionToFiles === null) {
257+
throw new ShouldNotHappenException();
258+
}
259+
}
260+
261+
$reflections = [];
262+
if ($identifierType->isClass()) {
263+
foreach ($this->classToFile as $className => $file) {
264+
if (array_key_exists($className, $this->classNodes)) {
265+
$reflections[$className] = $this->nodeToReflection($reflector, $this->classNodes[$className]);
266+
continue;
267+
}
268+
269+
$fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file);
270+
foreach ($fetchedNodesResult->getClassNodes() as $identifierName => $fetchedClassNodes) {
271+
foreach ($fetchedClassNodes as $fetchedClassNode) {
272+
$this->classNodes[$identifierName] = $fetchedClassNode;
273+
$reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedClassNode);
274+
continue;
275+
}
276+
}
277+
}
278+
} elseif ($identifierType->isFunction()) {
279+
foreach ($this->functionToFiles as $functionName => $files) {
280+
foreach ($files as $file) {
281+
if (array_key_exists($functionName, $this->functionNodes)) {
282+
$reflections[$functionName] = $this->nodeToReflection(
283+
$reflector,
284+
$this->functionNodes[$functionName]
285+
);
286+
continue;
287+
}
288+
289+
$fetchedNodesResult = $this->fileNodesFetcher->fetchNodes($file);
290+
foreach ($fetchedNodesResult->getFunctionNodes() as $identifierName => $fetchedFunctionNode) {
291+
$this->functionNodes[$identifierName] = $fetchedFunctionNode;
292+
$reflections[$identifierName] = $this->nodeToReflection($reflector, $fetchedFunctionNode);
293+
continue;
294+
}
295+
}
296+
}
297+
}
298+
299+
return array_values($reflections);
252300
}
253301

254302
}

tests/PHPStan/Reflection/BetterReflection/SourceLocator/OptimizedDirectorySourceLocatorTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
namespace PHPStan\Reflection\BetterReflection\SourceLocator;
44

55
use OptimizedDirectory\BFoo;
6+
use PHPStan\BetterReflection\Identifier\IdentifierType;
7+
use PHPStan\BetterReflection\Reflection\Reflection;
68
use PHPStan\BetterReflection\Reflector\DefaultReflector;
79
use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
810
use PHPStan\Testing\PHPStanTestCase;
911
use TestDirectorySourceLocator\AFoo;
12+
use function array_map;
1013
use function basename;
1114
use const PHP_VERSION_ID;
1215

@@ -135,6 +138,49 @@ public function testFunctionExists(string $functionName, string $expectedFunctio
135138
$this->assertSame($file, basename($functionReflection->getFileName()));
136139
}
137140

141+
public function testLocateIdentifiersByType(): void
142+
{
143+
/** @var OptimizedDirectorySourceLocatorFactory $factory */
144+
$factory = self::getContainer()->getByType(OptimizedDirectorySourceLocatorFactory::class);
145+
$locator = $factory->createByDirectory(__DIR__ . '/data/directory');
146+
$reflector = new DefaultReflector($locator);
147+
148+
$classIdentifiers = $locator->locateIdentifiersByType(
149+
$reflector,
150+
new IdentifierType(IdentifierType::IDENTIFIER_CLASS),
151+
);
152+
153+
$expectedClasses = [
154+
'TestDirectorySourceLocator\AFoo',
155+
'OptimizedDirectory\BFoo',
156+
'CFoo',
157+
];
158+
if (PHP_VERSION_ID >= 80100) {
159+
$expectedClasses[] = 'OptimizedDirectory\TestEnum';
160+
$expectedClasses[] = 'OptimizedDirectory\BackedByStringWithoutSpace';
161+
$expectedClasses[] = 'OptimizedDirectory\UppercaseEnum';
162+
}
163+
164+
$actualClasses = array_map(static fn (Reflection $reflection) => $reflection->getName(), $classIdentifiers);
165+
$this->assertEqualsCanonicalizing($expectedClasses, $actualClasses);
166+
167+
$functionIdentifiers = $locator->locateIdentifiersByType(
168+
$reflector,
169+
new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION),
170+
);
171+
172+
$actualFunctions = array_map(static fn (Reflection $reflection) => $reflection->getName(), $functionIdentifiers);
173+
174+
$this->assertEqualsCanonicalizing([
175+
'TestDirectorySourceLocator\doLorem',
176+
'OptimizedDirectory\doBar',
177+
'OptimizedDirectory\doBaz',
178+
'OptimizedDirectory\get_smarty',
179+
'OptimizedDirectory\get_smarty2',
180+
'OptimizedDirectory\upperCaseFunction',
181+
], $actualFunctions);
182+
}
183+
138184
public function dataFunctionDoesNotExist(): array
139185
{
140186
return [

0 commit comments

Comments
 (0)