From 2c684ddf181d9c0f670a3106a4ae35af5c2f52d5 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Mon, 21 Oct 2019 21:15:37 -0700 Subject: [PATCH 1/9] consume newlines --- src/Parser/TypeParser.php | 3 +++ tests/PHPStan/Parser/TypeParserTest.php | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Parser/TypeParser.php b/src/Parser/TypeParser.php index 5289c947..1d20112e 100644 --- a/src/Parser/TypeParser.php +++ b/src/Parser/TypeParser.php @@ -221,12 +221,15 @@ private function tryParseArray(TokenIterator $tokens, Ast\Type\TypeNode $type): private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode { $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); $items = [$this->parseArrayShapeItem($tokens)]; while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); $items[] = $this->parseArrayShapeItem($tokens); } + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET); return new Ast\Type\ArrayShapeNode($items); diff --git a/tests/PHPStan/Parser/TypeParserTest.php b/tests/PHPStan/Parser/TypeParserTest.php index a9e5e8df..abf571e8 100644 --- a/tests/PHPStan/Parser/TypeParserTest.php +++ b/tests/PHPStan/Parser/TypeParserTest.php @@ -393,7 +393,12 @@ public function provideParseData(): array ]), ], [ - 'array{a: int, b: array{c: callable(): int}}', + 'array{ + a: int, + b: array{ + c: callable(): int + } + }', new ArrayShapeNode([ new ArrayShapeItemNode( new IdentifierTypeNode('a'), From e6ec02660f995ab1adb0c8ed50a189eeedbcb2e5 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Mon, 21 Oct 2019 22:03:52 -0700 Subject: [PATCH 2/9] fix unrelated phpstan error --- src/Ast/PhpDoc/TemplateTagValueNode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ast/PhpDoc/TemplateTagValueNode.php b/src/Ast/PhpDoc/TemplateTagValueNode.php index 4c82ba74..dd59b909 100644 --- a/src/Ast/PhpDoc/TemplateTagValueNode.php +++ b/src/Ast/PhpDoc/TemplateTagValueNode.php @@ -26,7 +26,7 @@ public function __construct(string $name, ?TypeNode $bound, string $description) public function __toString(): string { - $bound = $this->bound ? " of {$this->bound}" : ''; + $bound = isset($this->bound) ? " of {$this->bound}" : ''; return trim("{$this->name}{$bound} {$this->description}"); } From 7e0ad3ae8e77799b2e4744f751e004ba52cd146c Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 07:09:57 -0700 Subject: [PATCH 3/9] explicit null check --- src/Ast/PhpDoc/TemplateTagValueNode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ast/PhpDoc/TemplateTagValueNode.php b/src/Ast/PhpDoc/TemplateTagValueNode.php index dd59b909..5847df22 100644 --- a/src/Ast/PhpDoc/TemplateTagValueNode.php +++ b/src/Ast/PhpDoc/TemplateTagValueNode.php @@ -26,7 +26,7 @@ public function __construct(string $name, ?TypeNode $bound, string $description) public function __toString(): string { - $bound = isset($this->bound) ? " of {$this->bound}" : ''; + $bound = $this->bound !== null ? " of {$this->bound}" : ''; return trim("{$this->name}{$bound} {$this->description}"); } From 414daf3af6c11198b6548d9f4b372fa3c4adcc7d Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 07:26:59 -0700 Subject: [PATCH 4/9] add test with asterisks --- tests/PHPStan/Parser/TypeParserTest.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/PHPStan/Parser/TypeParserTest.php b/tests/PHPStan/Parser/TypeParserTest.php index abf571e8..2a107b4e 100644 --- a/tests/PHPStan/Parser/TypeParserTest.php +++ b/tests/PHPStan/Parser/TypeParserTest.php @@ -393,12 +393,7 @@ public function provideParseData(): array ]), ], [ - 'array{ - a: int, - b: array{ - c: callable(): int - } - }', + 'array{a: int, b: array{c: callable(): int}}', new ArrayShapeNode([ new ArrayShapeItemNode( new IdentifierTypeNode('a'), @@ -470,6 +465,18 @@ public function provideParseData(): array Lexer::TOKEN_IDENTIFIER ), ], + [ + 'array{ + * a: int + *}', + new ArrayShapeNode([ + new ArrayShapeItemNode( + new IdentifierTypeNode('a'), + false, + new IdentifierTypeNode('int') + ), + ]), + ], [ 'callable(): Foo', new CallableTypeNode( From 2e69b9aac9148471cf6fb7e57de3af88aad5d03e Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 07:29:26 -0700 Subject: [PATCH 5/9] single comma --- tests/PHPStan/Parser/TypeParserTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/PHPStan/Parser/TypeParserTest.php b/tests/PHPStan/Parser/TypeParserTest.php index 2a107b4e..08b98d4e 100644 --- a/tests/PHPStan/Parser/TypeParserTest.php +++ b/tests/PHPStan/Parser/TypeParserTest.php @@ -477,6 +477,24 @@ public function provideParseData(): array ), ]), ], + [ + 'array{ + a: int, + b: string + }', + new ArrayShapeNode([ + new ArrayShapeItemNode( + new IdentifierTypeNode('a'), + false, + new IdentifierTypeNode('int') + ), + new ArrayShapeItemNode( + new IdentifierTypeNode('b'), + false, + new IdentifierTypeNode('string') + ), + ]), + ], [ 'callable(): Foo', new CallableTypeNode( From 571feedd4330bdae2ff6615934fc99491642ce93 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 08:00:13 -0700 Subject: [PATCH 6/9] support trailing commas --- src/Parser/TypeParser.php | 5 +++++ tests/PHPStan/Parser/TypeParserTest.php | 30 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/Parser/TypeParser.php b/src/Parser/TypeParser.php index 1d20112e..322fc8fe 100644 --- a/src/Parser/TypeParser.php +++ b/src/Parser/TypeParser.php @@ -226,6 +226,11 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type) while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + if($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + // trailing comma case + return new Ast\Type\ArrayShapeNode($items); + } + $items[] = $this->parseArrayShapeItem($tokens); } diff --git a/tests/PHPStan/Parser/TypeParserTest.php b/tests/PHPStan/Parser/TypeParserTest.php index 08b98d4e..7557c772 100644 --- a/tests/PHPStan/Parser/TypeParserTest.php +++ b/tests/PHPStan/Parser/TypeParserTest.php @@ -477,6 +477,36 @@ public function provideParseData(): array ), ]), ], + [ + 'array{ + a: int, + }', + new ArrayShapeNode([ + new ArrayShapeItemNode( + new IdentifierTypeNode('a'), + false, + new IdentifierTypeNode('int') + ), + ]), + ], + [ + 'array{ + a: int, + b: string, + }', + new ArrayShapeNode([ + new ArrayShapeItemNode( + new IdentifierTypeNode('a'), + false, + new IdentifierTypeNode('int') + ), + new ArrayShapeItemNode( + new IdentifierTypeNode('b'), + false, + new IdentifierTypeNode('string') + ), + ]), + ], [ 'array{ a: int, From 1f26308585b4329dd5c4359915d5ac2ea7554b32 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 08:10:41 -0700 Subject: [PATCH 7/9] commas on next line --- src/Parser/TypeParser.php | 2 ++ tests/PHPStan/Parser/TypeParserTest.php | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Parser/TypeParser.php b/src/Parser/TypeParser.php index 322fc8fe..772816f7 100644 --- a/src/Parser/TypeParser.php +++ b/src/Parser/TypeParser.php @@ -224,6 +224,7 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type) $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); $items = [$this->parseArrayShapeItem($tokens)]; + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); if($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { @@ -232,6 +233,7 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type) } $items[] = $this->parseArrayShapeItem($tokens); + $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); } $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); diff --git a/tests/PHPStan/Parser/TypeParserTest.php b/tests/PHPStan/Parser/TypeParserTest.php index 7557c772..38bbf5f9 100644 --- a/tests/PHPStan/Parser/TypeParserTest.php +++ b/tests/PHPStan/Parser/TypeParserTest.php @@ -507,6 +507,30 @@ public function provideParseData(): array ), ]), ], + [ + 'array{ + a: int + , b: string + , c: string + }', + new ArrayShapeNode([ + new ArrayShapeItemNode( + new IdentifierTypeNode('a'), + false, + new IdentifierTypeNode('int') + ), + new ArrayShapeItemNode( + new IdentifierTypeNode('b'), + false, + new IdentifierTypeNode('string') + ), + new ArrayShapeItemNode( + new IdentifierTypeNode('c'), + false, + new IdentifierTypeNode('string') + ), + ]), + ], [ 'array{ a: int, From 52d586e731e5c6b963fd1ec3c392e275337e43c9 Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 08:24:34 -0700 Subject: [PATCH 8/9] lint --- src/Parser/TypeParser.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Parser/TypeParser.php b/src/Parser/TypeParser.php index 772816f7..9279b5a5 100644 --- a/src/Parser/TypeParser.php +++ b/src/Parser/TypeParser.php @@ -227,7 +227,7 @@ private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type) $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) { $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); - if($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { // trailing comma case return new Ast\Type\ArrayShapeNode($items); } From 17d28cc099984a5ecbbbfb7b102daa45ce1af62f Mon Sep 17 00:00:00 2001 From: Max Loeb Date: Tue, 22 Oct 2019 08:30:38 -0700 Subject: [PATCH 9/9] lint --- tests/PHPStan/Parser/TypeParserTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Parser/TypeParserTest.php b/tests/PHPStan/Parser/TypeParserTest.php index 38bbf5f9..c7b6c9e4 100644 --- a/tests/PHPStan/Parser/TypeParserTest.php +++ b/tests/PHPStan/Parser/TypeParserTest.php @@ -393,7 +393,7 @@ public function provideParseData(): array ]), ], [ - 'array{a: int, b: array{c: callable(): int}}', + 'array{a: int, b: array{c: callable(): int}}', new ArrayShapeNode([ new ArrayShapeItemNode( new IdentifierTypeNode('a'),