Skip to content
2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
<arg value="--encoding=utf-8"/>
<arg value="--tab-width=4"/>
<arg value="--cache=tmp/cache/phpcs"/>
<arg value="--ignore=tests/*/data,tests/*/traits,tests/notAutoloaded,src/Reflection/SignatureMap/functionMap.php"/>
<arg value="--ignore=tests/*/data,tests/*/traits,tests/notAutoloaded,tests/*/cache,src/Reflection/SignatureMap/functionMap.php"/>
<arg value="-sp"/>
<arg path="src"/>
<arg path="tests"/>
Expand Down
3 changes: 3 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ services:
-
class: PHPStan\PhpDocParser\Parser\PhpDocParser

-
class: PHPStan\PhpDoc\PhpDocInheritanceResolver

-
class: PHPStan\PhpDoc\PhpDocNodeResolver

Expand Down
15 changes: 15 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ parameters:
count: 1
path: src/PhpDoc/PhpDocBlock.php

-
message: "#^Return type \\(PHPStan\\\\PhpDoc\\\\Tag\\\\ParamTag\\) of method PHPStan\\\\PhpDoc\\\\Tag\\\\ParamTag\\:\\:withType\\(\\) should be covariant with return type \\(static\\(PHPStan\\\\PhpDoc\\\\Tag\\\\TypedTag\\)\\) of method PHPStan\\\\PhpDoc\\\\Tag\\\\TypedTag\\:\\:withType\\(\\)$#"
count: 1
path: src/PhpDoc/Tag/ParamTag.php

-
message: "#^Return type \\(PHPStan\\\\PhpDoc\\\\Tag\\\\ReturnTag\\) of method PHPStan\\\\PhpDoc\\\\Tag\\\\ReturnTag\\:\\:withType\\(\\) should be covariant with return type \\(static\\(PHPStan\\\\PhpDoc\\\\Tag\\\\TypedTag\\)\\) of method PHPStan\\\\PhpDoc\\\\Tag\\\\TypedTag\\:\\:withType\\(\\)$#"
count: 1
path: src/PhpDoc/Tag/ReturnTag.php

-
message: "#^Return type \\(PHPStan\\\\PhpDoc\\\\Tag\\\\VarTag\\) of method PHPStan\\\\PhpDoc\\\\Tag\\\\VarTag\\:\\:withType\\(\\) should be covariant with return type \\(static\\(PHPStan\\\\PhpDoc\\\\Tag\\\\TypedTag\\)\\) of method PHPStan\\\\PhpDoc\\\\Tag\\\\TypedTag\\:\\:withType\\(\\)$#"
count: 1
path: src/PhpDoc/Tag/VarTag.php

-
message: "#^Property PHPStan\\\\Reflection\\\\ClassReflection\\:\\:\\$reflection with generic class ReflectionClass does not specify its types\\: T$#"
count: 1
Expand Down
55 changes: 19 additions & 36 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
use PHPStan\Node\ReturnStatement;
use PHPStan\Node\UnreachableStatementNode;
use PHPStan\Parser\Parser;
use PHPStan\PhpDoc\PhpDocBlock;
use PHPStan\PhpDoc\PhpDocInheritanceResolver;
use PHPStan\PhpDoc\ResolvedPhpDocBlock;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\Reflection\ClassReflection;
Expand Down Expand Up @@ -110,6 +110,9 @@ class NodeScopeResolver
/** @var \PHPStan\Type\FileTypeMapper */
private $fileTypeMapper;

/** @var \PHPStan\PhpDoc\PhpDocInheritanceResolver */
private $phpDocInheritanceResolver;

/** @var \PHPStan\File\FileHelper */
private $fileHelper;

