Skip to content

Commit bd72280

Browse files
committed
FPPP: Support removing nodes from start of list
1 parent 56356e4 commit bd72280

File tree

4 files changed

+106
-12
lines changed

4 files changed

+106
-12
lines changed

lib/PhpParser/Internal/TokenStream.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function __construct(array $tokens) {
3333
* @return bool
3434
*/
3535
public function haveParens(int $startPos, int $endPos) : bool {
36-
return $this->haveTokenImmediativelyBefore($startPos, '(')
36+
return $this->haveTokenImmediatelyBefore($startPos, '(')
3737
&& $this->haveTokenImmediatelyAfter($endPos, ')');
3838
}
3939

@@ -46,7 +46,7 @@ public function haveParens(int $startPos, int $endPos) : bool {
4646
* @return bool
4747
*/
4848
public function haveBraces(int $startPos, int $endPos) : bool {
49-
return $this->haveTokenImmediativelyBefore($startPos, '{')
49+
return $this->haveTokenImmediatelyBefore($startPos, '{')
5050
&& $this->haveTokenImmediatelyAfter($endPos, '}');
5151
}
5252

@@ -60,7 +60,7 @@ public function haveBraces(int $startPos, int $endPos) : bool {
6060
*
6161
* @return bool Whether the expected token was found
6262
*/
63-
public function haveTokenImmediativelyBefore(int $pos, $expectedTokenType) : bool {
63+
public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool {
6464
$tokens = $this->tokens;
6565
$pos--;
6666
for (; $pos >= 0; $pos--) {

lib/PhpParser/PrettyPrinterAbstract.php

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ protected function pArray(
706706
$insertStr = $this->listInsertionMap[$mapKey] ?? null;
707707

708708
$beforeFirstKeepOrReplace = true;
709+
$skipRemovedNode = false;
709710
$delayedAdd = [];
710711
$lastElemIndentLevel = $this->indentLevel;
711712

@@ -797,7 +798,7 @@ protected function pArray(
797798
$commentStartPos, $itemStartPos, $indentAdjustment);
798799

799800
$delayedAdd = [];
800-
} else {
801+
} else if (!$skipRemovedNode) {
801802
$result .= $this->origTokens->getTokenCode(
802803
$pos, $itemStartPos, $indentAdjustment);
803804
}
@@ -806,6 +807,9 @@ protected function pArray(
806807
// Add new comments
807808
$result .= $this->pComments($comments) . $this->nl;
808809
}
810+
811+
// If we had to remove anything, we have done so now.
812+
$skipRemovedNode = false;
809813
} elseif ($diffType === DiffElem::TYPE_ADD) {
810814
if (null === $insertStr) {
811815
// We don't have insertion information for this list type
@@ -839,18 +843,42 @@ protected function pArray(
839843
$result .= $insertStr;
840844
}
841845
} elseif ($diffType === DiffElem::TYPE_REMOVE) {
842-
if ($i === 0) {
843-
// TODO Handle removal at the start
844-
return null;
845-
}
846-
847846
if (!$origArrItem instanceof Node) {
848847
// We only support removal for nodes
849848
return null;
850849
}
851850

851+
$itemStartPos = $origArrItem->getStartTokenPos();
852852
$itemEndPos = $origArrItem->getEndTokenPos();
853-
\assert($itemEndPos >= 0);
853+
\assert($itemStartPos >= 0 && $itemEndPos >= 0);
854+
855+
// Consider comments part of the node.
856+
$origComments = $origArrItem->getComments();
857+
if ($origComments) {
858+
$itemStartPos = $origComments[0]->getStartTokenPos();
859+
}
860+
861+
if ($i === 0) {
862+
// If we're removing from the start, keep the tokens before the node and drop those after it,
863+
// instead of the other way around.
864+
$result .= $this->origTokens->getTokenCode(
865+
$pos, $itemStartPos, $indentAdjustment);
866+
$skipRemovedNode = true;
867+
868+
if ($this->origTokens->haveTokenImmediatelyAfter($itemEndPos, '{')
869+
|| $this->origTokens->haveTokenImmediatelyAfter($itemEndPos, '}')) {
870+
// We'd remove the brace of a code block.
871+
// TODO: Preserve formatting.
872+
return null;
873+
}
874+
} else {
875+
if ($this->origTokens->haveTokenImmediatelyBefore($itemStartPos, '{')
876+
|| $this->origTokens->haveTokenImmediatelyBefore($itemStartPos, '}')) {
877+
// We'd remove the brace of a code block.
878+
// TODO: Preserve formatting.
879+
return null;
880+
}
881+
}
854882

855883
$pos = $itemEndPos + 1;
856884
continue;
@@ -869,6 +897,11 @@ protected function pArray(
869897
$pos = $itemEndPos + 1;
870898
}
871899

900+
if ($skipRemovedNode) {
901+
// TODO: Support removing single node.
902+
return null;
903+
}
904+
872905
if (!empty($delayedAdd)) {
873906
if (!isset($this->emptyListInsertionMap[$mapKey])) {
874907
return null;

test/code/formatPreservation/basic.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ $stmts[2] = $tmp;
106106
array_splice($stmts, 0, 1, []);
107107
-----
108108
<?php
109-
110109
function test() {
111110
call2(
112111
$foo

test/code/formatPreservation/listRemoval.test

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,66 @@ array_pop($stmts[0]->returnType->types);
4949
-----
5050
<?php
5151
function test(): A
52-
|B {}
52+
|B {}
53+
-----
54+
<?php $a; $b; $c;
55+
-----
56+
array_splice($stmts, 0, 1, []);
57+
-----
58+
<?php $b; $c;
59+
-----
60+
<?php $a; $b; $c;
61+
-----
62+
array_splice($stmts, 0, 2, []);
63+
-----
64+
<?php $c;
65+
-----
66+
<?php
67+
{ $x; }
68+
$y;
69+
-----
70+
array_splice($stmts, 0, 1, []);
71+
-----
72+
<?php
73+
74+
$y;
75+
-----
76+
<?php
77+
$x;
78+
{ $y; }
79+
-----
80+
array_splice($stmts, 0, 1, []);
81+
-----
82+
<?php
83+
84+
$y;
85+
-----
86+
<?php
87+
$x;
88+
{ $y; }
89+
-----
90+
array_pop($stmts);
91+
-----
92+
<?php
93+
94+
$x;
95+
-----
96+
<?php
97+
{ $x; }
98+
$y;
99+
-----
100+
array_pop($stmts);
101+
-----
102+
<?php
103+
104+
$x;
105+
-----
106+
<?php
107+
// Foo
108+
$x;
109+
$y;
110+
-----
111+
array_splice($stmts, 0, 1, []);
112+
-----
113+
<?php
114+
$y;

0 commit comments

Comments
 (0)