Skip to content

Commit d840b69

Browse files
committedMay 4, 2020
Fix parsing const fetches with wildcard in complex types
1 parent 486b638 commit d840b69

File tree

6 files changed

+55
-65
lines changed

6 files changed

+55
-65
lines changed
 

Diff for: ‎src/Lexer/Lexer.php

+8-4
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,14 @@ class Lexer
1818
public const TOKEN_CLOSE_ANGLE_BRACKET = 7;
1919
public const TOKEN_OPEN_SQUARE_BRACKET = 8;
2020
public const TOKEN_CLOSE_SQUARE_BRACKET = 9;
21-
public const TOKEN_OPEN_CURLY_BRACKET = 30;
22-
public const TOKEN_CLOSE_CURLY_BRACKET = 31;
2321
public const TOKEN_COMMA = 10;
24-
public const TOKEN_COLON = 29;
2522
public const TOKEN_VARIADIC = 11;
2623
public const TOKEN_DOUBLE_COLON = 12;
2724
public const TOKEN_DOUBLE_ARROW = 13;
2825
public const TOKEN_EQUAL = 14;
2926
public const TOKEN_OPEN_PHPDOC = 15;
3027
public const TOKEN_CLOSE_PHPDOC = 16;
3128
public const TOKEN_PHPDOC_TAG = 17;
32-
public const TOKEN_PHPDOC_EOL = 26;
3329
public const TOKEN_FLOAT = 18;
3430
public const TOKEN_INTEGER = 19;
3531
public const TOKEN_SINGLE_QUOTED_STRING = 20;
@@ -38,8 +34,13 @@ class Lexer
3834
public const TOKEN_THIS_VARIABLE = 23;
3935
public const TOKEN_VARIABLE = 24;
4036
public const TOKEN_HORIZONTAL_WS = 25;
37+
public const TOKEN_PHPDOC_EOL = 26;
4138
public const TOKEN_OTHER = 27;
4239
public const TOKEN_END = 28;
40+
public const TOKEN_COLON = 29;
41+
public const TOKEN_WILDCARD = 30;
42+
public const TOKEN_OPEN_CURLY_BRACKET = 31;
43+
public const TOKEN_CLOSE_CURLY_BRACKET = 32;
4344

4445
public const TOKEN_LABELS = [
4546
self::TOKEN_REFERENCE => '\'&\'',
@@ -74,6 +75,7 @@ class Lexer
7475
self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS',
7576
self::TOKEN_OTHER => 'TOKEN_OTHER',
7677
self::TOKEN_END => 'TOKEN_END',
78+
self::TOKEN_WILDCARD => '*',
7779
];
7880

7981
public const VALUE_OFFSET = 0;
@@ -153,6 +155,8 @@ private function initialize(): void
153155

154156
self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++',
155157

158+
self::TOKEN_WILDCARD => '\\*',
159+
156160
// anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
157161
self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++',
158162
];

Diff for: ‎src/Parser/ConstExprParser.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ public function parse(TokenIterator $tokens, bool $trimStrings = false): Ast\Con
5757
if ($tokens->currentTokenType() === Lexer::TOKEN_IDENTIFIER) {
5858
$classConstantName .= $tokens->currentTokenValue();
5959
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
60-
if ($tokens->tryConsumeTokenValue('*')) {
60+
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) {
6161
$classConstantName .= '*';
6262
}
6363
} else {
64-
$tokens->consumeTokenValue('*');
64+
$tokens->consumeTokenType(Lexer::TOKEN_WILDCARD);
6565
$classConstantName .= '*';
6666
}
6767

Diff for: ‎src/Parser/ParserException.php

+7-28
Original file line numberDiff line numberDiff line change
@@ -19,43 +19,27 @@ class ParserException extends \Exception
1919
/** @var int */
2020
private $expectedTokenType;
2121

22-
/** @var string */
23-
private $expectedTokenValue;
24-
2522
public function __construct(
2623
string $currentTokenValue,
2724
int $currentTokenType,
2825
int $currentOffset,
29-
?int $expectedTokenType,
30-
?string $expectedTokenValue = null
26+
int $expectedTokenType
3127
)
3228
{
3329
$this->currentTokenValue = $currentTokenValue;
3430
$this->currentTokenType = $currentTokenType;
3531
$this->currentOffset = $currentOffset;
3632
$this->expectedTokenType = $expectedTokenType;
37-
$this->expectedTokenValue = $expectedTokenValue;
3833

3934
$json = json_encode($currentTokenValue, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
4035
assert($json !== false);
4136

42-
if ($expectedTokenType !== null) {
43-
parent::__construct(sprintf(
44-
'Unexpected token %s, expected %s at offset %d',
45-
$json,
46-
Lexer::TOKEN_LABELS[$expectedTokenType],
47-
$currentOffset
48-
));
49-
} elseif ($expectedTokenValue !== null) {
50-
parent::__construct(sprintf(
51-
'Unexpected token value %s, expected value %s at offset %d',
52-
$json,
53-
$expectedTokenValue,
54-
$currentOffset
55-
));
56-
} else {
57-
throw new \LogicException();
58-
}
37+
parent::__construct(sprintf(
38+
'Unexpected token %s, expected %s at offset %d',
39+
$json,
40+
Lexer::TOKEN_LABELS[$expectedTokenType],
41+
$currentOffset
42+
));
5943
}
6044

6145

@@ -82,9 +66,4 @@ public function getExpectedTokenType(): int
8266
return $this->expectedTokenType;
8367
}
8468

