Skip to content

Commit 7ff42f5

Browse files
committed
TypeParser - give all types the line and index attributes
1 parent 4255dd3 commit 7ff42f5

File tree

2 files changed

+70
-21
lines changed

2 files changed

+70
-21
lines changed

src/Parser/TypeParser.php

+20-8
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ public function parse(TokenIterator $tokens): Ast\Type\TypeNode
5757
$type = $this->parseIntersection($tokens, $type);
5858
}
5959
}
60+
61+
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
62+
}
63+
64+
private function enrichWithAttributes(TokenIterator $tokens, Ast\Type\TypeNode $type, int $startLine, int $startIndex): Ast\Type\TypeNode
65+
{
6066
$endLine = $tokens->currentTokenLine();
6167
$endIndex = $tokens->currentTokenIndex();
6268

@@ -76,6 +82,9 @@ public function parse(TokenIterator $tokens): Ast\Type\TypeNode
7682
/** @phpstan-impure */
7783
private function subParse(TokenIterator $tokens): Ast\Type\TypeNode
7884
{
85+
$startLine = $tokens->currentTokenLine();
86+
$startIndex = $tokens->currentTokenIndex();
87+
7988
if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
8089
$type = $this->parseNullable($tokens);
8190

@@ -99,13 +108,16 @@ private function subParse(TokenIterator $tokens): Ast\Type\TypeNode
99108
}
100109
}
101110

102-
return $type;
111+
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
103112
}
104113

105114

106115
/** @phpstan-impure */
107116
private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
108117
{
118+
$startLine = $tokens->currentTokenLine();
119+
$startIndex = $tokens->currentTokenIndex();
120+
109121
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
110122
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
111123
$type = $this->subParse($tokens);
@@ -114,20 +126,20 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
114126
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
115127

116128
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
117-
return $this->tryParseArrayOrOffsetAccess($tokens, $type);
129+
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
118130
}
119131

120-
return $type;
132+
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
121133
}
122134

123135
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
124136
$type = new Ast\Type\ThisTypeNode();
125137

126138
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
127-
return $this->tryParseArrayOrOffsetAccess($tokens, $type);
139+
$type = $this->tryParseArrayOrOffsetAccess($tokens, $type);
128140
}
129141

130-
return $type;
142+
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
131143
}
132144

133145
$currentTokenValue = $tokens->currentTokenValue();
@@ -143,7 +155,7 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
143155
$isHtml = $this->isHtml($tokens);
144156
$tokens->rollback();
145157
if ($isHtml) {
146-
return $type;
158+
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
147159
}
148160

149161
$type = $this->parseGeneric($tokens, $type);
@@ -169,7 +181,7 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
169181
}
170182
}
171183

172-
return $type;
184+
return $this->enrichWithAttributes($tokens, $type, $startLine, $startIndex);
173185
} else {
174186
$tokens->rollback(); // because of ConstFetchNode
175187
}
@@ -196,7 +208,7 @@ private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
196208
throw $exception;
197209
}
198210

199-
return new Ast\Type\ConstTypeNode($constExpr);
211+
return $this->enrichWithAttributes($tokens, new Ast\Type\ConstTypeNode($constExpr), $startLine, $startIndex);
200212
} catch (LogicException $e) {
201213
throw $exception;
202214
}

tests/PHPStan/Parser/TypeParserTest.php

+50-13
Original file line numberDiff line numberDiff line change
@@ -1909,39 +1909,76 @@ public function dataLinesAndIndexes(): iterable
19091909
{
19101910
yield [
19111911
'int | object{foo: int}[]',
1912-
1,
1913-
1,
1914-
0,
1915-
13,
1912+
[
1913+
[
1914+
static function (TypeNode $typeNode): TypeNode {
1915+
return $typeNode;
1916+
},
1917+
1,
1918+
1,
1919+
0,
1920+
13,
1921+
],
1922+
[
1923+
static function (UnionTypeNode $typeNode): TypeNode {
1924+
return $typeNode->types[0];
1925+
},
1926+
1,
1927+
1,
1928+
0,
1929+
2,
1930+
],
1931+
[
1932+
static function (UnionTypeNode $typeNode): TypeNode {
1933+
return $typeNode->types[1];
1934+
},
1935+
1,
1936+
1,
1937+
4,
1938+
13,
1939+
],
1940+
],
19161941
];
19171942

19181943
yield [
19191944
'array{
19201945
a: int,
19211946
b: string
19221947
}',
1923-
1,
1924-
4,
1925-
0,
1926-
15,
1948+
[
1949+
[
1950+
static function (TypeNode $typeNode): TypeNode {
1951+
return $typeNode;
1952+
},
1953+
1,
1954+
4,
1955+
0,
1956+
15,
1957+
],
1958+
],
19271959
];
19281960
}
19291961

19301962
/**
19311963
* @dataProvider dataLinesAndIndexes
1964+
* @param list<array{callable(TypeNode): TypeNode, int, int, int, int}> $assertions
19321965
*/
1933-
public function testLinesAndIndexes(string $input, int $startLine, int $endLine, int $startIndex, int $endIndex): void
1966+
public function testLinesAndIndexes(string $input, array $assertions): void
19341967
{
19351968
$tokens = new TokenIterator($this->lexer->tokenize($input));
19361969
$typeParser = new TypeParser(new ConstExprParser(true, true), true, [
19371970
'lines' => true,
19381971
'indexes' => true,
19391972
]);
19401973
$typeNode = $typeParser->parse($tokens);
1941-
$this->assertSame($startLine, $typeNode->getAttribute(Attribute::START_LINE));
1942-
$this->assertSame($endLine, $typeNode->getAttribute(Attribute::END_LINE));
1943-
$this->assertSame($startIndex, $typeNode->getAttribute(Attribute::START_INDEX));
1944-
$this->assertSame($endIndex, $typeNode->getAttribute(Attribute::END_INDEX));
1974+
1975+
foreach ($assertions as [$callable, $startLine, $endLine, $startIndex, $endIndex]) {
1976+
$typeToAssert = $callable($typeNode);
1977+
$this->assertSame($startLine, $typeToAssert->getAttribute(Attribute::START_LINE));
1978+
$this->assertSame($endLine, $typeToAssert->getAttribute(Attribute::END_LINE));
1979+
$this->assertSame($startIndex, $typeToAssert->getAttribute(Attribute::START_INDEX));
1980+
$this->assertSame($endIndex, $typeToAssert->getAttribute(Attribute::END_INDEX));
1981+
}
19451982
}
19461983

19471984
}

0 commit comments

Comments
 (0)