From 41cdde514f41d9f49048e4d63b6e45e77d72cf21 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Sat, 15 Jun 2019 17:57:40 -0400 Subject: [PATCH] Fix #1784 - detect missing end brackets --- src/Psalm/Internal/Codebase/Analyzer.php | 2 +- src/Psalm/Internal/Type/ParseTree.php | 10 ++++++++ tests/CodebaseTest.php | 8 +++--- tests/TypeParseTest.php | 31 +++++++++++++++++++++--- tests/UnusedVariableTest.php | 2 +- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/Psalm/Internal/Codebase/Analyzer.php b/src/Psalm/Internal/Codebase/Analyzer.php index 0222c49f5..e45f1b0a8 100644 --- a/src/Psalm/Internal/Codebase/Analyzer.php +++ b/src/Psalm/Internal/Codebase/Analyzer.php @@ -86,7 +86,7 @@ class Analyzer /** * Used to store counts of mixed vs non-mixed variables * - * @var array */ private $mixed_counts = []; diff --git a/src/Psalm/Internal/Type/ParseTree.php b/src/Psalm/Internal/Type/ParseTree.php index 2986fde36..e5ff42bbf 100644 --- a/src/Psalm/Internal/Type/ParseTree.php +++ b/src/Psalm/Internal/Type/ParseTree.php @@ -531,6 +531,16 @@ class ParseTree } } + if ($current_leaf !== $parse_tree + && ($parse_tree instanceof ParseTree\GenericTree + || $parse_tree instanceof ParseTree\CallableTree + || $parse_tree instanceof ParseTree\ObjectLikeTree) + ) { + throw new TypeParseTreeException( + 'Unterminated bracket' + ); + } + return $parse_tree; } diff --git a/tests/CodebaseTest.php b/tests/CodebaseTest.php index bd070e3bd..d506cde64 100644 --- a/tests/CodebaseTest.php +++ b/tests/CodebaseTest.php @@ -43,7 +43,7 @@ class CodebaseTest extends TestCase ); } - /** @return iterable */ public function typeContainments() { yield ['int', 'int|string', true]; @@ -74,7 +74,7 @@ class CodebaseTest extends TestCase ); } - /** @return iterable */ public function typeIntersections() { yield ['int', 'int|string', true]; @@ -114,11 +114,11 @@ class CodebaseTest extends TestCase ); } - /** @return iterable */ public function iterableParams() { yield ['iterable', ['int', 'string']]; - yield ['iterable', ['int|string', 'bool|float']]; } /** diff --git a/tests/TypeParseTest.php b/tests/TypeParseTest.php index 291a63296..0d8fa091a 100644 --- a/tests/TypeParseTest.php +++ b/tests/TypeParseTest.php @@ -100,11 +100,18 @@ class TypeParseTest extends TestCase /** * @return void */ - public function testArray() + public function testArrayWithClosingBracket() { $this->assertSame('array', (string) Type::parseString('array')); - $this->assertSame('array', (string) Type::parseString('array')); - $this->assertSame('array', (string) Type::parseString('array')); + } + + /** + * @return void + */ + public function testArrayWithoutClosingBracket() + { + $this->expectException(\Psalm\Exception\TypeParseTreeException::class); + Type::parseString('arrayassertSame('array{a:int, b:string}', (string) Type::parseString('array{a:int, b:string}')); } + /** + * @return void + */ + public function testObjectLikeWithoutClosingBracket() + { + $this->expectException(\Psalm\Exception\TypeParseTreeException::class); + Type::parseString('array{a:int, b:string'); + } + /** * @return void */ @@ -396,6 +412,15 @@ class TypeParseTest extends TestCase ); } + /** + * @return void + */ + public function testCallableWithoutClosingBracket() + { + $this->expectException(\Psalm\Exception\TypeParseTreeException::class); + Type::parseString('callable(int, string'); + } + /** * @return void */ diff --git a/tests/UnusedVariableTest.php b/tests/UnusedVariableTest.php index 1c4dabda4..5ddf86ffa 100644 --- a/tests/UnusedVariableTest.php +++ b/tests/UnusedVariableTest.php @@ -100,7 +100,7 @@ class UnusedVariableTest extends TestCase } /** - * @return array */ public function providerValidCodeParse() {