Skip to content

Commit d3753fc

Browse files
committed
Fix parsing invalid types in type aliases
1 parent bfec872 commit d3753fc

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

src/Parser/PhpDocParser.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,20 @@ private function parseTypeAliasTagValue(TokenIterator $tokens): Ast\PhpDoc\TypeA
460460
if ($this->preserveTypeAliasesWithInvalidTypes) {
461461
try {
462462
$type = $this->typeParser->parse($tokens);
463+
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
464+
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
465+
throw new ParserException(
466+
$tokens->currentTokenValue(),
467+
$tokens->currentTokenType(),
468+
$tokens->currentTokenOffset(),
469+
Lexer::TOKEN_PHPDOC_EOL
470+
);
471+
}
472+
}
463473

464474
return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
465475
} catch (ParserException $e) {
476+
$this->parseOptionalDescription($tokens);
466477
return new Ast\PhpDoc\TypeAliasTagValueNode($alias, new Ast\Type\InvalidTypeNode($e));
467478
}
468479
}

tests/PHPStan/Parser/PhpDocParserTest.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,24 @@ public function provideVarTagsData(): Iterator
916916
)
917917
),
918918
]),
919+
null,
920+
new PhpDocNode([
921+
new PhpDocTagNode(
922+
'@psalm-type',
923+
new TypeAliasTagValueNode(
924+
'PARTSTRUCTURE_PARAM',
925+
new InvalidTypeNode(
926+
new ParserException(
927+
'{',
928+
Lexer::TOKEN_OPEN_CURLY_BRACKET,
929+
44,
930+
Lexer::TOKEN_PHPDOC_EOL,
931+
null
932+
)
933+
)
934+
)
935+
),
936+
]),
919937
];
920938
}
921939

@@ -3954,6 +3972,106 @@ public function provideTypeAliasTagsData(): Iterator
39543972
]),
39553973
];
39563974

3975+
yield [
3976+
'invalid type that should be an error',
3977+
'/**
3978+
* @phpstan-type Foo array{}
3979+
* @phpstan-type InvalidFoo what{}
3980+
*/',
3981+
new PhpDocNode([
3982+
new PhpDocTagNode(
3983+
'@phpstan-type',
3984+
new InvalidTagValueNode(
3985+
"Unexpected token \"{\", expected '*/' at offset 65",
3986+
new ParserException(
3987+
'{',
3988+
Lexer::TOKEN_OPEN_CURLY_BRACKET,
3989+
65,
3990+
Lexer::TOKEN_CLOSE_PHPDOC,
3991+
null
3992+
)
3993+
)
3994+
),
3995+
]),
3996+
null,
3997+
new PhpDocNode([
3998+
new PhpDocTagNode(
3999+
'@phpstan-type',
4000+
new TypeAliasTagValueNode(
4001+
'Foo',
4002+
new ArrayShapeNode([])
4003+
)
4004+
),
4005+
new PhpDocTagNode(
4006+
'@phpstan-type',
4007+
new TypeAliasTagValueNode(
4008+
'InvalidFoo',
4009+
new InvalidTypeNode(new ParserException(
4010+
'{',
4011+
Lexer::TOKEN_OPEN_CURLY_BRACKET,
4012+
65,
4013+
Lexer::TOKEN_PHPDOC_EOL,
4014+
null
4015+
))
4016+
)
4017+
),
4018+
]),
4019+
];
4020+
4021+
yield [
4022+
'invalid type that should be an error followed by valid again',
4023+
'/**
4024+
* @phpstan-type Foo array{}
4025+
* @phpstan-type InvalidFoo what{}
4026+
* @phpstan-type Bar array{}
4027+
*/',
4028+
new PhpDocNode([
4029+
new PhpDocTagNode(
4030+
'@phpstan-type',
4031+
new InvalidTagValueNode(
4032+
"Unexpected token \"{\", expected '*/' at offset 65",
4033+
new ParserException(
4034+
'{',
4035+
Lexer::TOKEN_OPEN_CURLY_BRACKET,
4036+
65,
4037+
Lexer::TOKEN_CLOSE_PHPDOC,
4038+
null
4039+
)
4040+
)
4041+
),
4042+
]),
4043+
null,
4044+
new PhpDocNode([
4045+
new PhpDocTagNode(
4046+
'@phpstan-type',
4047+
new TypeAliasTagValueNode(
4048+
'Foo',
4049+
new ArrayShapeNode([])
4050+
)
4051+
),
4052+
new PhpDocTagNode(
4053+
'@phpstan-type',
4054+
new TypeAliasTagValueNode(
4055+
'InvalidFoo',
4056+
new InvalidTypeNode(new ParserException(
4057+
'{',
4058+
Lexer::TOKEN_OPEN_CURLY_BRACKET,
4059+
65,
4060+
Lexer::TOKEN_PHPDOC_EOL,
4061+
null
4062+
))
4063+
)
4064+
),
4065+
new PhpDocTagNode(
4066+
'@phpstan-type',
4067+
new TypeAliasTagValueNode(
4068+
'Bar',
4069+
new ArrayShapeNode([])
4070+
)
4071+
),
4072+
]),
4073+
];
4074+
39574075
yield [
39584076
'invalid empty',
39594077
'/** @phpstan-type */',

0 commit comments

Comments
 (0)