2020use Roave \BetterReflection \SourceLocator \Ast \Strategy \NodeToReflection ;
2121use Roave \BetterReflection \SourceLocator \Located \LocatedSource ;
2222use Roave \BetterReflection \SourceLocator \Type \SourceLocator ;
23+ use function array_key_exists ;
2324use function file_exists ;
2425use function restore_error_handler ;
2526
@@ -40,6 +41,18 @@ class AutoloadSourceLocator implements SourceLocator
4041
4142 private static ?FileNodesFetcher $ currentFileNodesFetcher = null ;
4243
44+ /** @var array<string, FetchedNode<\PhpParser\Node\Stmt\ClassLike>> */
45+ private array $ classNodes = [];
46+
47+ /** @var array<string, FetchedNode<\PhpParser\Node\Stmt\Function_>> */
48+ private array $ functionNodes = [];
49+
50+ /** @var array<int, FetchedNode<\PhpParser\Node\Stmt\Const_|\PhpParser\Node\Expr\FuncCall>> */
51+ private array $ constantNodes = [];
52+
53+ /** @var array<string, \Roave\BetterReflection\SourceLocator\Located\LocatedSource> */
54+ private array $ locatedSourcesByFile = [];
55+
4356 /**
4457 * Note: the constructor has been made a 0-argument constructor because `\stream_wrapper_register`
4558 * is a piece of trash, and doesn't accept instances, just class names.
@@ -63,6 +76,16 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier):
6376 {
6477 if ($ identifier ->isFunction ()) {
6578 $ functionName = $ identifier ->getName ();
79+ $ loweredFunctionName = strtolower ($ functionName );
80+ if (array_key_exists ($ loweredFunctionName , $ this ->functionNodes )) {
81+ $ nodeToReflection = new NodeToReflection ();
82+ return $ nodeToReflection ->__invoke (
83+ $ reflector ,
84+ $ this ->functionNodes [$ loweredFunctionName ]->getNode (),
85+ $ this ->locatedSourcesByFile [$ this ->functionNodes [$ loweredFunctionName ]->getFileName ()],
86+ $ this ->functionNodes [$ loweredFunctionName ]->getNamespace ()
87+ );
88+ }
6689 if (!function_exists ($ functionName )) {
6790 return null ;
6891 }
@@ -79,6 +102,51 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier):
79102
80103 if ($ identifier ->isConstant ()) {
81104 $ constantName = $ identifier ->getName ();
105+ $ nodeToReflection = new NodeToReflection ();
106+ foreach ($ this ->constantNodes as $ stmtConst ) {
107+ if ($ stmtConst ->getNode () instanceof FuncCall) {
108+ $ constantReflection = $ nodeToReflection ->__invoke (
109+ $ reflector ,
110+ $ stmtConst ->getNode (),
111+ $ this ->locatedSourcesByFile [$ stmtConst ->getFileName ()],
112+ $ stmtConst ->getNamespace ()
113+ );
114+ if ($ constantReflection === null ) {
115+ continue ;
116+ }
117+ if (!$ constantReflection instanceof ReflectionConstant) {
118+ throw new \PHPStan \ShouldNotHappenException ();
119+ }
120+ if ($ constantReflection ->getName () !== $ identifier ->getName ()) {
121+ continue ;
122+ }
123+
124+ return $ constantReflection ;
125+ }
126+
127+ foreach (array_keys ($ stmtConst ->getNode ()->consts ) as $ i ) {
128+ $ constantReflection = $ nodeToReflection ->__invoke (
129+ $ reflector ,
130+ $ stmtConst ->getNode (),
131+ $ this ->locatedSourcesByFile [$ stmtConst ->getFileName ()],
132+ $ stmtConst ->getNamespace (),
133+ $ i
134+ );
135+ if ($ constantReflection === null ) {
136+ continue ;
137+ }
138+ if (!$ constantReflection instanceof ReflectionConstant) {
139+ throw new \PHPStan \ShouldNotHappenException ();
140+ }
141+ if ($ constantReflection ->getName () !== $ identifier ->getName ()) {
142+ continue ;
143+ }
144+
145+ return $ constantReflection ;
146+ }
147+ }
148+
149+
82150 if (!defined ($ constantName )) {
83151 return null ;
84152 }
@@ -102,6 +170,17 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier):
102170 return null ;
103171 }
104172
173+ $ loweredClassName = strtolower ($ identifier ->getName ());
174+ if (array_key_exists ($ loweredClassName , $ this ->classNodes )) {
175+ $ nodeToReflection = new NodeToReflection ();
176+ return $ nodeToReflection ->__invoke (
177+ $ reflector ,
178+ $ this ->classNodes [$ loweredClassName ]->getNode (),
179+ $ this ->locatedSourcesByFile [$ this ->classNodes [$ loweredClassName ]->getFileName ()],
180+ $ this ->classNodes [$ loweredClassName ]->getNamespace ()
181+ );
182+ }
183+
105184 $ locateResult = $ this ->locateClassByName ($ identifier ->getName ());
106185 if ($ locateResult === null ) {
107186 return null ;
@@ -114,36 +193,43 @@ public function locateIdentifier(Reflector $reflector, Identifier $identifier):
114193 private function findReflection (Reflector $ reflector , string $ file , Identifier $ identifier ): ?Reflection
115194 {
116195 $ result = $ this ->fileNodesFetcher ->fetchNodes ($ file );
196+ $ this ->locatedSourcesByFile [$ file ] = $ result ->getLocatedSource ();
197+ foreach ($ result ->getClassNodes () as $ className => $ fetchedClassNode ) {
198+ $ this ->classNodes [$ className ] = $ fetchedClassNode ;
199+ }
200+ foreach ($ result ->getFunctionNodes () as $ functionName => $ fetchedFunctionNode ) {
201+ $ this ->functionNodes [$ functionName ] = $ fetchedFunctionNode ;
202+ }
203+ foreach ($ result ->getConstantNodes () as $ fetchedConstantNode ) {
204+ $ this ->constantNodes [] = $ fetchedConstantNode ;
205+ }
206+
117207 $ nodeToReflection = new NodeToReflection ();
118208 if ($ identifier ->isClass ()) {
119- foreach ($ result ->getClassNodes () as $ fetchedFunctionNode ) {
120- $ reflection = $ nodeToReflection ->__invoke (
121- $ reflector ,
122- $ fetchedFunctionNode ->getNode (),
123- $ result ->getLocatedSource (),
124- $ fetchedFunctionNode ->getNamespace ()
125- );
126- if ($ reflection === null ) {
127- continue ;
128- }
129-
130- return $ reflection ;
209+ $ identifierName = strtolower ($ identifier ->getName ());
210+ if (!array_key_exists ($ identifierName , $ this ->classNodes )) {
211+ return null ;
131212 }
213+
214+ return $ nodeToReflection ->__invoke (
215+ $ reflector ,
216+ $ this ->classNodes [$ identifierName ]->getNode (),
217+ $ result ->getLocatedSource (),
218+ $ this ->classNodes [$ identifierName ]->getNamespace ()
219+ );
132220 }
133221 if ($ identifier ->isFunction ()) {
134- foreach ($ result ->getFunctionNodes () as $ fetchedFunctionNode ) {
135- $ reflection = $ nodeToReflection ->__invoke (
136- $ reflector ,
137- $ fetchedFunctionNode ->getNode (),
138- $ result ->getLocatedSource (),
139- $ fetchedFunctionNode ->getNamespace ()
140- );
141- if ($ reflection === null ) {
142- continue ;
143- }
144-
145- return $ reflection ;
222+ $ identifierName = strtolower ($ identifier ->getName ());
223+ if (!array_key_exists ($ identifierName , $ this ->functionNodes )) {
224+ return null ;
146225 }
226+
227+ return $ nodeToReflection ->__invoke (
228+ $ reflector ,
229+ $ this ->functionNodes [$ identifierName ]->getNode (),
230+ $ result ->getLocatedSource (),
231+ $ this ->functionNodes [$ identifierName ]->getNamespace ()
232+ );
147233 }
148234
149235 return null ;
0 commit comments