Skip to content

Commit

Permalink
Plumbing for @phpstan-require-extends and `@phpstan-require-impleme…
Browse files Browse the repository at this point in the history
…nts`
  • Loading branch information
staabm authored and ondrejmirtes committed Jan 6, 2024
1 parent 9d3eba2 commit 53a61dc
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/PhpDoc/PhpDocNodeResolver.php
Expand Up @@ -14,6 +14,8 @@
use PHPStan\PhpDoc\Tag\ParamOutTag;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\PhpDoc\Tag\PropertyTag;
use PHPStan\PhpDoc\Tag\RequireExtendsTag;
use PHPStan\PhpDoc\Tag\RequireImplementsTag;
use PHPStan\PhpDoc\Tag\ReturnTag;
use PHPStan\PhpDoc\Tag\SelfOutTypeTag;
use PHPStan\PhpDoc\Tag\TemplateTag;
Expand All @@ -25,6 +27,8 @@
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNullNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\MixinTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\RequireExtendsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\RequireImplementsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
use PHPStan\Reflection\PassedByReference;
use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper;
Expand Down Expand Up @@ -409,6 +413,26 @@ public function resolveMixinTags(PhpDocNode $phpDocNode, NameScope $nameScope):
), $phpDocNode->getMixinTagValues());
}

/**
* @return array<RequireExtendsTag>
*/
public function resolveRequireExtendsTags(PhpDocNode $phpDocNode, NameScope $nameScope): array
{
return array_map(fn (RequireExtendsTagValueNode $requireExtendsTagValueNode): RequireExtendsTag => new RequireExtendsTag(
$this->typeNodeResolver->resolve($requireExtendsTagValueNode->type, $nameScope),
), $phpDocNode->getRequireExtendsTagValues());
}

/**
* @return array<RequireImplementsTag>
*/
public function resolveRequireImplementsTags(PhpDocNode $phpDocNode, NameScope $nameScope): array
{
return array_map(fn (RequireImplementsTagValueNode $requireImplementsTagValueNode): RequireImplementsTag => new RequireImplementsTag(
$this->typeNodeResolver->resolve($requireImplementsTagValueNode->type, $nameScope),
), $phpDocNode->getRequireImplementsTagValues());
}

/**
* @return array<string, TypeAliasTag>
*/
Expand Down
44 changes: 44 additions & 0 deletions src/PhpDoc/ResolvedPhpDocBlock.php
Expand Up @@ -12,6 +12,8 @@
use PHPStan\PhpDoc\Tag\ParamOutTag;
use PHPStan\PhpDoc\Tag\ParamTag;
use PHPStan\PhpDoc\Tag\PropertyTag;
use PHPStan\PhpDoc\Tag\RequireExtendsTag;
use PHPStan\PhpDoc\Tag\RequireImplementsTag;
use PHPStan\PhpDoc\Tag\ReturnTag;
use PHPStan\PhpDoc\Tag\SelfOutTypeTag;
use PHPStan\PhpDoc\Tag\TemplateTag;
Expand Down Expand Up @@ -94,6 +96,12 @@ class ResolvedPhpDocBlock
/** @var array<MixinTag>|false */
private array|false $mixinTags = false;

/** @var array<RequireExtendsTag>|false */
private array|false $requireExtendsTags = false;

/** @var array<RequireImplementsTag>|false */
private array|false $requireImplementsTags = false;

/** @var array<TypeAliasTag>|false */
private array|false $typeAliasTags = false;

