1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 09:37:59 +01:00

Fix #1784 - detect missing end brackets

This commit is contained in:
Matthew Brown 2019-06-15 17:57:40 -04:00
parent 56e66af6a2
commit 41cdde514f
5 changed files with 44 additions and 9 deletions

View File

@ -86,7 +86,7 @@ class Analyzer
/** /**
* Used to store counts of mixed vs non-mixed variables * Used to store counts of mixed vs non-mixed variables
* *
* @var array<string, array{0: int, 1: int} * @var array<string, array{0: int, 1: int}>
*/ */
private $mixed_counts = []; private $mixed_counts = [];

View File

@ -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; return $parse_tree;
} }

View File

@ -43,7 +43,7 @@ class CodebaseTest extends TestCase
); );
} }
/** @return iterable<int,array{string,string,bool} */ /** @return iterable<int,array{string,string,bool}> */
public function typeContainments() public function typeContainments()
{ {
yield ['int', 'int|string', true]; yield ['int', 'int|string', true];
@ -74,7 +74,7 @@ class CodebaseTest extends TestCase
); );
} }
/** @return iterable<int,array{string,string,bool} */ /** @return iterable<int,array{string,string,bool}> */
public function typeIntersections() public function typeIntersections()
{ {
yield ['int', 'int|string', true]; yield ['int', 'int|string', true];
@ -114,11 +114,11 @@ class CodebaseTest extends TestCase
); );
} }
/** @return iterable<int,array{string,array{string,string}} */ /** @return iterable<int,array{string,array{string,string}}> */
public function iterableParams() public function iterableParams()
{ {
yield ['iterable<int,string>', ['int', 'string']]; yield ['iterable<int,string>', ['int', 'string']];
yield ['iterable<int|string,bool|float', ['int|string', 'bool|float']]; yield ['iterable<int|string,bool|float>', ['int|string', 'bool|float']];
} }
/** /**

View File

@ -100,11 +100,18 @@ class TypeParseTest extends TestCase
/** /**
* @return void * @return void
*/ */
public function testArray() public function testArrayWithClosingBracket()
{ {
$this->assertSame('array<int, int>', (string) Type::parseString('array<int, int>')); $this->assertSame('array<int, int>', (string) Type::parseString('array<int, int>'));
$this->assertSame('array<int, string>', (string) Type::parseString('array<int, string>')); }
$this->assertSame('array<int, static>', (string) Type::parseString('array<int, static>'));
/**
* @return void
*/
public function testArrayWithoutClosingBracket()
{
$this->expectException(\Psalm\Exception\TypeParseTreeException::class);
Type::parseString('array<int, int');
} }
/** /**
@ -317,6 +324,15 @@ class TypeParseTest extends TestCase
$this->assertSame('array{a:int, b:string}', (string) Type::parseString('array{a:int, b:string}')); $this->assertSame('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 * @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 * @return void
*/ */

View File

@ -100,7 +100,7 @@ class UnusedVariableTest extends TestCase
} }
/** /**
* @return array<string, array{string,error_levels?:string[]} * @return array<string, array{string,error_levels?:string[]}>
*/ */
public function providerValidCodeParse() public function providerValidCodeParse()
{ {