5959use PHPStan \Node \ReturnStatement ;
6060use PHPStan \Node \UnreachableStatementNode ;
6161use PHPStan \Parser \Parser ;
62- use PHPStan \PhpDoc \PhpDocBlock ;
62+ use PHPStan \PhpDoc \PhpDocInheritanceResolver ;
6363use PHPStan \PhpDoc \ResolvedPhpDocBlock ;
6464use PHPStan \PhpDoc \Tag \ParamTag ;
6565use PHPStan \Reflection \ClassReflection ;
@@ -110,6 +110,9 @@ class NodeScopeResolver
110110/** @var \PHPStan\Type\FileTypeMapper */
111111private $ fileTypeMapper ;
112112
113+ /** @var \PHPStan\PhpDoc\PhpDocInheritanceResolver */
114+ private $ phpDocInheritanceResolver ;
115+
113116/** @var \PHPStan\File\FileHelper */
114117private $ fileHelper ;
115118
@@ -138,6 +141,7 @@ class NodeScopeResolver
138141 * @param \PHPStan\Reflection\ReflectionProvider $reflectionProvider
139142 * @param Parser $parser
140143 * @param FileTypeMapper $fileTypeMapper
144+ * @param PhpDocInheritanceResolver $phpDocInheritanceResolver
141145 * @param FileHelper $fileHelper
142146 * @param TypeSpecifier $typeSpecifier
143147 * @param bool $polluteScopeWithLoopInitialAssignments
@@ -150,6 +154,7 @@ public function __construct(
150154ReflectionProvider $ reflectionProvider ,
151155Parser $ parser ,
152156FileTypeMapper $ fileTypeMapper ,
157+ PhpDocInheritanceResolver $ phpDocInheritanceResolver ,
153158FileHelper $ fileHelper ,
154159TypeSpecifier $ typeSpecifier ,
155160bool $ polluteScopeWithLoopInitialAssignments ,
@@ -162,6 +167,7 @@ public function __construct(
162167$ this ->reflectionProvider = $ reflectionProvider ;
163168$ this ->parser = $ parser ;
164169$ this ->fileTypeMapper = $ fileTypeMapper ;
170+ $ this ->phpDocInheritanceResolver = $ phpDocInheritanceResolver ;
165171$ this ->fileHelper = $ fileHelper ;
166172$ this ->typeSpecifier = $ typeSpecifier ;
167173$ this ->polluteScopeWithLoopInitialAssignments = $ polluteScopeWithLoopInitialAssignments ;
@@ -2540,7 +2546,6 @@ private function processNodesForTraitUse($node, ClassReflection $traitReflection
25402546public function getPhpDocs (Scope $ scope , Node \FunctionLike $ functionLike ): array
25412547{
25422548$ templateTypeMap = TemplateTypeMap::createEmpty ();
2543- $ phpDocBlockTemplateTypeMap = null ;
25442549$ phpDocParameterTypes = [];
25452550$ phpDocReturnType = null ;
25462551$ phpDocThrowType = null ;
@@ -2555,8 +2560,9 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array
25552560$ file = $ scope ->getFile ();
25562561$ class = $ scope ->isInClass () ? $ scope ->getClassReflection ()->getName () : null ;
25572562$ trait = $ scope ->isInTrait () ? $ scope ->getTraitReflection ()->getName () : null ;
2558- $ phpDocBlock = null ;
2563+ $ resolvedPhpDoc = null ;
25592564$ functionName = null ;
2565+
25602566if ($ functionLike instanceof Node \Stmt \ClassMethod) {
25612567if (!$ scope ->isInClass ()) {
25622568throw new \PHPStan \ShouldNotHappenException ();
@@ -2569,51 +2575,35 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array
25692575
25702576return $ param ->var ->name ;
25712577}, $ functionLike ->getParams ());
2572- $ phpDocBlock = PhpDocBlock:: resolvePhpDocBlockForMethod (
2578+ $ resolvedPhpDoc = $ this -> phpDocInheritanceResolver -> resolvePhpDocForMethod (
25732579$ docComment ,
2580+ $ file ,
25742581$ scope ->getClassReflection (),
25752582$ trait ,
25762583$ functionLike ->name ->name ,
2577- $ file ,
2578- null ,
2579- $ positionalParameterNames ,
25802584$ positionalParameterNames
25812585);
2582-
2583- if ($ phpDocBlock !== null ) {
2584- $ docComment = $ phpDocBlock ->getDocComment ();
2585- $ file = $ phpDocBlock ->getFile ();
2586- $ class = $ phpDocBlock ->getClassReflection ()->getName ();
2587- $ trait = $ phpDocBlock ->getTrait ();
2588- $ phpDocBlockTemplateTypeMap = $ phpDocBlock ->getClassReflection ()->getActiveTemplateTypeMap ();
2589- }
25902586} elseif ($ functionLike instanceof Node \Stmt \Function_) {
25912587$ functionName = trim ($ scope ->getNamespace () . '\\' . $ functionLike ->name ->name , '\\' );
25922588}
25932589
2594- if ($ docComment !== null ) {
2590+ if ($ docComment !== null && $ resolvedPhpDoc === null ) {
25952591$ resolvedPhpDoc = $ this ->fileTypeMapper ->getResolvedPhpDoc (
25962592$ file ,
25972593$ class ,
25982594$ trait ,
25992595$ functionName ,
26002596$ docComment
26012597);
2598+ }
2599+
2600+ if ($ resolvedPhpDoc !== null ) {
26022601$ templateTypeMap = $ resolvedPhpDoc ->getTemplateTypeMap ();
2603- $ phpDocParameterTypes = array_map (static function (ParamTag $ tag ) use ($ phpDocBlockTemplateTypeMap ): Type {
2604- if ($ phpDocBlockTemplateTypeMap !== null ) {
2605- return TemplateTypeHelper::resolveTemplateTypes (
2606- $ tag ->getType (),
2607- $ phpDocBlockTemplateTypeMap
2608- );
2609- }
2602+ $ phpDocParameterTypes = array_map (static function (ParamTag $ tag ): Type {
26102603return $ tag ->getType ();
26112604}, $ resolvedPhpDoc ->getParamTags ());
2612- if ($ phpDocBlock !== null ) {
2613- $ phpDocParameterTypes = $ phpDocBlock ->transformArrayKeysWithParameterNameMapping ($ phpDocParameterTypes );
2614- }
26152605$ nativeReturnType = $ scope ->getFunctionType ($ functionLike ->getReturnType (), false , false );
2616- $ phpDocReturnType = $ this ->getPhpDocReturnType ($ phpDocBlock , $ resolvedPhpDoc , $ nativeReturnType );
2606+ $ phpDocReturnType = $ this ->getPhpDocReturnType ($ resolvedPhpDoc , $ nativeReturnType );
26172607$ phpDocThrowType = $ resolvedPhpDoc ->getThrowsTag () !== null ? $ resolvedPhpDoc ->getThrowsTag ()->getType () : null ;
26182608$ deprecatedDescription = $ resolvedPhpDoc ->getDeprecatedTag () !== null ? $ resolvedPhpDoc ->getDeprecatedTag ()->getMessage () : null ;
26192609$ isDeprecated = $ resolvedPhpDoc ->isDeprecated ();
@@ -2624,7 +2614,7 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array
26242614return [$ templateTypeMap , $ phpDocParameterTypes , $ phpDocReturnType , $ phpDocThrowType , $ deprecatedDescription , $ isDeprecated , $ isInternal , $ isFinal ];
26252615}
26262616
2627- private function getPhpDocReturnType (? PhpDocBlock $ phpDocBlock , ResolvedPhpDocBlock $ resolvedPhpDoc , Type $ nativeReturnType ): ?Type
2617+ private function getPhpDocReturnType (ResolvedPhpDocBlock $ resolvedPhpDoc , Type $ nativeReturnType ): ?Type
26282618{
26292619$ returnTag = $ resolvedPhpDoc ->getReturnTag ();
26302620
@@ -2634,14 +2624,7 @@ private function getPhpDocReturnType(?PhpDocBlock $phpDocBlock, ResolvedPhpDocBl
26342624
26352625$ phpDocReturnType = $ returnTag ->getType ();
26362626
2637- if ($ phpDocBlock !== null ) {
2638- $ phpDocReturnType = TemplateTypeHelper::resolveTemplateTypes (
2639- $ phpDocReturnType ,
2640- $ phpDocBlock ->getClassReflection ()->getActiveTemplateTypeMap ()
2641- );
2642- }
2643-
2644- if ($ phpDocBlock === null || $ phpDocBlock ->isExplicit ()) {
2627+ if ($ returnTag ->isExplicit ()) {
26452628return $ phpDocReturnType ;
26462629}
26472630
0 commit comments