-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Array shapes support #30
Conversation
Related: phpstan/phpstan#2173 |
I love it! 😍 But looks like you've forgot to add those new classes in. The build (after my CS fix) fails on:
BTW: The optional keys in PHPStan are right now modeled with a union of two constant arrays - with the keys and without the keys. Unfortunately, this leads to some wrongly interpreted code. We can improve that later for example by introducing optional keys to ConstantArrayType but that brings more work. I'd continue represent them with unions of two arrays right now. |
@@ -53,6 +55,9 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode | |||
|
|||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { | |||
$type = $this->tryParseArray($tokens, $type); | |||
|
|||
} elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { | |||
$type = $this->parseArrayShape($tokens, $type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be maybe tryParseArrayShape
, so that /** @return array {curly description} */
is not suddenly invalid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with tryParse
is that it silently ignores errors. An array shape specification will be silently ignored if it has a minor typo in it.
Alternatively, if we don't allow spaces between array
and {
, this would prevent the problem you mention. We could do that by adding an array{
token. What do you think ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with tryParse is that it silently ignores errors.
That's not a problem of tryParse
but inherent problem of phpDoc which is designed to be human friendly and not computer friendly (same problem as markdown).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
without tryParse
it's a BC break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what do you think of not allowing a whitespace between array
and {
? This would prevent the BC break, while also avoiding silenced errors (which are not user friendly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
f93ce08
to
d5c7122
Compare
@@ -53,6 +55,9 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode | |||
|
|||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { | |||
$type = $this->tryParseArray($tokens, $type); | |||
|
|||
} elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { | |||
$type = $this->parseArrayShape($tokens, $type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with tryParse is that it silently ignores errors.
That's not a problem of tryParse
but inherent problem of phpDoc which is designed to be human friendly and not computer friendly (same problem as markdown).
@@ -53,6 +55,9 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode | |||
|
|||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) { | |||
$type = $this->tryParseArray($tokens, $type); | |||
|
|||
} elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { | |||
$type = $this->parseArrayShape($tokens, $type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
without tryParse
it's a BC break.
I wonder if we should make Also it should be noted that allowing quoted string (which psalm does not allow) introduces grammar inconsistency (because it creates a place which looks like it expects constants expression but identifiers are not treated as constants) so I'm not sure it's a good idea. |
cc @muglug |
I'm in favor of not allowing whitespaces between Pros:
Cons:
While looking at Psalm I though it was supported, but you are right: it's not. In Pslam, So I would be in favor of either allowing quoted strings (so that |
Thank you both for improving this! @arnaud-lb I don't see a testcase for something wrong inside the |
Added :) More about keys:
Thoughts ? |
I think this is the best option for now. Edit: identifiers + integers |
Array key escaping is an open issue vimeo/psalm#1518 Psalm should support it, I just haven’t got around to it yet |
We should have a test that verifies that quoted string as a key parsing fails :) Otherwise it's ready to merge, right, everyone? |
👍 added a test |
Thank you very much! I'll start poking it with ConstantArrayType right away :) |
And done: phpstan/phpstan@c4ed3c7 Feel free to review :) |
Adds support for parsing array shapes (object-like arrays).
Examples:
Keys can be single quoted strings, double quoted strings, integers, or identifiers (represented as ConstExprStringNode, ConstExprIntegerNode, IdentifierTypeNode).
They can be marked optional with a
?
before the key and the:
.They can be omitted entirely.
Values can be any type, including nullable types or nested array shapes.