From 54893fdd55bd74c0a89ca36472c10dfe0ba44cfe Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Mon, 11 Jun 2018 17:23:28 -0400 Subject: [PATCH] Fix #808 - detect badly-placed ampersand early --- src/Psalm/Type/ParseTree.php | 23 +++++++++++++++++++-- tests/AnnotationTest.php | 8 ++++++++ tests/TypeParseTest.php | 40 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Type/ParseTree.php b/src/Psalm/Type/ParseTree.php index 4d695c048..7c7147900 100644 --- a/src/Psalm/Type/ParseTree.php +++ b/src/Psalm/Type/ParseTree.php @@ -54,11 +54,11 @@ class ParseTree throw new TypeParseTreeException('Unexpected token ' . $type_token); case '[': - if ($next_token !== ']') { + if ($current_leaf instanceof ParseTree\Root) { throw new TypeParseTreeException('Unexpected token ' . $type_token); } - if ($current_leaf instanceof ParseTree\Root) { + if ($next_token !== ']') { throw new TypeParseTreeException('Unexpected token ' . $type_token); } @@ -143,6 +143,11 @@ class ParseTree break; case ',': + if ($current_leaf instanceof ParseTree\Root) { + throw new TypeParseTreeException('Unexpected token ' . $type_token); + } + + if (!$current_leaf->parent) { throw new TypeParseTreeException('Cannot parse comma without a parent node'); } @@ -213,6 +218,10 @@ class ParseTree break; case ':': + if ($current_leaf instanceof ParseTree\Root) { + throw new TypeParseTreeException('Unexpected token ' . $type_token); + } + $current_parent = $current_leaf->parent; if ($current_leaf instanceof ParseTree\CallableTree) { @@ -277,6 +286,10 @@ class ParseTree break; case '|': + if ($current_leaf instanceof ParseTree\Root) { + throw new TypeParseTreeException('Unexpected token ' . $type_token); + } + $added_null = false; $current_parent = $current_leaf->parent; @@ -321,6 +334,12 @@ class ParseTree break; case '&': + if ($current_leaf instanceof ParseTree\Root) { + throw new TypeParseTreeException( + 'Unexpected &' + ); + } + $current_parent = $current_leaf->parent; if ($current_parent && $current_parent instanceof ParseTree\IntersectionTree) { diff --git a/tests/AnnotationTest.php b/tests/AnnotationTest.php index 3e035c1cb..8afe438be 100644 --- a/tests/AnnotationTest.php +++ b/tests/AnnotationTest.php @@ -1426,6 +1426,14 @@ class AnnotationTest extends TestCase }', 'error_message' => 'InvalidDocblock', ], + 'badAmpersand' => [ + ' 'InvalidDocblock', + ], ]; } } diff --git a/tests/TypeParseTest.php b/tests/TypeParseTest.php index d81729ae8..8d9e1b432 100644 --- a/tests/TypeParseTest.php +++ b/tests/TypeParseTest.php @@ -453,6 +453,46 @@ class TypeParseTest extends TestCase Type::parseString('string;'); } + /** + * @expectedException \Psalm\Exception\TypeParseTreeException + * + * @return void + */ + public function testBadAmpersand() + { + Type::parseString('&array'); + } + + /** + * @expectedException \Psalm\Exception\TypeParseTreeException + * + * @return void + */ + public function testBadColon() + { + Type::parseString(':array'); + } + + /** + * @expectedException \Psalm\Exception\TypeParseTreeException + * + * @return void + */ + public function testBadEquals() + { + Type::parseString('=array'); + } + + /** + * @expectedException \Psalm\Exception\TypeParseTreeException + * + * @return void + */ + public function testBadBar() + { + Type::parseString('|array'); + } + /** * @expectedException \Psalm\Exception\TypeParseTreeException *