From 47c973b3aad6e8be86a2d6117e8823e5c3f7ef3e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 4 Nov 2017 17:45:14 +0100 Subject: [PATCH] Store start token position in comments --- lib/PhpParser/Comment.php | 23 +++++++++++++++++++---- lib/PhpParser/JsonDecoder.php | 4 +++- lib/PhpParser/Lexer.php | 4 ++-- test/PhpParser/CommentTest.php | 3 ++- test/PhpParser/LexerTest.php | 10 +++++----- test/PhpParser/NodeAbstractTest.php | 6 ++++-- test/PhpParser/ParserTest.php | 6 +++--- 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/lib/PhpParser/Comment.php b/lib/PhpParser/Comment.php index 6a1f47b..1a287b6 100644 --- a/lib/PhpParser/Comment.php +++ b/lib/PhpParser/Comment.php @@ -7,18 +7,23 @@ class Comment implements \JsonSerializable protected $text; protected $line; protected $filePos; + protected $tokenPos; /** * Constructs a comment node. * - * @param string $text Comment text (including comment delimiters like /*) - * @param int $startLine Line number the comment started on - * @param int $startFilePos File offset the comment started on + * @param string $text Comment text (including comment delimiters like /*) + * @param int $startLine Line number the comment started on + * @param int $startFilePos File offset the comment started on + * @param int $startTokenPos Token offset the comment started on */ - public function __construct(string $text, int $startLine = -1, int $startFilePos = -1) { + public function __construct( + string $text, int $startLine = -1, int $startFilePos = -1, int $startTokenPos = -1 + ) { $this->text = $text; $this->line = $startLine; $this->filePos = $startFilePos; + $this->tokenPos = $startTokenPos; } /** @@ -48,6 +53,15 @@ class Comment implements \JsonSerializable return $this->filePos; } + /** + * Gets the token offset the comment started on. + * + * @return int Token offset + */ + public function getTokenPos() : int { + return $this->tokenPos; + } + /** * Gets the comment text. * @@ -147,6 +161,7 @@ class Comment implements \JsonSerializable 'text' => $this->text, 'line' => $this->line, 'filePos' => $this->filePos, + 'tokenPos' => $this->tokenPos, ]; } } \ No newline at end of file diff --git a/lib/PhpParser/JsonDecoder.php b/lib/PhpParser/JsonDecoder.php index 832ac25..8b662c9 100644 --- a/lib/PhpParser/JsonDecoder.php +++ b/lib/PhpParser/JsonDecoder.php @@ -71,7 +71,9 @@ class JsonDecoder { throw new \RuntimeException('Comment must have text'); } - return new $className($value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1); + return new $className( + $value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1 + ); } private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass { diff --git a/lib/PhpParser/Lexer.php b/lib/PhpParser/Lexer.php index f6c1884..aa7ff8a 100644 --- a/lib/PhpParser/Lexer.php +++ b/lib/PhpParser/Lexer.php @@ -265,8 +265,8 @@ class Lexer if (T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0]) { if (isset($this->usedAttributes['comments'])) { $comment = T_DOC_COMMENT === $token[0] - ? new Comment\Doc($token[1], $this->line, $this->filePos) - : new Comment($token[1], $this->line, $this->filePos); + ? new Comment\Doc($token[1], $this->line, $this->filePos, $this->pos) + : new Comment($token[1], $this->line, $this->filePos, $this->pos); $startAttributes['comments'][] = $comment; } } diff --git a/test/PhpParser/CommentTest.php b/test/PhpParser/CommentTest.php index a49dec7..7b6c2aa 100644 --- a/test/PhpParser/CommentTest.php +++ b/test/PhpParser/CommentTest.php @@ -7,12 +7,13 @@ use PHPUnit\Framework\TestCase; class CommentTest extends TestCase { public function testGetSet() { - $comment = new Comment('/* Some comment */', 1, 10); + $comment = new Comment('/* Some comment */', 1, 10, 2); $this->assertSame('/* Some comment */', $comment->getText()); $this->assertSame('/* Some comment */', (string) $comment); $this->assertSame(1, $comment->getLine()); $this->assertSame(10, $comment->getFilePos()); + $this->assertSame(2, $comment->getTokenPos()); } /** diff --git a/test/PhpParser/LexerTest.php b/test/PhpParser/LexerTest.php index 8bf7bd5..7cdf5b9 100644 --- a/test/PhpParser/LexerTest.php +++ b/test/PhpParser/LexerTest.php @@ -104,7 +104,7 @@ class LexerTest extends TestCase [ 'startLine' => 3, 'comments' => [ - new Comment\Doc('/** doc' . "\n" . 'comment */', 2, 14), + new Comment\Doc('/** doc' . "\n" . 'comment */', 2, 14, 5), ] ], ['endLine' => 3] @@ -121,10 +121,10 @@ class LexerTest extends TestCase [ 'startLine' => 2, 'comments' => [ - new Comment('/* comment */', 1, 6), - new Comment('// comment' . "\n", 1, 20), - new Comment\Doc('/** docComment 1 */', 2, 31), - new Comment\Doc('/** docComment 2 */', 2, 50), + new Comment('/* comment */', 1, 6, 1), + new Comment('// comment' . "\n", 1, 20, 3), + new Comment\Doc('/** docComment 1 */', 2, 31, 4), + new Comment\Doc('/** docComment 2 */', 2, 50, 5), ], ], ['endLine' => 2] diff --git a/test/PhpParser/NodeAbstractTest.php b/test/PhpParser/NodeAbstractTest.php index 9a93812..cb6fa49 100644 --- a/test/PhpParser/NodeAbstractTest.php +++ b/test/PhpParser/NodeAbstractTest.php @@ -301,13 +301,15 @@ PHP; "nodeType": "Comment", "text": "\/\/ comment\n", "line": 2, - "filePos": 6 + "filePos": 6, + "tokenPos": 1 }, { "nodeType": "Comment_Doc", "text": "\/** doc comment *\/", "line": 3, - "filePos": 17 + "filePos": 17, + "tokenPos": 2 } ], "endLine": 6 diff --git a/test/PhpParser/ParserTest.php b/test/PhpParser/ParserTest.php index 54866b2..d4d7fae 100644 --- a/test/PhpParser/ParserTest.php +++ b/test/PhpParser/ParserTest.php @@ -66,7 +66,7 @@ EOC; $this->assertInstanceOf('PhpParser\Node\Stmt\Function_', $fn); $this->assertEquals([ 'comments' => [ - new Comment\Doc('/** Doc comment */', 2, 6), + new Comment\Doc('/** Doc comment */', 2, 6, 1), ], 'startLine' => 3, 'endLine' => 7, @@ -88,8 +88,8 @@ EOC; $this->assertInstanceOf('PhpParser\Node\Stmt\Echo_', $echo); $this->assertEquals([ 'comments' => [ - new Comment("// Line\n", 4, 49), - new Comment("// Comments\n", 5, 61), + new Comment("// Line\n", 4, 49, 12), + new Comment("// Comments\n", 5, 61, 14), ], 'startLine' => 6, 'endLine' => 6,