diff --git a/src/Psalm/Internal/Type/ParseTreeCreator.php b/src/Psalm/Internal/Type/ParseTreeCreator.php index edad53cb928..0ee5d9b329f 100644 --- a/src/Psalm/Internal/Type/ParseTreeCreator.php +++ b/src/Psalm/Internal/Type/ParseTreeCreator.php @@ -751,6 +751,16 @@ private function handleValue(array $type_token): void $new_parent ); ++$this->t; + + $nexter_token = $this->t + 1 < $this->type_token_count ? $this->type_tokens[$this->t + 1] : null; + + if ($nexter_token !== null && $nexter_token[0] === '}') { + $new_leaf->terminated = true; + ++$this->t; + } elseif ($nexter_token === null) { + throw new TypeParseTreeException('Unclosed bracket in keyed array'); + } + break; case '(': diff --git a/src/Psalm/Internal/Type/TypeParser.php b/src/Psalm/Internal/Type/TypeParser.php index 26e2658ca4b..d7b9f8268e6 100644 --- a/src/Psalm/Internal/Type/TypeParser.php +++ b/src/Psalm/Internal/Type/TypeParser.php @@ -1235,7 +1235,7 @@ private static function getTypeFromIndexAccessTree( /** * @param array> $template_type_map * @param array $type_aliases - * @return TCallableKeyedArray|TKeyedArray|TObjectWithProperties + * @return TCallableKeyedArray|TKeyedArray|TObjectWithProperties|TArray * @throws TypeParseTreeException */ private static function getTypeFromKeyedArrayTree( @@ -1314,7 +1314,7 @@ private static function getTypeFromKeyedArrayTree( } if (!$properties) { - throw new TypeParseTreeException('No properties supplied for TKeyedArray'); + return new TArray([Type::getNever(), Type::getNever()]); } if ($type === 'object') { diff --git a/tests/AnnotationTest.php b/tests/AnnotationTest.php index 2f7ec306d08..506524aa215 100644 --- a/tests/AnnotationTest.php +++ b/tests/AnnotationTest.php @@ -1490,14 +1490,6 @@ public function bar() { ', 'error_message' => 'UndefinedDocblockClass', ], - 'preventBadTKeyedArrayFormat' => [ - ' 'InvalidDocblock', - ], 'noPhpStormAnnotationsThankYou' => [ 'assertSame( + 'array', + (string)Type::parseString('array{}') + ); + } + public function testSingleLiteralInt(): void { $this->assertSame(