85-
public function getExpectedTokenValue(): string
86-
{
87-
return $this->expectedTokenValue;
88-
}
89-
9069
}

Diff for: ‎src/Parser/TokenIterator.php

+3-24
Original file line numberDiff line numberDiff line change
@@ -69,25 +69,6 @@ public function isPrecededByHorizontalWhitespace(): bool
6969
return ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS;
7070
}
7171

72-
/**
73-
* @param string $tokenValue
74-
* @throws \PHPStan\PhpDocParser\Parser\ParserException
75-
*/
76-
public function consumeTokenValue(string $tokenValue): void
77-
{
78-
if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) {
79-
$this->throwError(null, $tokenValue);
80-
}
81-
82-
$this->index++;
83-
84-
if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) !== Lexer::TOKEN_HORIZONTAL_WS) {
85-
return;
86-
}
87-
88-
$this->index++;
89-
}
90-
9172

9273
/**
9374
* @param int $tokenType
@@ -194,18 +175,16 @@ public function rollback(): void
194175

195176

196177
/**
197-
* @param int|null $expectedTokenType
198-
* @param string|null $expectedTokenValue
178+
* @param int $expectedTokenType
199179
* @throws \PHPStan\PhpDocParser\Parser\ParserException
200180
*/
201-
private function throwError(?int $expectedTokenType, ?string $expectedTokenValue): void
181+
private function throwError(int $expectedTokenType): void
202182
{
203183
throw new \PHPStan\PhpDocParser\Parser\ParserException(
204184
$this->currentTokenValue(),
205185
$this->currentTokenType(),
206186
$this->currentTokenOffset(),
207-
$expectedTokenType,
208-
$expectedTokenValue
187+
$expectedTokenType
209188
);
210189
}
211190

Diff for: ‎tests/PHPStan/Parser/PhpDocParserTest.php

+8
Original file line numberDiff line numberDiff line change
@@ -3046,6 +3046,14 @@ public function provideRealWorldExampleData(): \Iterator
30463046
),
30473047
]),
30483048
];
3049+
3050+
yield [
3051+
'malformed const fetch',
3052+
'/** @param Foo::** $a */',
3053+
new PhpDocNode([
3054+
new PhpDocTagNode('@param', new InvalidTagValueNode('Foo::** $a', new ParserException('*', Lexer::TOKEN_WILDCARD, 17, Lexer::TOKEN_VARIABLE))),
3055+
]),
3056+
];
30493057
}
30503058

30513059
public function dataParseTagValue(): array

Diff for: ‎tests/PHPStan/Parser/TypeParserTest.php

+27-7
Original file line numberDiff line numberDiff line change
@@ -864,13 +864,13 @@ public function provideParseData(): array
864864
],
865865
[
866866
'Foo::**',
867-
new \PHPStan\PhpDocParser\Parser\ParserException(
868-
'**',
869-
Lexer::TOKEN_END,
870-
5,
871-
null,
872-
'*'
873-
),
867+
new ConstTypeNode(new ConstFetchNode('Foo', '*')), // fails later in PhpDocParser
868+
Lexer::TOKEN_WILDCARD,
869+
],
870+
[
871+
'Foo::*a',
872+
new ConstTypeNode(new ConstFetchNode('Foo', '*')), // fails later in PhpDocParser
873+
Lexer::TOKEN_IDENTIFIER,
874874
],
875875
[
876876
'( "foo" | Foo::FOO_* )',
@@ -879,6 +879,26 @@ public function provideParseData(): array
879879
new ConstTypeNode(new ConstFetchNode('Foo', 'FOO_*')),
880880
]),
881881
],
882+
[
883+
'DateTimeImmutable::*|DateTime::*',
884+
new UnionTypeNode([
885+
new ConstTypeNode(new ConstFetchNode('DateTimeImmutable', '*')),
886+
new ConstTypeNode(new ConstFetchNode('DateTime', '*')),
887+
]),
888+
],
889+
[
890+
'ParameterTier::*|null',
891+
new UnionTypeNode([
892+
new ConstTypeNode(new ConstFetchNode('ParameterTier', '*')),
893+
new IdentifierTypeNode('null'),
894+
]),
895+
],
896+
[
897+
'list<QueueAttributeName::*>',
898+
new GenericTypeNode(new IdentifierTypeNode('list'), [
899+
new ConstTypeNode(new ConstFetchNode('QueueAttributeName', '*')),
900+
]),
901+
],
882902
];
883903
}
884904

0 commit comments

Comments
 (0)
Please sign in to comment.