Skip to content

Commit 912c963

Browse files
committed
Track line number for each token
1 parent f216273 commit 912c963

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
}
2929
},
3030
"scripts": {
31-
"analyze": "phpstan analyze src --level 10",
31+
"analyze": "phpstan analyze --level 10 src test",
3232
"test": "vendor/bin/phpunit test"
3333
},
3434
"config": {

src/Phlexer/Phlexer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ public function getNextToken(): ?Token
4949
return null;
5050
}
5151

52+
$line = substr_count($this->text, "\n", 0, $this->cursor + 1) + 1;
5253
$subject = substr($this->text, $this->cursor);
5354

5455
foreach ($this->rules as $rule) {
@@ -66,7 +67,7 @@ public function getNextToken(): ?Token
6667
return $this->getNextToken();
6768
}
6869

69-
return new Token($tokenName, $this->yytext);
70+
return new Token($tokenName, $this->yytext, $line);
7071
}
7172
}
7273

src/Phlexer/Token.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
public function __construct(
88
public string $name,
99
public string $text,
10+
public int $line,
1011
) {}
1112
}

test/LexerTest.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,32 @@
77
use PHPUnit\Framework\Attributes\DataProvider;
88
use PHPUnit\Framework\TestCase;
99

10+
/**
11+
* @phpstan-type SpecToken array{name: string, text: string}
12+
* @phpstan-type SpecArr array{it: string, template: string, expected: list<SpecToken>}
13+
*/
1014
class LexerTest extends TestCase
1115
{
16+
/**
17+
* @return list<array{0: SpecArr}>
18+
*/
1219
public static function jsonSpecProvider(): array
1320
{
1421
$filename = 'vendor/jbboehr/handlebars-spec/spec/tokenizer.json';
15-
$json = json_decode(file_get_contents($filename), true);
22+
$contents = file_get_contents($filename);
23+
24+
if ($contents === false) {
25+
throw new \Exception("Failed to read file {$filename}");
26+
}
27+
28+
/** @var list<SpecArr> $json */
29+
$json = json_decode($contents, true);
1630
return array_map(fn(array $d): array => [$d], $json);
1731
}
1832

33+
/**
34+
* @param SpecArr $spec
35+
*/
1936
#[DataProvider("jsonSpecProvider")]
2037
public function testSpecs(array $spec): void
2138
{
@@ -32,4 +49,25 @@ public function testSpecs(array $spec): void
3249
$actual = array_map($toJson, $lexer->tokenize($spec['template']));
3350
$this->assertSame($spec['expected'], $actual);
3451
}
52+
53+
public function testLineNumbers(): void
54+
{
55+
$template = <<<_tpl
56+
This
57+
is a {{template}}
58+
with multiple
59+
{{lines}}
60+
_tpl;
61+
$expected = [
62+
new Token('CONTENT', "This\nis a ", 1),
63+
new Token('OPEN', '{{', 2),
64+
new Token('ID', 'template', 2),
65+
new Token('CLOSE', '}}', 2),
66+
new Token('CONTENT', "\nwith multiple\n", 3),
67+
new Token('OPEN', '{{', 4),
68+
new Token('ID', 'lines', 4),
69+
new Token('CLOSE', '}}', 4),
70+
];
71+
$this->assertEquals($expected, (new Lexer())->tokenize($template));
72+
}
3573
}

0 commit comments

Comments
 (0)