1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace PHPStan\BetterReflection;
6:
7: use PhpParser\Parser;
8: use PhpParser\ParserFactory;
9: use PhpParser\PrettyPrinter\Standard;
10: use PHPStan\BetterReflection\Reflector\DefaultReflector;
11: use PHPStan\BetterReflection\Reflector\Reflector;
12: use PHPStan\BetterReflection\SourceLocator\Ast\Locator as AstLocator;
13: use PHPStan\BetterReflection\SourceLocator\SourceStubber\AggregateSourceStubber;
14: use PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
15: use PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber;
16: use PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber;
17: use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
18: use PHPStan\BetterReflection\SourceLocator\Type\AutoloadSourceLocator;
19: use PHPStan\BetterReflection\SourceLocator\Type\EvaledCodeSourceLocator;
20: use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
21: use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
22: use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
23: use PHPStan\BetterReflection\Util\FindReflectionOnLine;
24:
25: use const PHP_VERSION_ID;
26:
27: final class BetterReflection
28: {
29: /**
30: * @var int
31: */
32: public static $phpVersion = PHP_VERSION_ID;
33:
34: /**
35: * @var \PHPStan\BetterReflection\SourceLocator\Type\SourceLocator|null
36: */
37: private static $sharedSourceLocator = null;
38:
39: /**
40: * @var \PHPStan\BetterReflection\SourceLocator\Type\SourceLocator|null
41: */
42: private $sourceLocator = null;
43:
44: /**
45: * @var \PHPStan\BetterReflection\Reflector\Reflector|null
46: */
47: private static $sharedReflector = null;
48:
49: /**
50: * @var \PHPStan\BetterReflection\Reflector\Reflector|null
51: */
52: private $reflector = null;
53:
54: /**
55: * @var \PhpParser\Parser|null
56: */
57: private static $sharedPhpParser = null;
58:
59: /**
60: * @var \PhpParser\Parser|null
61: */
62: private $phpParser = null;
63:
64: /**
65: * @var AstLocator|null
66: */
67: private $astLocator = null;
68:
69: /**
70: * @var \PHPStan\BetterReflection\Util\FindReflectionOnLine|null
71: */
72: private $findReflectionOnLine = null;
73:
74: /**
75: * @var \PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber|null
76: */
77: private $sourceStubber = null;
78:
79: /**
80: * @var \PHPStan\BetterReflection\SourceLocator\SourceStubber\SourceStubber|null
81: */
82: private static $sharedSourceStubber = null;
83:
84: /**
85: * @var Standard|null
86: */
87: private static $sharedPrinter = null;
88:
89: /**
90: * @var Standard|null
91: */
92: private $printer = null;
93:
94: public static function populate(int $phpVersion, SourceLocator $sourceLocator, Reflector $classReflector, Parser $phpParser, SourceStubber $sourceStubber, Standard $printer): void
95: {
96: self::$phpVersion = $phpVersion;
97: self::$sharedSourceLocator = $sourceLocator;
98: self::$sharedReflector = $classReflector;
99: self::$sharedPhpParser = $phpParser;
100: self::$sharedSourceStubber = $sourceStubber;
101: self::$sharedPrinter = $printer;
102: }
103:
104: public function __construct()
105: {
106: $this->sourceLocator = self::$sharedSourceLocator;
107: $this->reflector = self::$sharedReflector;
108: $this->phpParser = self::$sharedPhpParser;
109: $this->sourceStubber = self::$sharedSourceStubber;
110: $this->printer = self::$sharedPrinter;
111: }
112:
113: public function sourceLocator(): SourceLocator
114: {
115: $astLocator = $this->astLocator();
116: $sourceStubber = $this->sourceStubber();
117:
118: return $this->sourceLocator
119: ?? $this->sourceLocator = new MemoizingSourceLocator(new AggregateSourceLocator([
120: new PhpInternalSourceLocator($astLocator, $sourceStubber),
121: new EvaledCodeSourceLocator($astLocator, $sourceStubber),
122: new AutoloadSourceLocator($astLocator, $this->phpParser()),
123: ]));
124: }
125:
126: public function reflector(): Reflector
127: {
128: return $this->reflector
129: ?? $this->reflector = new DefaultReflector($this->sourceLocator());
130: }
131:
132: public function phpParser(): Parser
133: {
134: return $this->phpParser
135: ?? $this->phpParser = (new ParserFactory())->createForNewestSupportedVersion();
136: }
137:
138: public function astLocator(): AstLocator
139: {
140: return $this->astLocator
141: ?? $this->astLocator = new AstLocator($this->phpParser());
142: }
143:
144: public function findReflectionsOnLine(): FindReflectionOnLine
145: {
146: return $this->findReflectionOnLine
147: ?? $this->findReflectionOnLine = new FindReflectionOnLine($this->sourceLocator(), $this->astLocator());
148: }
149:
150: public function sourceStubber(): SourceStubber
151: {
152: return $this->sourceStubber
153: ?? $this->sourceStubber = new AggregateSourceStubber(new PhpStormStubsSourceStubber($this->phpParser(), $this->printer(), self::$phpVersion), new ReflectionSourceStubber($this->printer()));
154: }
155:
156: public function printer(): Standard
157: {
158: return $this->printer ?? $this->printer = new Standard(['shortArraySyntax' => true]);
159: }
160: }
161: