FPPP: Support removing nodes from start of list

This commit is contained in:
Nikita Popov 2020-08-23 17:33:02 +02:00
parent 56356e4aec
commit bd722809f7
4 changed files with 106 additions and 12 deletions

View File

@ -33,7 +33,7 @@ class TokenStream
* @return bool
*/
public function haveParens(int $startPos, int $endPos) : bool {
return $this->haveTokenImmediativelyBefore($startPos, '(')
return $this->haveTokenImmediatelyBefore($startPos, '(')
&& $this->haveTokenImmediatelyAfter($endPos, ')');
}
@ -46,7 +46,7 @@ class TokenStream
* @return bool
*/
public function haveBraces(int $startPos, int $endPos) : bool {
return $this->haveTokenImmediativelyBefore($startPos, '{')
return $this->haveTokenImmediatelyBefore($startPos, '{')
&& $this->haveTokenImmediatelyAfter($endPos, '}');
}
@ -60,7 +60,7 @@ class TokenStream
*
* @return bool Whether the expected token was found
*/
public function haveTokenImmediativelyBefore(int $pos, $expectedTokenType) : bool {
public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool {
$tokens = $this->tokens;
$pos--;
for (; $pos >= 0; $pos--) {

View File

@ -706,6 +706,7 @@ abstract class PrettyPrinterAbstract
$insertStr = $this->listInsertionMap[$mapKey] ?? null;
$beforeFirstKeepOrReplace = true;
$skipRemovedNode = false;
$delayedAdd = [];
$lastElemIndentLevel = $this->indentLevel;
@ -797,7 +798,7 @@ abstract class PrettyPrinterAbstract
$commentStartPos, $itemStartPos, $indentAdjustment);
$delayedAdd = [];
} else {
} else if (!$skipRemovedNode) {
$result .= $this->origTokens->getTokenCode(
$pos, $itemStartPos, $indentAdjustment);
}
@ -806,6 +807,9 @@ abstract class PrettyPrinterAbstract
// Add new comments
$result .= $this->pComments($comments) . $this->nl;
}
// If we had to remove anything, we have done so now.
$skipRemovedNode = false;
} elseif ($diffType === DiffElem::TYPE_ADD) {
if (null === $insertStr) {
// We don't have insertion information for this list type
@ -839,18 +843,42 @@ abstract class PrettyPrinterAbstract
$result .= $insertStr;
}
} elseif ($diffType === DiffElem::TYPE_REMOVE) {
if ($i === 0) {
// TODO Handle removal at the start
return null;
}
if (!$origArrItem instanceof Node) {
// We only support removal for nodes
return null;
}
$itemStartPos = $origArrItem->getStartTokenPos();
$itemEndPos = $origArrItem->getEndTokenPos();
\assert($itemEndPos >= 0);
\assert($itemStartPos >= 0 && $itemEndPos >= 0);
// Consider comments part of the node.
$origComments = $origArrItem->getComments();
if ($origComments) {
$itemStartPos = $origComments[0]->getStartTokenPos();
}
if ($i === 0) {
// If we're removing from the start, keep the tokens before the node and drop those after it,
// instead of the other way around.
$result .= $this->origTokens->getTokenCode(
$pos, $itemStartPos, $indentAdjustment);
$skipRemovedNode = true;
if ($this->origTokens->haveTokenImmediatelyAfter($itemEndPos, '{')
|| $this->origTokens->haveTokenImmediatelyAfter($itemEndPos, '}')) {
// We'd remove the brace of a code block.
// TODO: Preserve formatting.
return null;
}
} else {
if ($this->origTokens->haveTokenImmediatelyBefore($itemStartPos, '{')
|| $this->origTokens->haveTokenImmediatelyBefore($itemStartPos, '}')) {
// We'd remove the brace of a code block.
// TODO: Preserve formatting.
return null;
}
}
$pos = $itemEndPos + 1;
continue;
@ -869,6 +897,11 @@ abstract class PrettyPrinterAbstract
$pos = $itemEndPos + 1;
}
if ($skipRemovedNode) {
// TODO: Support removing single node.
return null;
}
if (!empty($delayedAdd)) {
if (!isset($this->emptyListInsertionMap[$mapKey])) {
return null;

View File

@ -106,7 +106,6 @@ $stmts[2] = $tmp;
array_splice($stmts, 0, 1, []);
-----
<?php
function test() {
call2(
$foo

View File

@ -49,4 +49,66 @@ array_pop($stmts[0]->returnType->types);
-----
<?php
function test(): A
|B {}
|B {}
-----
<?php $a; $b; $c;
-----
array_splice($stmts, 0, 1, []);
-----
<?php $b; $c;
-----
<?php $a; $b; $c;
-----
array_splice($stmts, 0, 2, []);
-----
<?php $c;
-----
<?php
{ $x; }
$y;
-----
array_splice($stmts, 0, 1, []);
-----
<?php
$y;
-----
<?php
$x;
{ $y; }
-----
array_splice($stmts, 0, 1, []);
-----
<?php
$y;
-----
<?php
$x;
{ $y; }
-----
array_pop($stmts);
-----
<?php
$x;
-----
<?php
{ $x; }
$y;
-----
array_pop($stmts);
-----
<?php
$x;
-----
<?php
// Foo
$x;
$y;
-----
array_splice($stmts, 0, 1, []);
-----
<?php
$y;