Expand Down Expand Up @@ -138,6 +141,7 @@ class NodeScopeResolver
* @param \PHPStan\Reflection\ReflectionProvider $reflectionProvider
* @param Parser $parser
* @param FileTypeMapper $fileTypeMapper
* @param PhpDocInheritanceResolver $phpDocInheritanceResolver
* @param FileHelper $fileHelper
* @param TypeSpecifier $typeSpecifier
* @param bool $polluteScopeWithLoopInitialAssignments
Expand All @@ -150,6 +154,7 @@ public function __construct(
ReflectionProvider $reflectionProvider,
Parser $parser,
FileTypeMapper $fileTypeMapper,
PhpDocInheritanceResolver $phpDocInheritanceResolver,
FileHelper $fileHelper,
TypeSpecifier $typeSpecifier,
bool $polluteScopeWithLoopInitialAssignments,
Expand All @@ -162,6 +167,7 @@ public function __construct(
$this->reflectionProvider = $reflectionProvider;
$this->parser = $parser;
$this->fileTypeMapper = $fileTypeMapper;
$this->phpDocInheritanceResolver = $phpDocInheritanceResolver;
$this->fileHelper = $fileHelper;
$this->typeSpecifier = $typeSpecifier;
$this->polluteScopeWithLoopInitialAssignments = $polluteScopeWithLoopInitialAssignments;
Expand Down Expand Up @@ -2540,7 +2546,6 @@ private function processNodesForTraitUse($node, ClassReflection $traitReflection
public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array
{
$templateTypeMap = TemplateTypeMap::createEmpty();
$phpDocBlockTemplateTypeMap = null;
$phpDocParameterTypes = [];
$phpDocReturnType = null;
$phpDocThrowType = null;
Expand All @@ -2555,8 +2560,9 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array
$file = $scope->getFile();
$class = $scope->isInClass() ? $scope->getClassReflection()->getName() : null;
$trait = $scope->isInTrait() ? $scope->getTraitReflection()->getName() : null;
$phpDocBlock = null;
$resolvedPhpDoc = null;
$functionName = null;

if ($functionLike instanceof Node\Stmt\ClassMethod) {
if (!$scope->isInClass()) {
throw new \PHPStan\ShouldNotHappenException();
Expand All @@ -2569,51 +2575,35 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array

return $param->var->name;
}, $functionLike->getParams());
$phpDocBlock = PhpDocBlock::resolvePhpDocBlockForMethod(
$resolvedPhpDoc = $this->phpDocInheritanceResolver->resolvePhpDocForMethod(
$docComment,
$file,
$scope->getClassReflection(),
$trait,
$functionLike->name->name,
$file,
null,
$positionalParameterNames,
$positionalParameterNames
);

if ($phpDocBlock !== null) {
$docComment = $phpDocBlock->getDocComment();
$file = $phpDocBlock->getFile();
$class = $phpDocBlock->getClassReflection()->getName();
$trait = $phpDocBlock->getTrait();
$phpDocBlockTemplateTypeMap = $phpDocBlock->getClassReflection()->getActiveTemplateTypeMap();
}
} elseif ($functionLike instanceof Node\Stmt\Function_) {
$functionName = trim($scope->getNamespace() . '\\' . $functionLike->name->name, '\\');
}

if ($docComment !== null) {
if ($docComment !== null && $resolvedPhpDoc === null) {
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
$file,
$class,
$trait,
$functionName,
$docComment
);
}

if ($resolvedPhpDoc !== null) {
$templateTypeMap = $resolvedPhpDoc->getTemplateTypeMap();
$phpDocParameterTypes = array_map(static function (ParamTag $tag) use ($phpDocBlockTemplateTypeMap): Type {
if ($phpDocBlockTemplateTypeMap !== null) {
return TemplateTypeHelper::resolveTemplateTypes(
$tag->getType(),
$phpDocBlockTemplateTypeMap
);
}
$phpDocParameterTypes = array_map(static function (ParamTag $tag): Type {
return $tag->getType();
}, $resolvedPhpDoc->getParamTags());
if ($phpDocBlock !== null) {
$phpDocParameterTypes = $phpDocBlock->transformArrayKeysWithParameterNameMapping($phpDocParameterTypes);
}
$nativeReturnType = $scope->getFunctionType($functionLike->getReturnType(), false, false);
$phpDocReturnType = $this->getPhpDocReturnType($phpDocBlock, $resolvedPhpDoc, $nativeReturnType);
$phpDocReturnType = $this->getPhpDocReturnType($resolvedPhpDoc, $nativeReturnType);
$phpDocThrowType = $resolvedPhpDoc->getThrowsTag() !== null ? $resolvedPhpDoc->getThrowsTag()->getType() : null;
$deprecatedDescription = $resolvedPhpDoc->getDeprecatedTag() !== null ? $resolvedPhpDoc->getDeprecatedTag()->getMessage() : null;
$isDeprecated = $resolvedPhpDoc->isDeprecated();
Expand All @@ -2624,7 +2614,7 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike $functionLike): array
return [$templateTypeMap, $phpDocParameterTypes, $phpDocReturnType, $phpDocThrowType, $deprecatedDescription, $isDeprecated, $isInternal, $isFinal];
}

private function getPhpDocReturnType(?PhpDocBlock $phpDocBlock, ResolvedPhpDocBlock $resolvedPhpDoc, Type $nativeReturnType): ?Type
private function getPhpDocReturnType(ResolvedPhpDocBlock $resolvedPhpDoc, Type $nativeReturnType): ?Type
{
$returnTag = $resolvedPhpDoc->getReturnTag();

Expand All @@ -2634,14 +2624,7 @@ private function getPhpDocReturnType(?PhpDocBlock $phpDocBlock, ResolvedPhpDocBl

$phpDocReturnType = $returnTag->getType();

if ($phpDocBlock !== null) {
$phpDocReturnType = TemplateTypeHelper::resolveTemplateTypes(
$phpDocReturnType,
$phpDocBlock->getClassReflection()->getActiveTemplateTypeMap()
);
}

if ($phpDocBlock === null || $phpDocBlock->isExplicit()) {
if ($returnTag->isExplicit()) {
return $phpDocReturnType;
}

Expand Down
Loading