Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 57090cf

Browse files
authored
Add support for list shapes
1 parent b065956 commit 57090cf

File tree

3 files changed

+45
-9
lines changed

3 files changed

+45
-9
lines changed

‎src/Ast/Type/ArrayShapeNode.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
class ArrayShapeNode implements TypeNode
99
{
1010

11+
public const KIND_ARRAY = 'array';
12+
public const KIND_LIST = 'list';
13+
1114
use NodeAttributes;
1215

1316
/** @var ArrayShapeItemNode[] */
@@ -16,10 +19,17 @@ class ArrayShapeNode implements TypeNode
1619
/** @var bool */
1720
public $sealed;
1821

19-
public function __construct(array $items, bool $sealed = true)
22+
/** @var self::KIND_* */
23+
public $kind;
24+
25+
/**
26+
* @param self::KIND_* $kind
27+
*/
28+
public function __construct(array $items, bool $sealed = true, string $kind = self::KIND_ARRAY)
2029
{
2130
$this->items = $items;
2231
$this->sealed = $sealed;
32+
$this->kind = $kind;
2333
}
2434

2535

@@ -31,7 +41,7 @@ public function __toString(): string
3141
$items[] = '...';
3242
}
3343

34-
return 'array{' . implode(', ', $items) . '}';
44+
return $this->kind . '{' . implode(', ', $items) . '}';
3545
}
3646

3747
}

‎src/Parser/TypeParser.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use LogicException;
66
use PHPStan\PhpDocParser\Ast;
77
use PHPStan\PhpDocParser\Lexer\Lexer;
8+
use function in_array;
89
use function strpos;
910
use function trim;
1011

@@ -123,8 +124,8 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
123124
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
124125
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
125126

126-
} elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
127-
$type = $this->parseArrayShape($tokens, $type);
127+
} elseif (in_array($type->name, ['array', 'list'], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
128+
$type = $this->parseArrayShape($tokens, $type, $type->name);
128129

129130
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
130131
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
@@ -439,8 +440,8 @@ private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNo
439440
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
440441
$type = $this->parseGeneric($tokens, $type);
441442

442-
} elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
443-
$type = $this->parseArrayShape($tokens, $type);
443+
} elseif (in_array($type->name, ['array', 'list'], true) && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
444+
$type = $this->parseArrayShape($tokens, $type, $type->name);
444445
}
445446
}
446447

@@ -499,8 +500,11 @@ private function tryParseArrayOrOffsetAccess(TokenIterator $tokens, Ast\Type\Typ
499500
}
500501

501502

502-
/** @phpstan-impure */
503-
private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\ArrayShapeNode
503+
/**
504+
* @phpstan-impure
505+
* @param Ast\Type\ArrayShapeNode::KIND_* $kind
506+
*/
507+
private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type, string $kind): Ast\Type\ArrayShapeNode
504508
{
505509
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET);
506510

@@ -528,7 +532,7 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type)
528532
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
529533
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
530534

531-
return new Ast\Type\ArrayShapeNode($items, $sealed);
535+
return new Ast\Type\ArrayShapeNode($items, $sealed, $kind);
532536
}
533537

534538

‎tests/PHPStan/Parser/TypeParserTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,28 @@ public function provideParseData(): array
668668
Lexer::TOKEN_CLOSE_CURLY_BRACKET
669669
),
670670
],
671+
[
672+
'list{
673+
int,
674+
string
675+
}',
676+
new ArrayShapeNode(
677+
[
678+
new ArrayShapeItemNode(
679+
null,
680+
false,
681+
new IdentifierTypeNode('int')
682+
),
683+
new ArrayShapeItemNode(
684+
null,
685+
false,
686+
new IdentifierTypeNode('string')
687+
),
688+
],
689+
true,
690+
ArrayShapeNode::KIND_LIST
691+
),
692+
],
671693
[
672694
'callable(): Foo',
673695
new CallableTypeNode(

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /