mirror of
https://github.com/danog/PHP-Parser.git
synced 2024-11-27 04:14:44 +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;
|
namespace PhpParser;
|
||||||
|
|
||||||
|
use PhpParser\Internal\DiffElem;
|
||||||
use PhpParser\Node\Expr;
|
use PhpParser\Node\Expr;
|
||||||
use PhpParser\Node\Scalar;
|
use PhpParser\Node\Scalar;
|
||||||
use PhpParser\Node\Stmt;
|
use PhpParser\Node\Stmt;
|
||||||
@ -99,6 +100,8 @@ abstract class PrettyPrinterAbstract
|
|||||||
protected $origTokens;
|
protected $origTokens;
|
||||||
/** @var int Current indentation level during format-preserving pretty printing */
|
/** @var int Current indentation level during format-preserving pretty printing */
|
||||||
protected $fpIndentLevel;
|
protected $fpIndentLevel;
|
||||||
|
/** @var Internal\Differ Differ for node lists */
|
||||||
|
protected $nodeListDiffer;
|
||||||
/** @var bool[] Map determining whether a certain character is a label character */
|
/** @var bool[] Map determining whether a certain character is a label character */
|
||||||
protected $labelCharMap;
|
protected $labelCharMap;
|
||||||
/**
|
/**
|
||||||
@ -441,6 +444,7 @@ abstract class PrettyPrinterAbstract
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string {
|
public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string {
|
||||||
|
$this->initializeNodeListDiffer();
|
||||||
$this->initializeLabelCharMap();
|
$this->initializeLabelCharMap();
|
||||||
$this->initializeFixupMap();
|
$this->initializeFixupMap();
|
||||||
$this->initializeRemovalMap();
|
$this->initializeRemovalMap();
|
||||||
@ -643,22 +647,24 @@ abstract class PrettyPrinterAbstract
|
|||||||
* @return null|string Result of pretty print or null if cannot preserve formatting
|
* @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) {
|
protected function pArray(array $nodes, array $origNodes, int &$pos, int $indentAdjustment, $fixup) {
|
||||||
$len = count($nodes);
|
$diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes);
|
||||||
$origLen = count($origNodes);
|
|
||||||
if ($len !== $origLen) {
|
$result = '';
|
||||||
|
foreach ($diff as $diffElem) {
|
||||||
|
$diffType = $diffElem->type;
|
||||||
|
if ($diffType !== DiffElem::TYPE_KEEP && $diffType !== DiffElem::TYPE_REPLACE) {
|
||||||
|
// Only replace supported right now
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = '';
|
/** @var Node|null $arrItem */
|
||||||
for ($i = 0; $i < $len; $i++) {
|
$arrItem = $diffElem->new;
|
||||||
$arrItem = $nodes[$i];
|
/** @var Node|null $origArrItem */
|
||||||
$origArrItem = $origNodes[$i];
|
$origArrItem = $diffElem->old;
|
||||||
|
|
||||||
// We can only handle arrays of nodes meaningfully
|
if ($origArrItem === null || $arrItem === null) {
|
||||||
if (!$arrItem instanceof Node || !$origArrItem instanceof Node) {
|
// We can only handle the case where both are null
|
||||||
// Destructing can also contain null elements. If they occur symmetrically, this is
|
if ($origArrItem === $arrItem) {
|
||||||
// fine as well
|
|
||||||
if ($arrItem === null && $origArrItem === null) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return null;
|
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.
|
* Lazily initializes fixup map.
|
||||||
*
|
*
|
||||||
|
@ -227,18 +227,19 @@ function foo() {
|
|||||||
$tmp = $stmts[0];
|
$tmp = $stmts[0];
|
||||||
$stmts[0] = $stmts[1];
|
$stmts[0] = $stmts[1];
|
||||||
$stmts[1] = $tmp;
|
$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
|
<?php
|
||||||
$x;
|
|
||||||
|
|
||||||
{
|
$x;
|
||||||
function foo() {
|
function foo() {
|
||||||
foo();
|
foo();
|
||||||
/*
|
/*
|
||||||
* bar
|
* bar
|
||||||
*/
|
*/
|
||||||
baz();
|
baz();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
-----
|
-----
|
||||||
<?php
|
<?php
|
||||||
|
Loading…
Reference in New Issue
Block a user