Skip to content

Commit 928179e

Browse files
iluuu1994ondrejmirtes
authored andcommitted
Fix parsing of [] in various cases - closes #36
* Array shapes * Generics * $this * Nullables
1 parent 1a80f73 commit 928179e

File tree

2 files changed

+107
-3
lines changed

2 files changed

+107
-3
lines changed

src/Parser/TypeParser.php

+20-3
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,22 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
3737
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
3838
$type = $this->tryParseArray($tokens, $type);
3939
}
40-
4140
} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
42-
return new Ast\Type\ThisTypeNode();
41+
$type = new Ast\Type\ThisTypeNode();
4342

43+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
44+
$type = $this->tryParseArray($tokens, $type);
45+
}
4446
} else {
4547
$type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
4648
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
4749

4850
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
4951
$type = $this->parseGeneric($tokens, $type);
5052

53+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
54+
$type = $this->tryParseArray($tokens, $type);
55+
}
5156
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
5257
$type = $this->tryParseCallable($tokens, $type);
5358

@@ -56,6 +61,10 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
5661

5762
} elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
5863
$type = $this->parseArrayShape($tokens, $type);
64+
65+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
66+
$type = $this->tryParseArray($tokens, $type);
67+
}
5968
}
6069
}
6170

@@ -101,6 +110,10 @@ private function parseNullable(TokenIterator $tokens): Ast\Type\TypeNode
101110
$type = $this->parseArrayShape($tokens, $type);
102111
}
103112

113+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
114+
$type = $this->tryParseArray($tokens, $type);
115+
}
116+
104117
return new Ast\Type\NullableTypeNode($type);
105118
}
106119

@@ -179,6 +192,10 @@ private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNo
179192
}
180193
}
181194

195+
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
196+
$type = $this->tryParseArray($tokens, $type);
197+
}
198+
182199
return $type;
183200
}
184201

@@ -218,7 +235,7 @@ private function tryParseArray(TokenIterator $tokens, Ast\Type\TypeNode $type):
218235
}
219236

220237

221-
private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
238+
private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\ArrayShapeNode
222239
{
223240
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET);
224241
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);

tests/PHPStan/Parser/TypeParserTest.php

+87
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,93 @@ public function provideParseData(): array
711711
new IdentifierTypeNode("\xA009")
712712
),
713713
],
714+
[
715+
'Collection<array-key, int>[]',
716+
new ArrayTypeNode(
717+
new GenericTypeNode(
718+
new IdentifierTypeNode('Collection'),
719+
[
720+
new IdentifierTypeNode('array-key'),
721+
new IdentifierTypeNode('int'),
722+
]
723+
)
724+
),
725+
],
726+
[
727+
'int | Collection<array-key, int>[]',
728+
new UnionTypeNode([
729+
new IdentifierTypeNode('int'),
730+
new ArrayTypeNode(
731+
new GenericTypeNode(
732+
new IdentifierTypeNode('Collection'),
733+
[
734+
new IdentifierTypeNode('array-key'),
735+
new IdentifierTypeNode('int'),
736+
]
737+
)
738+
),
739+
]),
740+
],
741+
[
742+
'array{foo: int}[]',
743+
new ArrayTypeNode(
744+
new ArrayShapeNode([
745+
new ArrayShapeItemNode(
746+
new IdentifierTypeNode('foo'),
747+
false,
748+
new IdentifierTypeNode('int')
749+
),
750+
])
751+
),
752+
],
753+
[
754+
'int | array{foo: int}[]',
755+
new UnionTypeNode([
756+
new IdentifierTypeNode('int'),
757+
new ArrayTypeNode(
758+
new ArrayShapeNode([
759+
new ArrayShapeItemNode(
760+
new IdentifierTypeNode('foo'),
761+
false,
762+
new IdentifierTypeNode('int')
763+
),
764+
])
765+
),
766+
]),
767+
],
768+
[
769+
'$this[]',
770+
new ArrayTypeNode(
771+
new ThisTypeNode()
772+
),
773+
],
774+
[
775+
'int | $this[]',
776+
new UnionTypeNode([
777+
new IdentifierTypeNode('int'),
778+
new ArrayTypeNode(
779+
new ThisTypeNode()
780+
),
781+
]),
782+
],
783+
[
784+
'callable(): int[]',
785+
new CallableTypeNode(
786+
new IdentifierTypeNode('callable'),
787+
[],
788+
new ArrayTypeNode(
789+
new IdentifierTypeNode('int')
790+
)
791+
),
792+
],
793+
[
794+
'?int[]',
795+
new NullableTypeNode(
796+
new ArrayTypeNode(
797+
new IdentifierTypeNode('int')
798+
)
799+
),
800+
],
714801
];
715802
}
716803

0 commit comments

Comments
 (0)