Skip to content

Commit

Permalink
add support for object shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
JanTvrdik committed Apr 7, 2023
1 parent 8a3621f commit 9435f6c
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/Analyzer/NodeVisitors/PhpDocResolver.php
Expand Up @@ -35,6 +35,7 @@
use PHPStan\PhpDocParser\Ast\PhpDoc\TypeAliasTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeItemNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\ObjectShapeItemNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
Expand Down Expand Up @@ -208,7 +209,7 @@ protected function resolvePhpDoc(PhpDocNode $phpDoc): void
} elseif ($value instanceof ConstExprNode) {
$value->setAttribute('info', $this->resolveConstExpr($value));

} elseif ($value instanceof ArrayShapeItemNode) {
} elseif ($value instanceof ArrayShapeItemNode || $value instanceof ObjectShapeItemNode) {
$stack[$index++] = $value->valueType; // intentionally not pushing $value->keyName

} else {
Expand Down
10 changes: 10 additions & 0 deletions src/Renderer/Latte/Template/blocks/type.latte
Expand Up @@ -42,6 +42,16 @@
{if !$type->sealed}{if $type->items}, {/if}...{/if}
}

{elseif $type instanceof PHPStan\PhpDocParser\Ast\Type\ObjectShapeNode}
object{
{foreach $type->items as $item}
{$item->keyName}
{if $item->optional}?{/if}{=": "}
{include this, type: $item->valueType, scope: $scope, brackets: true, short: $short}
{sep}, {/sep}
{/foreach}
}

{elseif $type instanceof PHPStan\PhpDocParser\Ast\Type\NullableTypeNode}
?{include this, type: $type->type, scope: $scope, brackets: true, short: $short}

Expand Down
118 changes: 118 additions & 0 deletions tests/Features/PhpDoc/Types/ObjectShapes.neon
@@ -0,0 +1,118 @@
[
@Interface(
file: '%rootDir%/tests/Features/PhpDoc/Types/ObjectShapes.php'
properties: {
a: @Property(
type: @ObjectShape(
items: [
@ObjectShapeItem(
keyName: @IdentifierType(
name: 'a'
)
optional: false
valueType: @IdentifierType(
name: 'int'
attributes: {
kind: 'Keyword'
}
)
),
]
)
name: 'a'
magic: true
public: true
)
b: @Property(
type: @ObjectShape(
items: [
@ObjectShapeItem(
keyName: @IdentifierType(
name: 'b'
)
optional: false
valueType: @NullableType(
type: @IdentifierType(
name: 'int'
attributes: {
kind: 'Keyword'
}
)
)
),
]
)
name: 'b'
magic: true
public: true
)
c: @Property(
type: @ObjectShape(
items: [
@ObjectShapeItem(
keyName: @IdentifierType(
name: 'c'
)
optional: true
valueType: @IdentifierType(
name: 'int'
attributes: {
kind: 'Keyword'
}
)
),
]
)
name: 'c'
magic: true
public: true
)
d: @Property(
type: @NullableType(
type: @ObjectShape(
items: [
@ObjectShapeItem(
keyName: @IdentifierType(
name: 'd'
)
optional: false
valueType: @IdentifierType(
name: 'int'
attributes: {
kind: 'Keyword'
}
)
),
]
)
)
name: 'd'
magic: true
public: true
)
e: @Property(
type: @ObjectShape(
items: [
@ObjectShapeItem(
keyName: @ConstExprString(
value: 'e'
)
optional: false
valueType: @IdentifierType(
name: 'int'
attributes: {
kind: 'Keyword'
}
)
),
]
)
name: 'e'
magic: true
public: true
)
}
name: 'ApiGenTests\Features\PhpDoc\Types\ObjectShapes'
primary: true
),
]
14 changes: 14 additions & 0 deletions tests/Features/PhpDoc/Types/ObjectShapes.php
@@ -0,0 +1,14 @@
<?php declare(strict_types = 1);

namespace ApiGenTests\Features\PhpDoc\Types;

/**
* @property object{a: int} $a
* @property object{b: ?int} $b
* @property object{c?: int} $c
* @property ?object{d: int} $d
* @property object{'e': int} $e
*/
interface ObjectShapes
{
}

0 comments on commit 9435f6c

Please sign in to comment.