1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\SourceLocator\Type\Composer;
6:
7: use PHPStan\BetterReflection\Identifier\Identifier;
8: use PHPStan\BetterReflection\Identifier\IdentifierType;
9: use PHPStan\BetterReflection\Reflection\Reflection;
10: use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
11: use PHPStan\BetterReflection\Reflector\Reflector;
12: use PHPStan\BetterReflection\SourceLocator\Ast\Locator;
13: use PHPStan\BetterReflection\SourceLocator\Exception\InvalidFileLocation;
14: use PHPStan\BetterReflection\SourceLocator\FileChecker;
15: use PHPStan\BetterReflection\SourceLocator\Located\LocatedSource;
16: use PHPStan\BetterReflection\SourceLocator\Type\Composer\Psr\PsrAutoloaderMapping;
17: use PHPStan\BetterReflection\SourceLocator\Type\DirectoriesSourceLocator;
18: use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
19:
20: use function assert;
21: use function file_get_contents;
22:
23: final class PsrAutoloaderLocator implements SourceLocator
24: {
25: private PsrAutoloaderMapping $mapping;
26: private Locator $astLocator;
27: public function __construct(PsrAutoloaderMapping $mapping, Locator $astLocator)
28: {
29: $this->mapping = $mapping;
30: $this->astLocator = $astLocator;
31: }
32:
33: public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?\PHPStan\BetterReflection\Reflection\Reflection
34: {
35: /** @phpstan-var non-empty-string $file */
36: foreach ($this->mapping->resolvePossibleFilePaths($identifier) as $file) {
37: try {
38: FileChecker::assertReadableFile($file);
39: $fileContents = file_get_contents($file);
40: assert($fileContents !== false);
41:
42: return $this->astLocator->findReflection(
43: $reflector,
44: new LocatedSource(
45: $fileContents,
46: $identifier->getName(),
47: $file,
48: ),
49: $identifier,
50: );
51: } catch (InvalidFileLocation $exception) {
52: // Ignore
53: } catch (IdentifierNotFound $exception) {
54: // on purpose - autoloading is allowed to fail, and silently-failing autoloaders are normal/endorsed
55: }
56: }
57:
58: return null;
59: }
60:
61: /**
62: * Find all identifiers of a type
63: *
64: * @return list<Reflection>
65: */
66: public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
67: {
68: return (new DirectoriesSourceLocator(
69: $this->mapping->directories(),
70: $this->astLocator,
71: ))->locateIdentifiersByType($reflector, $identifierType);
72: }
73: }
74: