From 3d58c713287a7c70686288e0d6bcf4ff7120725a Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 16 Dec 2021 05:38:35 +0100 Subject: [PATCH] Node: added $startLine & $endLine --- src/Neon/Node.php | 6 ++ src/Neon/Parser.php | 21 ++++- tests/Neon/fixtures/Encoder.nodes.txt | 106 ++++++++++++++++++++++++++ tests/Neon/fixtures/Parser.nodes.txt | 92 ++++++++++++++++++++++ 4 files changed, 224 insertions(+), 1 deletion(-) diff --git a/src/Neon/Node.php b/src/Neon/Node.php index b047a8c3..71f10f3e 100644 --- a/src/Neon/Node.php +++ b/src/Neon/Node.php @@ -19,6 +19,12 @@ abstract class Node /** @var ?int */ public $endPos; + /** @var ?int */ + public $startLine; + + /** @var ?int */ + public $endLine; + /** @return mixed */ abstract public function toValue(); diff --git a/src/Neon/Parser.php b/src/Neon/Parser.php index d4aa7e37..60602ed8 100644 --- a/src/Neon/Parser.php +++ b/src/Neon/Parser.php @@ -16,10 +16,15 @@ final class Parser /** @var TokenStream */ private $tokens; + /** @var int[] */ + private $posToLine = []; + public function parse(TokenStream $tokens): Node { $this->tokens = $tokens; + $this->initLines(); + while ($this->tokens->consume(Token::NEWLINE)); $node = $this->parseBlock($this->tokens->getIndentation()); @@ -234,7 +239,8 @@ private function checkArrayKey(Node $key, array &$arr): void private function setPos(Node $node, int $startPos = null, int $endPos = null): Node { $node->startPos = $startPos ?? $this->tokens->getPos(); - $node->endPos = $endPos ?? $node->startPos; + $node->startLine = $this->posToLine[$node->startPos] ?? end($this->posToLine); + $this->setEndPos($node, $endPos ?? $node->startPos); return $node; } @@ -242,5 +248,18 @@ private function setPos(Node $node, int $startPos = null, int $endPos = null): N private function setEndPos(Node $node, int $endPos): void { $node->endPos = $endPos; + $node->endLine = $this->posToLine[$node->endPos + 1] ?? end($this->posToLine); + } + + + private function initLines(): void + { + $this->posToLine = []; + $line = 1; + foreach ($this->tokens->getTokens() as $token) { + $this->posToLine[] = $line; + $line += substr_count($token->value, "\n"); + } + $this->posToLine[] = $line; } } diff --git a/tests/Neon/fixtures/Encoder.nodes.txt b/tests/Neon/fixtures/Encoder.nodes.txt index 51492b65..ebca6639 100644 --- a/tests/Neon/fixtures/Encoder.nodes.txt +++ b/tests/Neon/fixtures/Encoder.nodes.txt @@ -6,6 +6,8 @@ Nette\Neon\Node\InlineArrayNode | | | value: 'map' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\InlineArrayNode | | | bracket: '{' | | | items: array (2) @@ -14,32 +16,50 @@ Nette\Neon\Node\InlineArrayNode | | | | | | value: 'a' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'b' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | key: Nette\Neon\Node\LiteralNode | | | | | | value: 'c' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'd' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null | 1 => Nette\Neon\Node\ArrayItemNode | | key: Nette\Neon\Node\LiteralNode | | | value: 'index' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\InlineArrayNode | | | bracket: '[' | | | items: array (3) @@ -49,33 +69,51 @@ Nette\Neon\Node\InlineArrayNode | | | | | | value: 'a' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | key: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'b' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 2 => Nette\Neon\Node\ArrayItemNode | | | | | key: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'c' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null | 2 => Nette\Neon\Node\ArrayItemNode | | key: Nette\Neon\Node\LiteralNode | | | value: 'mixed' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\InlineArrayNode | | | bracket: '{' | | | items: array (4) @@ -85,52 +123,80 @@ Nette\Neon\Node\InlineArrayNode | | | | | | value: 'a' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | key: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'b' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 2 => Nette\Neon\Node\ArrayItemNode | | | | | key: Nette\Neon\Node\LiteralNode | | | | | | value: 4 | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'c' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 3 => Nette\Neon\Node\ArrayItemNode | | | | | key: Nette\Neon\Node\LiteralNode | | | | | | value: 5 | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'd' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null | 3 => Nette\Neon\Node\ArrayItemNode | | key: Nette\Neon\Node\LiteralNode | | | value: 'entity' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\EntityNode | | | value: Nette\Neon\Node\LiteralNode | | | | value: 'ent' | | | | startPos: null | | | | endPos: null + | | | | startLine: null + | | | | endLine: null | | | attributes: array (2) | | | | 0 => Nette\Neon\Node\ArrayItemNode | | | | | key: null @@ -138,25 +204,39 @@ Nette\Neon\Node\InlineArrayNode | | | | | | value: 'a' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | key: null | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'b' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null | 4 => Nette\Neon\Node\ArrayItemNode | | key: Nette\Neon\Node\LiteralNode | | | value: 'chain' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\EntityChainNode | | | chain: array (2) | | | | 0 => Nette\Neon\Node\EntityNode @@ -164,41 +244,61 @@ Nette\Neon\Node\InlineArrayNode | | | | | | value: 'first' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | attributes: array (2) | | | | | | 0 => Nette\Neon\Node\ArrayItemNode ... | | | | | | 1 => Nette\Neon\Node\ArrayItemNode ... | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | | 1 => Nette\Neon\Node\EntityNode | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | value: 'second' | | | | | | startPos: null | | | | | | endPos: null + | | | | | | startLine: null + | | | | | | endLine: null | | | | | attributes: array (0) | | | | | startPos: null | | | | | endPos: null + | | | | | startLine: null + | | | | | endLine: null | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null | 5 => Nette\Neon\Node\ArrayItemNode | | key: Nette\Neon\Node\LiteralNode | | | value: 'multiline' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\StringNode | | | value: string | | | | 'hello\n | | | | world' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null | 6 => Nette\Neon\Node\ArrayItemNode | | key: Nette\Neon\Node\LiteralNode | | | value: 'date' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | value: Nette\Neon\Node\LiteralNode | | | value: DateTime | | | | date: '2016-06-03 19:00:00.000000' @@ -206,7 +306,13 @@ Nette\Neon\Node\InlineArrayNode | | | | timezone: '+02:00' | | | startPos: null | | | endPos: null + | | | startLine: null + | | | endLine: null | | startPos: null | | endPos: null + | | startLine: null + | | endLine: null startPos: null endPos: null + startLine: null + endLine: null diff --git a/tests/Neon/fixtures/Parser.nodes.txt b/tests/Neon/fixtures/Parser.nodes.txt index c753a3ba..9d677c62 100644 --- a/tests/Neon/fixtures/Parser.nodes.txt +++ b/tests/Neon/fixtures/Parser.nodes.txt @@ -27,6 +27,8 @@ Nette\Neon\Node\BlockArrayNode | | | value: 'first' | | | startPos: unset | | | endPos: unset + | | | startLine: 3 + | | | endLine: 3 | | value: Nette\Neon\Node\BlockArrayNode | | | code: '- a' | | | indentation: '\t ' @@ -39,12 +41,20 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'a' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 5 + | | | | | | endLine: 5 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 5 + | | | | | endLine: 5 | | | startPos: unset | | | endPos: unset + | | | startLine: 5 + | | | endLine: 5 | | startPos: unset | | endPos: unset + | | startLine: 3 + | | endLine: 5 | 1 => Nette\Neon\Node\ArrayItemNode | | code: string | | | 'next:\n @@ -56,6 +66,8 @@ Nette\Neon\Node\BlockArrayNode | | | value: 'next' | | | startPos: unset | | | endPos: unset + | | | startLine: 6 + | | | endLine: 6 | | value: Nette\Neon\Node\BlockArrayNode | | | code: string | | | | '- [k,\n @@ -78,12 +90,20 @@ Nette\Neon\Node\BlockArrayNode | | | | | | items: array (4) ... | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 7 + | | | | | | endLine: 9 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 7 + | | | | | endLine: 9 | | | startPos: unset | | | endPos: unset + | | | startLine: 7 + | | | endLine: 9 | | startPos: unset | | endPos: unset + | | startLine: 6 + | | endLine: 9 | 2 => Nette\Neon\Node\ArrayItemNode | | code: string | | | 'second:\n @@ -95,6 +115,8 @@ Nette\Neon\Node\BlockArrayNode | | | value: 'second' | | | startPos: unset | | | endPos: unset + | | | startLine: 10 + | | | endLine: 10 | | value: Nette\Neon\Node\BlockArrayNode | | | code: string | | | | 'sub:\n @@ -112,6 +134,8 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'sub' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 11 + | | | | | | endLine: 11 | | | | | value: Nette\Neon\Node\BlockArrayNode | | | | | | code: string | | | | | | | 'a: 1\n @@ -120,12 +144,20 @@ Nette\Neon\Node\BlockArrayNode | | | | | | items: array (2) ... | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 12 + | | | | | | endLine: 13 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 11 + | | | | | endLine: 13 | | | startPos: unset | | | endPos: unset + | | | startLine: 11 + | | | endLine: 13 | | startPos: unset | | endPos: unset + | | startLine: 10 + | | endLine: 13 | 3 => Nette\Neon\Node\ArrayItemNode | | code: string | | | 'third:\n @@ -136,6 +168,8 @@ Nette\Neon\Node\BlockArrayNode | | | value: 'third' | | | startPos: unset | | | endPos: unset + | | | startLine: 14 + | | | endLine: 14 | | value: Nette\Neon\Node\BlockArrayNode | | | code: string | | | | '- entity(a: 1)\n @@ -151,8 +185,12 @@ Nette\Neon\Node\BlockArrayNode | | | | | | attributes: array (1) ... | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 15 + | | | | | | endLine: 15 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 15 + | | | | | endLine: 15 | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | code: '- entity(a: 1)foo()bar' | | | | | key: null @@ -161,12 +199,20 @@ Nette\Neon\Node\BlockArrayNode | | | | | | chain: array (3) ... | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 16 + | | | | | | endLine: 16 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 16 + | | | | | endLine: 16 | | | startPos: unset | | | endPos: unset + | | | startLine: 15 + | | | endLine: 16 | | startPos: unset | | endPos: unset + | | startLine: 14 + | | endLine: 16 | 4 => Nette\Neon\Node\ArrayItemNode | | code: string | | | '- a: 1\n @@ -185,13 +231,19 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'a' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 17 + | | | | | | endLine: 17 | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | code: '1' | | | | | | value: 1 | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 17 + | | | | | | endLine: 17 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 17 + | | | | | endLine: 17 | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | code: 'b: 2' | | | | | key: Nette\Neon\Node\LiteralNode @@ -199,17 +251,27 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'b' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 18 + | | | | | | endLine: 18 | | | | | value: Nette\Neon\Node\LiteralNode | | | | | | code: '2' | | | | | | value: 2 | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 18 + | | | | | | endLine: 18 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 18 + | | | | | endLine: 18 | | | startPos: unset | | | endPos: unset + | | | startLine: 17 + | | | endLine: 18 | | startPos: unset | | endPos: unset + | | startLine: 17 + | | endLine: 18 | 5 => Nette\Neon\Node\ArrayItemNode | | code: '- - c' | | key: null @@ -225,12 +287,20 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'c' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 19 + | | | | | | endLine: 19 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 19 + | | | | | endLine: 19 | | | startPos: unset | | | endPos: unset + | | | startLine: 19 + | | | endLine: 19 | | startPos: unset | | endPos: unset + | | startLine: 19 + | | endLine: 19 | 6 => Nette\Neon\Node\ArrayItemNode | | code: string | | | 'dash subblock:\n @@ -241,6 +311,8 @@ Nette\Neon\Node\BlockArrayNode | | | value: 'dash subblock' | | | startPos: unset | | | endPos: unset + | | | startLine: 20 + | | | endLine: 20 | | value: Nette\Neon\Node\BlockArrayNode | | | code: string | | | | '- a\n @@ -255,8 +327,12 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'a' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 21 + | | | | | | endLine: 21 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 21 + | | | | | endLine: 21 | | | | 1 => Nette\Neon\Node\ArrayItemNode | | | | | code: '- b' | | | | | key: null @@ -265,12 +341,20 @@ Nette\Neon\Node\BlockArrayNode | | | | | | value: 'b' | | | | | | startPos: unset | | | | | | endPos: unset + | | | | | | startLine: 22 + | | | | | | endLine: 22 | | | | | startPos: unset | | | | | endPos: unset + | | | | | startLine: 22 + | | | | | endLine: 22 | | | startPos: unset | | | endPos: unset + | | | startLine: 21 + | | | endLine: 22 | | startPos: unset | | endPos: unset + | | startLine: 20 + | | endLine: 22 | 7 => Nette\Neon\Node\ArrayItemNode | | code: string | | | 'text: """\n @@ -282,6 +366,8 @@ Nette\Neon\Node\BlockArrayNode | | | value: 'text' | | | startPos: unset | | | endPos: unset + | | | startLine: 23 + | | | endLine: 23 | | value: Nette\Neon\Node\StringNode | | | code: string | | | | '"""\n @@ -293,7 +379,13 @@ Nette\Neon\Node\BlockArrayNode | | | | two' | | | startPos: unset | | | endPos: unset + | | | startLine: 23 + | | | endLine: 26 | | startPos: unset | | endPos: unset + | | startLine: 23 + | | endLine: 26 startPos: unset endPos: unset + startLine: 3 + endLine: 26