1919use PHPStan \PhpDoc \PhpDocStringResolver ;
2020use PHPStan \PhpDoc \ResolvedPhpDocBlock ;
2121use PHPStan \PhpDoc \Tag \TemplateTag ;
22+ use PHPStan \PhpDoc \TypeNodeResolver ;
2223use PHPStan \PhpDocParser \Ast \PhpDoc \PhpDocNode ;
2324use PHPStan \PhpDocParser \Ast \PhpDoc \PhpDocTagNode ;
2425use PHPStan \PhpDocParser \Ast \PhpDoc \TemplateTagValueNode ;
26+ use PHPStan \PhpDocParser \Ast \Type \TypeNode ;
2527use PHPStan \Reflection \ReflectionProvider \ReflectionProviderProvider ;
2628use PHPStan \ShouldNotHappenException ;
2729use PHPStan \Type \Generic \GenericObjectType ;
@@ -76,6 +78,7 @@ public function __construct(
7678 private Parser $ phpParser ,
7779 private PhpDocStringResolver $ phpDocStringResolver ,
7880 private PhpDocNodeResolver $ phpDocNodeResolver ,
81+ private TypeNodeResolver $ typeNodeResolver ,
7982 private AnonymousClassNameHelper $ anonymousClassNameHelper ,
8083 private FileHelper $ fileHelper ,
8184 private Cache $ cache ,
@@ -217,6 +220,7 @@ public function getNameScope(
217220
218221 $ phpDocTemplateTypes = [];
219222 $ templateTags = [];
223+ $ typeAliases = [];
220224 $ reflectionProvider = $ this ->reflectionProviderProvider ->getReflectionProvider ();
221225 foreach (array_reverse ($ parents ) as $ parent ) {
222226 $ nameScope = new NameScope (
@@ -226,7 +230,21 @@ public function getNameScope(
226230 $ parent ->getFunctionName (),
227231 new TemplateTypeMap ($ phpDocTemplateTypes ),
228232 $ templateTags ,
229- $ parent ->getTypeAliasesMap (),
233+ $ typeAliases ,
234+ $ parent ->shouldBypassTypeAliases (),
235+ $ parent ->getConstUses (),
236+ $ parent ->getClassNameForTypeAlias (),
237+ );
238+ $ resolvedTypeAliases = $ this ->resolveTypeAliases ($ parent ->getTypeAliasesMap (), $ nameScope );
239+ $ typeAliases = array_merge ($ typeAliases , $ resolvedTypeAliases );
240+ $ nameScope = new NameScope (
241+ $ parent ->getNamespace (),
242+ $ parent ->getUses (),
243+ $ parent ->getClassName (),
244+ $ parent ->getFunctionName (),
245+ new TemplateTypeMap ($ phpDocTemplateTypes ),
246+ $ templateTags ,
247+ $ typeAliases ,
230248 $ parent ->shouldBypassTypeAliases (),
231249 $ parent ->getConstUses (),
232250 $ parent ->getClassNameForTypeAlias (),
@@ -307,7 +325,7 @@ public function getNameScope(
307325 $ intermediaryNameScope ->getFunctionName (),
308326 new TemplateTypeMap ($ phpDocTemplateTypes ),
309327 $ templateTags ,
310- $ intermediaryNameScope -> getTypeAliasesMap () ,
328+ $ typeAliases ,
311329 $ intermediaryNameScope ->shouldBypassTypeAliases (),
312330 $ intermediaryNameScope ->getConstUses (),
313331 $ intermediaryNameScope ->getClassNameForTypeAlias (),
@@ -317,14 +335,44 @@ public function getNameScope(
317335 }
318336 }
319337
338+ /**
339+ * @param array<string, TypeNode|array{string, string}> $typeAliasesMap
340+ * @return array<string, Type>
341+ */
342+ private function resolveTypeAliases (array $ typeAliasesMap , NameScope $ nameScope ): array
343+ {
344+ $ aliases = [];
345+ foreach ($ typeAliasesMap as $ localAliasName => $ alias ) {
346+ if (is_array ($ alias )) {
347+ [$ aliasName , $ importedFrom ] = $ alias ;
348+ $ importedFrom = $ nameScope ->resolveStringName ($ importedFrom );
349+ $ reflectionProvider = $ this ->reflectionProviderProvider ->getReflectionProvider ();
350+ if (!$ reflectionProvider ->hasClass ($ importedFrom )) {
351+ continue ;
352+ }
353+ $ importedFromClassReflection = $ reflectionProvider ->getClass ($ importedFrom );
354+ $ classTypeAliaseses = $ importedFromClassReflection ->getTypeAliases ();
355+ if (!array_key_exists ($ aliasName , $ classTypeAliaseses )) {
356+ continue ;
357+ }
358+
359+ $ aliases [$ localAliasName ] = $ classTypeAliaseses [$ aliasName ]->resolve ($ this ->typeNodeResolver );
360+ continue ;
361+ }
362+
363+ $ aliases [$ localAliasName ] = $ this ->typeNodeResolver ->resolve ($ alias , $ nameScope );
364+ }
365+ return $ aliases ;
366+ }
367+
320368 /**
321369 * @return array{array<string, IntermediaryNameScope>}
322370 */
323371 private function getNameScopeMap (string $ fileName ): array
324372 {
325373 if (!isset ($ this ->memoryCache [$ fileName ])) {
326374 $ cacheKey = sprintf ('ftm-%s ' , $ fileName );
327- $ variableCacheKey = 'v2 ' ;
375+ $ variableCacheKey = 'v3 ' ;
328376 $ cached = $ this ->loadCachedPhpDocNodeMap ($ cacheKey , $ variableCacheKey );
329377 if ($ cached === null ) {
330378 [$ nameScopeMap , $ files ] = $ this ->createPhpDocNodeMap ($ fileName , null , null , [], $ fileName );
@@ -399,7 +447,7 @@ private function createPhpDocNodeMap(string $fileName, ?string $lookForTrait, ?s
399447 /** @var array<int, IntermediaryNameScope> $typeMapStack */
400448 $ typeMapStack = [];
401449
402- /** @var array<int, array<string, true >> $typeAliasStack */
450+ /** @var array<int, array<string, TypeNode|array{string, string} >> $typeAliasStack */
403451 $ typeAliasStack = [];
404452
405453 /** @var string[] $classStack */
@@ -735,19 +783,19 @@ private function chooseTemplateTagValueNodesByPriority(array $tags): array
735783 }
736784
737785 /**
738- * @return array<string, true >
786+ * @return array<string, TypeNode|array{string, string} >
739787 */
740788 private function getTypeAliasesMap (PhpDocNode $ phpDocNode ): array
741789 {
742790 $ nameScope = new NameScope (null , []);
743791
744792 $ aliasesMap = [];
745- foreach (array_keys ( $ this ->phpDocNodeResolver ->resolveTypeAliasImportTags ($ phpDocNode , $ nameScope )) as $ key ) {
746- $ aliasesMap [$ key ] = true ;
793+ foreach ($ this ->phpDocNodeResolver ->resolveTypeAliasImportTags ($ phpDocNode , $ nameScope ) as $ key => $ typeAliasImportTag ) {
794+ $ aliasesMap [$ key ] = [ $ typeAliasImportTag -> getImportedAlias (), $ typeAliasImportTag -> getImportedFrom ()] ;
747795 }
748796
749- foreach (array_keys ( $ this ->phpDocNodeResolver ->resolveTypeAliasTags ($ phpDocNode , $ nameScope )) as $ key ) {
750- $ aliasesMap [$ key ] = true ;
797+ foreach ($ this ->phpDocNodeResolver ->resolveTypeAliasTags ($ phpDocNode , $ nameScope ) as $ key => $ typeAlias ) {
798+ $ aliasesMap [$ key ] = $ typeAlias -> getTypeNode () ;
751799 }
752800
753801 return $ aliasesMap ;
0 commit comments