1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection\SourceLocator\Type;
6:
7: use InvalidArgumentException;
8: use ReflectionClass;
9: use PHPStan\BetterReflection\Identifier\Identifier;
10: use PHPStan\BetterReflection\SourceLocator\Ast\Locator;
11: use PHPStan\BetterReflection\SourceLocator\Exception\InvalidFileLocation;
12: use PHPStan\BetterReflection\SourceLocator\Located\EvaledLocatedSource;
13: use PHPStan\BetterReflection\SourceLocator\Located\LocatedSource;
14: use PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber;
15: use PHPStan\BetterReflection\Util\ClassExistenceChecker;
16:
17: use function is_file;
18:
19: final class EvaledCodeSourceLocator extends AbstractSourceLocator
20: {
21: /**
22: * @var \PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber
23: */
24: private $stubber;
25: public function __construct(Locator $astLocator, SourceStubber $stubber)
26: {
27: $this->stubber = $stubber;
28: parent::__construct($astLocator);
29: }
30:
31: /**
32: * {@inheritDoc}
33: *
34: * @throws InvalidArgumentException
35: * @throws InvalidFileLocation
36: */
37: protected function createLocatedSource(Identifier $identifier): ?\PHPStan\BetterReflection\SourceLocator\Located\LocatedSource
38: {
39: $classReflection = $this->getInternalReflectionClass($identifier);
40:
41: if ($classReflection === null) {
42: return null;
43: }
44:
45: $stubData = $this->stubber->generateClassStub($classReflection->getName());
46:
47: if ($stubData === null) {
48: return null;
49: }
50:
51: return new EvaledLocatedSource($stubData->getStub(), $classReflection->getName());
52: }
53:
54: private function getInternalReflectionClass(Identifier $identifier): ?\ReflectionClass
55: {
56: if (! $identifier->isClass()) {
57: return null;
58: }
59:
60: /** @psalm-var class-string|trait-string $name */
61: $name = $identifier->getName();
62:
63: if (! ClassExistenceChecker::exists($name, false)) {
64: return null; // not an available internal class
65: }
66:
67: $reflection = new ReflectionClass($name);
68: $sourceFile = $reflection->getFileName();
69:
70: return $sourceFile && is_file($sourceFile)
71: ? null : $reflection;
72: }
73: }
74: