From 46cbd9393a28a0e2f7488257779b7f46c39db1f5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 9 Feb 2020 17:10:33 +0100 Subject: [PATCH] Place Nop nodes more precisely If the Nop is created to collect comments, place it directly after the comment, instead of at the next non-whitespace character. --- grammar/rebuildParsers.php | 2 +- lib/PhpParser/Parser/Php5.php | 6 ++-- lib/PhpParser/Parser/Php7.php | 6 ++-- lib/PhpParser/ParserAbstract.php | 28 ++++++++++++------- .../formatPreservation/classMethodNop.test | 21 +++++++++++++- test/code/parser/nopPositions.test | 14 ++++++++++ 6 files changed, 59 insertions(+), 18 deletions(-) diff --git a/grammar/rebuildParsers.php b/grammar/rebuildParsers.php index c36699c..66bf705 100644 --- a/grammar/rebuildParsers.php +++ b/grammar/rebuildParsers.php @@ -178,7 +178,7 @@ function resolveMacros($code) { return '$startAttributes = ' . $args[1] . ';' . ' if (isset($startAttributes[\'comments\']))' - . ' { ' . $args[0] . ' = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); }' + . ' { ' . $args[0] . ' = new Stmt\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }' . ' else { ' . $args[0] . ' = null; }'; } diff --git a/lib/PhpParser/Parser/Php5.php b/lib/PhpParser/Parser/Php5.php index a558d28..397e605 100644 --- a/lib/PhpParser/Parser/Php5.php +++ b/lib/PhpParser/Parser/Php5.php @@ -944,7 +944,7 @@ class Php5 extends \PhpParser\ParserAbstract $this->semValue = array(); }, 4 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); } else { $nop = null; }; + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 5 => function ($stackPos) { @@ -1317,7 +1317,7 @@ class Php5 extends \PhpParser\ParserAbstract $this->semValue = array(); }, 126 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); } else { $nop = null; }; + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 127 => function ($stackPos) { @@ -1715,7 +1715,7 @@ class Php5 extends \PhpParser\ParserAbstract $this->semValue = array(); }, 255 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); } else { $nop = null; }; + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 256 => function ($stackPos) { diff --git a/lib/PhpParser/Parser/Php7.php b/lib/PhpParser/Parser/Php7.php index f250ede..fda56f4 100644 --- a/lib/PhpParser/Parser/Php7.php +++ b/lib/PhpParser/Parser/Php7.php @@ -876,7 +876,7 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = array(); }, 4 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); } else { $nop = null; }; + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 5 => function ($stackPos) { @@ -1282,7 +1282,7 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = array(); }, 137 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); } else { $nop = null; }; + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 138 => function ($stackPos) { @@ -1710,7 +1710,7 @@ class Php7 extends \PhpParser\ParserAbstract $this->semValue = array(); }, 276 => function ($stackPos) { - $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createZeroLengthAttributes($startAttributes)); } else { $nop = null; }; + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments'])); } else { $nop = null; }; if ($nop !== null) { $this->semStack[$stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$stackPos-(1-1)]; }, 277 => function ($stackPos) { diff --git a/lib/PhpParser/ParserAbstract.php b/lib/PhpParser/ParserAbstract.php index 4d968cd..80dc560 100644 --- a/lib/PhpParser/ParserAbstract.php +++ b/lib/PhpParser/ParserAbstract.php @@ -842,21 +842,29 @@ abstract class ParserAbstract implements Parser } /** - * Create attributes for a zero-length node with the given start attributes. + * Create attributes for a zero-length common-capturing nop. * - * @param array $startAttributes + * @param Comment[] $comments * @return array */ - protected function createZeroLengthAttributes(array $startAttributes) { - $attributes = $startAttributes; - if (isset($startAttributes['startLine'])) { - $attributes['endLine'] = $startAttributes['startLine']; + protected function createCommentNopAttributes(array $comments) { + $comment = $comments[count($comments) - 1]; + $commentEndLine = $comment->getEndLine(); + $commentEndFilePos = $comment->getEndFilePos(); + $commentEndTokenPos = $comment->getEndTokenPos(); + + $attributes = ['comments' => $comments]; + if (-1 !== $commentEndLine) { + $attributes['startLine'] = $commentEndLine; + $attributes['endLine'] = $commentEndLine; } - if (isset($startAttributes['startTokenPos'])) { - $attributes['endTokenPos'] = $startAttributes['startTokenPos'] - 1; + if (-1 !== $commentEndFilePos) { + $attributes['startFilePos'] = $commentEndFilePos + 1; + $attributes['endFilePos'] = $commentEndFilePos; } - if (isset($startAttributes['startFilePos'])) { - $attributes['endFilePos'] = $startAttributes['startFilePos'] - 1; + if (-1 !== $commentEndTokenPos) { + $attributes['startTokenPos'] = $commentEndTokenPos + 1; + $attributes['endTokenPos'] = $commentEndTokenPos; } return $attributes; } diff --git a/test/code/formatPreservation/classMethodNop.test b/test/code/formatPreservation/classMethodNop.test index 32facb6..00b8e2a 100644 --- a/test/code/formatPreservation/classMethodNop.test +++ b/test/code/formatPreservation/classMethodNop.test @@ -16,5 +16,24 @@ class Foo { { // I'm just a comment - $foo;} + $foo; } +} +----- +stmts[0]->stmts[] = new Stmt\Expression(new Node\Expr\Variable('foo')); +----- +