Skip to content

Commit

Permalink
Separate classes for new @param- tags
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Apr 24, 2024
1 parent f4d1d48 commit 6277fb4
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 244 deletions.
20 changes: 10 additions & 10 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -5660,6 +5660,7 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike|Node\Stmt\Property $n
$varTags = [];
if ($resolvedPhpDoc !== null) {
$templateTypeMap = $resolvedPhpDoc->getTemplateTypeMap();
$phpDocImmediatelyInvokedCallableParameters = $resolvedPhpDoc->getParamsImmediatelyInvokedCallable();
foreach ($resolvedPhpDoc->getParamTags() as $paramName => $paramTag) {
if (array_key_exists($paramName, $phpDocParameterTypes)) {
continue;
Expand All @@ -5668,20 +5669,19 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike|Node\Stmt\Property $n
if ($scope->isInClass()) {
$paramType = $this->transformStaticType($scope->getClassReflection(), $paramType);
}
$closureThisType = $paramTag->getClosureThisType();
if ($closureThisType !== null) {
if ($scope->isInClass()) {
$closureThisType = $this->transformStaticType($scope->getClassReflection(), $closureThisType);
}
$phpDocClosureThisTypeParameters[$paramName] = $closureThisType;
}
$phpDocParameterTypes[$paramName] = $paramType;
$immediatelyInvokedCallable = $paramTag->isImmediatelyInvokedCallable();
if ($immediatelyInvokedCallable->maybe()) {
}
foreach ($resolvedPhpDoc->getParamClosureThisTags() as $paramName => $paramClosureThisTag) {
if (array_key_exists($paramName, $phpDocClosureThisTypeParameters)) {
continue;
}
$phpDocImmediatelyInvokedCallableParameters[$paramName] = $immediatelyInvokedCallable->yes();
$paramClosureThisType = $paramClosureThisTag->getType();
if ($scope->isInClass()) {
$paramClosureThisType = $this->transformStaticType($scope->getClassReflection(), $paramClosureThisType);
}
$phpDocClosureThisTypeParameters[$paramName] = $paramClosureThisType;
}

foreach ($resolvedPhpDoc->getParamOutTags() as $paramName => $paramOutTag) {
$phpDocParameterOutTypes[$paramName] = $paramOutTag->getType();
}
Expand Down
107 changes: 39 additions & 68 deletions src/PhpDoc/PhpDocNodeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use PHPStan\PhpDoc\Tag\MethodTag;
use PHPStan\PhpDoc\Tag\MethodTagParameter;
use PHPStan\PhpDoc\Tag\MixinTag;
use PHPStan\PhpDoc\Tag\ParamClosureThisTag;
use PHPStan\PhpDoc\Tag\ParamOutTag;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\PhpDoc\Tag\PropertyTag;
Expand All @@ -30,14 +31,11 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use PHPStan\Reflection\PassedByReference;
use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper;
use PHPStan\TrinaryLogic;
use PHPStan\Type\CallableType;
use PHPStan\Type\Generic\TemplateTypeFactory;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeScope;
use PHPStan\Type\Generic\TemplateTypeVariance;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use function array_key_exists;
Expand Down Expand Up @@ -345,31 +343,6 @@ public function resolveTemplateTags(PhpDocNode $phpDocNode, NameScope $nameScope
public function resolveParamTags(PhpDocNode $phpDocNode, NameScope $nameScope): array
{
$resolved = [];
$immediatelyInvokedCallableParameters = [];
foreach (['@param-immediately-invoked-callable', '@phpstan-param-immediately-invoked-callable'] as $tagName) {
foreach ($phpDocNode->getParamImmediatelyInvokedCallableTagValues($tagName) as $tagValue) {
$parameterName = substr($tagValue->parameterName, 1);
$immediatelyInvokedCallableParameters[$parameterName] = TrinaryLogic::createYes();
}
}
foreach (['@param-later-invoked-callable', '@phpstan-param-later-invoked-callable'] as $tagName) {
foreach ($phpDocNode->getParamLaterInvokedCallableTagValues($tagName) as $tagValue) {
$parameterName = substr($tagValue->parameterName, 1);
$immediatelyInvokedCallableParameters[$parameterName] = TrinaryLogic::createNo();
}
}

$unusedImmediatelyInvokedCallableParameters = $immediatelyInvokedCallableParameters;

$closureThisTypes = [];
foreach (['@param-closure-this', '@phpstan-param-closure-this'] as $tagName) {
foreach ($phpDocNode->getParamClosureThisTagValues($tagName) as $tagValue) {
$parameterName = substr($tagValue->parameterName, 1);
$closureThisTypes[$parameterName] = TypeCombinator::intersect(new ObjectWithoutClassType(), $this->typeNodeResolver->resolve($tagValue->type, $nameScope));
}
}

$unusedClosureThisTypes = $closureThisTypes;

foreach (['@param', '@phan-param', '@psalm-param', '@phpstan-param'] as $tagName) {
foreach ($phpDocNode->getParamTagValues($tagName) as $tagValue) {
Expand All @@ -379,53 +352,13 @@ public function resolveParamTags(PhpDocNode $phpDocNode, NameScope $nameScope):
continue;
}

if (array_key_exists($parameterName, $immediatelyInvokedCallableParameters)) {
$immediatelyInvokedCallable = $immediatelyInvokedCallableParameters[$parameterName];
unset($unusedImmediatelyInvokedCallableParameters[$parameterName]);
} else {
$immediatelyInvokedCallable = TrinaryLogic::createMaybe();
}

if (array_key_exists($parameterName, $closureThisTypes)) {
$closureThisType = $closureThisTypes[$parameterName];
unset($unusedClosureThisTypes[$parameterName]);
} else {
$closureThisType = null;
}

$resolved[$parameterName] = new ParamTag(
$parameterType,
$tagValue->isVariadic,
$immediatelyInvokedCallable,
$closureThisType,
);
}
}

foreach ($unusedImmediatelyInvokedCallableParameters as $parameterName => $immediately) {
if (array_key_exists($parameterName, $closureThisTypes)) {
$closureThisType = $closureThisTypes[$parameterName];
unset($unusedClosureThisTypes[$parameterName]);
} else {
$closureThisType = null;
}
$resolved[$parameterName] = new ParamTag(
new CallableType(),
false,
$immediately,
$closureThisType,
);
}

foreach ($unusedClosureThisTypes as $parameterName => $closureThisType) {
$resolved[$parameterName] = new ParamTag(
new CallableType(),
false,
TrinaryLogic::createMaybe(),
$closureThisType,
);
}

return $resolved;
}

Expand Down Expand Up @@ -457,6 +390,44 @@ public function resolveParamOutTags(PhpDocNode $phpDocNode, NameScope $nameScope
return $resolved;
}

/**
* @return array<string, bool>
*/
public function resolveParamImmediatelyInvokedCallable(PhpDocNode $phpDocNode): array
{
$parameters = [];
foreach (['@param-immediately-invoked-callable', '@phpstan-param-immediately-invoked-callable'] as $tagName) {
foreach ($phpDocNode->getParamImmediatelyInvokedCallableTagValues($tagName) as $tagValue) {
$parameterName = substr($tagValue->parameterName, 1);
$parameters[$parameterName] = true;
}
}
foreach (['@param-later-invoked-callable', '@phpstan-param-later-invoked-callable'] as $tagName) {
foreach ($phpDocNode->getParamLaterInvokedCallableTagValues($tagName) as $tagValue) {
$parameterName = substr($tagValue->parameterName, 1);
$parameters[$parameterName] = false;
}
}

return $parameters;
}

/**
* @return array<string, ParamClosureThisTag>
*/
public function resolveParamClosureThisTags(PhpDocNode $phpDocNode, NameScope $nameScope): array
{
$closureThisTypes = [];
foreach (['@param-closure-this', '@phpstan-param-closure-this'] as $tagName) {
foreach ($phpDocNode->getParamClosureThisTagValues($tagName) as $tagValue) {
$parameterName = substr($tagValue->parameterName, 1);
$closureThisTypes[$parameterName] = new ParamClosureThisTag($this->typeNodeResolver->resolve($tagValue->type, $nameScope));
}
}

return $closureThisTypes;
}

public function resolveReturnTag(PhpDocNode $phpDocNode, NameScope $nameScope): ?ReturnTag
{
$resolved = null;
Expand Down

0 comments on commit 6277fb4

Please sign in to comment.