Skip to content

Commit

Permalink
feat: support imported array shapes (@phpstan-import-type)
Browse files Browse the repository at this point in the history
  • Loading branch information
simPod committed Jul 19, 2024
1 parent 13292e1 commit 0190dfc
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/Metadata/Driver/DocBlockDriver/DocBlockTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasImportTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayTypeNode;
Expand Down Expand Up @@ -266,7 +267,7 @@ private function expandClassNameUsingUseStatements(string $typeHint, \Reflection
}

if ($declaringClass->getDocComment()) {
$phpstanArrayType = $this->getPhpstanType($declaringClass, $typeHint, $reflector);
$phpstanArrayType = $this->getPhpstanArrayType($declaringClass, $typeHint, $reflector);

if ($phpstanArrayType) {
return $phpstanArrayType;
Expand Down Expand Up @@ -402,7 +403,7 @@ private function resolveTypeFromDocblock($reflector): array
/**
* @param \ReflectionMethod|\ReflectionProperty $reflector
*/
private function getPhpstanType(\ReflectionClass $declaringClass, string $typeHint, $reflector): ?string
private function getPhpstanArrayType(\ReflectionClass $declaringClass, string $typeHint, $reflector): ?string
{
$tokens = $this->lexer->tokenize($declaringClass->getDocComment());
$phpDocNode = $this->phpDocParser->parse(new TokenIterator($tokens));
Expand All @@ -425,6 +426,14 @@ private function getPhpstanType(\ReflectionClass $declaringClass, string $typeHi
array_map(static fn (string $type) => $self->resolveType(trim($type), $reflector), $types),
));
}
} elseif ($node instanceof PhpDocTagNode && $node->value instanceof TypeAliasImportTagValueNode) {
$importedFromFqn = $this->resolveType($node->value->importedFrom->name, $reflector);

return $this->getPhpstanArrayType(
new \ReflectionClass($importedFromFqn),
$node->value->importedAlias,
$reflector,
);
}
}

Expand Down
24 changes: 24 additions & 0 deletions tests/Fixtures/DocBlockType/Phpstan/PhpstanArrayShapeImported.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan;

use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\Sub\PhpstanArrayShapeToImport;

/**
* @phpstan-import-type Settings from PhpstanArrayShapeToImport
* @phpstan-import-type Settings from PhpstanArrayShapeToImport as AliasedSettings
*/
final class PhpstanArrayShapeImported
{
/**
* @var Settings
*/
public $data;

/**
* @var AliasedSettings
*/
public $dataAliased;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\Sub;

/**
* @phpstan-type Settings array{
* method: string,
* amount: array{type: string, value: string|null}
* }
*/
final class PhpstanArrayShapeToImport
{
/**
* @var Settings
*/
public $data;
}
16 changes: 16 additions & 0 deletions tests/Metadata/Driver/DocBlockDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
use JMS\Serializer\Tests\Fixtures\DocBlockType\Collection\Vehicle;
use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\PhpstanArrayCollectionShape;
use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\PhpstanArrayShape;
use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\PhpstanArrayShapeImported;
use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\PhpstanMultipleArrayShapes;
use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\PhpstanNestedArrayShape;
use JMS\Serializer\Tests\Fixtures\DocBlockType\Phpstan\ProductType;
Expand Down Expand Up @@ -349,6 +350,21 @@ public function testInferTypeForPhpstanArray()
);
}

public function testInferImportedTypeForPhpstanArray()
{
$m = $this->resolve(PhpstanArrayShapeImported::class);

self::assertEquals(
['name' => 'array', 'params' => []],
$m->propertyMetadata['data']->type,
);

self::assertEquals(
['name' => 'array', 'params' => []],
$m->propertyMetadata['dataAliased']->type,
);
}

public function testInferTypeForPhpstanNestedArrayShape()
{
$m = $this->resolve(PhpstanNestedArrayShape::class);
Expand Down

0 comments on commit 0190dfc

Please sign in to comment.