mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-11-30 04:19:30 +01:00
FPPP: Switch pArray() to use node list diffing
This commit is contained in:
parent
69aec6fb5b
commit
ed8a744cd5
@ -2,6 +2,7 @@
|
||||
|
||||
namespace PhpParser;
|
||||
|
||||
use PhpParser\Internal\DiffElem;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Scalar;
|
||||
use PhpParser\Node\Stmt;
|
||||
@ -99,6 +100,8 @@ abstract class PrettyPrinterAbstract
|
||||
protected $origTokens;
|
||||
/** @var int Current indentation level during format-preserving pretty printing */
|
||||
protected $fpIndentLevel;
|
||||
/** @var Internal\Differ Differ for node lists */
|
||||
protected $nodeListDiffer;
|
||||
/** @var bool[] Map determining whether a certain character is a label character */
|
||||
protected $labelCharMap;
|
||||
/**
|
||||
@ -441,6 +444,7 @@ abstract class PrettyPrinterAbstract
|
||||
* @return string
|
||||
*/
|
||||
public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string {
|
||||
$this->initializeNodeListDiffer();
|
||||
$this->initializeLabelCharMap();
|
||||
$this->initializeFixupMap();
|
||||
$this->initializeRemovalMap();
|
||||
@ -643,22 +647,24 @@ abstract class PrettyPrinterAbstract
|
||||
* @return null|string Result of pretty print or null if cannot preserve formatting
|
||||
*/
|
||||
protected function pArray(array $nodes, array $origNodes, int &$pos, int $indentAdjustment, $fixup) {
|
||||
$len = count($nodes);
|
||||
$origLen = count($origNodes);
|
||||
if ($len !== $origLen) {
|
||||
$diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes);
|
||||
|
||||
$result = '';
|
||||
foreach ($diff as $diffElem) {
|
||||
$diffType = $diffElem->type;
|
||||
if ($diffType !== DiffElem::TYPE_KEEP && $diffType !== DiffElem::TYPE_REPLACE) {
|
||||
// Only replace supported right now
|
||||
return null;
|
||||
}
|
||||
|
||||
$result = '';
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$arrItem = $nodes[$i];
|
||||
$origArrItem = $origNodes[$i];
|
||||
/** @var Node|null $arrItem */
|
||||
$arrItem = $diffElem->new;
|
||||
/** @var Node|null $origArrItem */
|
||||
$origArrItem = $diffElem->old;
|
||||
|
||||
// We can only handle arrays of nodes meaningfully
|
||||
if (!$arrItem instanceof Node || !$origArrItem instanceof Node) {
|
||||
// Destructing can also contain null elements. If they occur symmetrically, this is
|
||||
// fine as well
|
||||
if ($arrItem === null && $origArrItem === null) {
|
||||
if ($origArrItem === null || $arrItem === null) {
|
||||
// We can only handle the case where both are null
|
||||
if ($origArrItem === $arrItem) {
|
||||
continue;
|
||||
}
|
||||
return null;
|
||||
@ -844,6 +850,23 @@ abstract class PrettyPrinterAbstract
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily initializes node list differ.
|
||||
*
|
||||
* The node list differ is used to determine differences between two array subnodes.
|
||||
*/
|
||||
protected function initializeNodeListDiffer() {
|
||||
if ($this->nodeListDiffer) return;
|
||||
|
||||
$this->nodeListDiffer = new Internal\Differ(function ($a, $b) {
|
||||
if ($a instanceof Node && $b instanceof Node) {
|
||||
return $a === $b->getAttribute('origNode');
|
||||
}
|
||||
// Can happen for array destructuring
|
||||
return $a === null && $b === null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily initializes fixup map.
|
||||
*
|
||||
|
@ -227,11 +227,13 @@ function foo() {
|
||||
$tmp = $stmts[0];
|
||||
$stmts[0] = $stmts[1];
|
||||
$stmts[1] = $tmp;
|
||||
/* TODO This used to do two replacement operations, but with the node list diffing this is a
|
||||
* remove, keep, add (which probably makes more sense). As such, this currently triggers a
|
||||
* fallback. */
|
||||
-----
|
||||
<?php
|
||||
$x;
|
||||
|
||||
{
|
||||
$x;
|
||||
function foo() {
|
||||
foo();
|
||||
/*
|
||||
@ -239,7 +241,6 @@ $x;
|
||||
*/
|
||||
baz();
|
||||
}
|
||||
}
|
||||
-----
|
||||
<?php
|
||||
echo "${foo}bar";
|
||||
|
Loading…
Reference in New Issue
Block a user