Expand Down Expand Up @@ -181,6 +189,8 @@ public static function createEmpty(): self
$self->returnTag = null;
$self->throwsTag = null;
$self->mixinTags = [];
$self->requireExtendsTags = [];
$self->requireImplementsTags = [];
$self->typeAliasTags = [];
$self->typeAliasImportTags = [];
$self->assertTags = [];
Expand Down Expand Up @@ -241,6 +251,8 @@ public function merge(array $parents, array $parentPhpDocBlocks): self
$result->returnTag = self::mergeReturnTags($this->getReturnTag(), $classReflection, $parents, $parentPhpDocBlocks);
$result->throwsTag = self::mergeThrowsTags($this->getThrowsTag(), $parents);
$result->mixinTags = $this->getMixinTags();
$result->requireExtendsTags = $this->getRequireExtendsTags();
$result->requireImplementsTags = $this->getRequireImplementsTags();
$result->typeAliasTags = $this->getTypeAliasTags();
$result->typeAliasImportTags = $this->getTypeAliasImportTags();
$result->assertTags = self::mergeAssertTags($this->getAssertTags(), $parents, $parentPhpDocBlocks);
Expand Down Expand Up @@ -336,6 +348,8 @@ public function changeParameterNamesByMapping(array $parameterNameMapping): self
$self->returnTag = $returnTag;
$self->throwsTag = $this->throwsTag;
$self->mixinTags = $this->mixinTags;
$self->requireImplementsTags = $this->requireImplementsTags;
$self->requireExtendsTags = $this->requireExtendsTags;
$self->typeAliasTags = $this->typeAliasTags;
$self->typeAliasImportTags = $this->typeAliasImportTags;
$self->assertTags = $assertTags;
Expand Down Expand Up @@ -540,6 +554,36 @@ public function getMixinTags(): array
return $this->mixinTags;
}

/**
* @return array<RequireExtendsTag>
*/
public function getRequireExtendsTags(): array
{
if ($this->requireExtendsTags === false) {
$this->requireExtendsTags = $this->phpDocNodeResolver->resolveRequireExtendsTags(
$this->phpDocNode,
$this->getNameScope(),
);
}

return $this->requireExtendsTags;
}

/**
* @return array<RequireImplementsTag>
*/
public function getRequireImplementsTags(): array
{
if ($this->requireImplementsTags === false) {
$this->requireImplementsTags = $this->phpDocNodeResolver->resolveRequireImplementsTags(
$this->phpDocNode,
$this->getNameScope(),
);
}

return $this->requireImplementsTags;
}

/**
* @return array<TypeAliasTag>
*/
Expand Down
20 changes: 20 additions & 0 deletions src/PhpDoc/Tag/RequireExtendsTag.php
@@ -0,0 +1,20 @@
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

/** @api */
class RequireExtendsTag
{

public function __construct(private Type $type)
{
}

public function getType(): Type
{
return $this->type;
}

}
20 changes: 20 additions & 0 deletions src/PhpDoc/Tag/RequireImplementsTag.php
@@ -0,0 +1,20 @@
<?php declare(strict_types = 1);

namespace PHPStan\PhpDoc\Tag;

use PHPStan\Type\Type;

/** @api */
class RequireImplementsTag
{

public function __construct(private Type $type)
{
}

public function getType(): Type
{
return $this->type;
}

}
28 changes: 28 additions & 0 deletions src/Reflection/ClassReflection.php
Expand Up @@ -21,6 +21,8 @@
use PHPStan\PhpDoc\Tag\MethodTag;
use PHPStan\PhpDoc\Tag\MixinTag;
use PHPStan\PhpDoc\Tag\PropertyTag;
use PHPStan\PhpDoc\Tag\RequireExtendsTag;
use PHPStan\PhpDoc\Tag\RequireImplementsTag;
use PHPStan\PhpDoc\Tag\TemplateTag;
use PHPStan\PhpDoc\Tag\TypeAliasImportTag;
use PHPStan\PhpDoc\Tag\TypeAliasTag;
Expand Down Expand Up @@ -1594,6 +1596,32 @@ public function getMixinTags(): array
return $resolvedPhpDoc->getMixinTags();
}

/**
* @return array<RequireExtendsTag>
*/
public function getRequireExtendsTags(): array
{
$resolvedPhpDoc = $this->getResolvedPhpDoc();
if ($resolvedPhpDoc === null) {
return [];
}

return $resolvedPhpDoc->getRequireExtendsTags();
}

/**
* @return array<RequireImplementsTag>
*/
public function getRequireImplementsTags(): array
{
$resolvedPhpDoc = $this->getResolvedPhpDoc();
if ($resolvedPhpDoc === null) {
return [];
}

return $resolvedPhpDoc->getRequireImplementsTags();
}

/**
* @return array<PropertyTag>
*/
Expand Down

0 comments on commit 53a61dc

Please sign in to comment.