diff --git a/src/Printer/Printer.php b/src/Printer/Printer.php index c80315eb..a54e9ea6 100644 --- a/src/Printer/Printer.php +++ b/src/Printer/Printer.php @@ -69,6 +69,7 @@ use PHPStan\PhpDocParser\Parser\TokenIterator; use function array_keys; use function array_map; +use function array_values; use function assert; use function count; use function get_class; @@ -598,6 +599,10 @@ private function printConstExpr(ConstExprNode $node): string */ private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $subNodeName): ?string { + // unset() leaves gaps in the keys, the differ reads the lists by position + $nodes = array_values($nodes); + $originalNodes = array_values($originalNodes); + $diff = $this->differ->diffWithReplacements($originalNodes, $nodes); $mapKey = $parentNodeClass . '->' . $subNodeName; $insertStr = $this->listInsertionMap[$mapKey] ?? null; diff --git a/tests/PHPStan/Printer/PrinterTest.php b/tests/PHPStan/Printer/PrinterTest.php index 2b6fa576..4cee45e0 100644 --- a/tests/PHPStan/Printer/PrinterTest.php +++ b/tests/PHPStan/Printer/PrinterTest.php @@ -2899,6 +2899,44 @@ public function enterNode(Node $node) }, ]; + + $unsetSecond = new class extends AbstractNodeVisitor { + + public function enterNode(Node $node) + { + if ($node instanceof PhpDocNode) { + unset($node->children[1]); + } + + if ($node instanceof UnionTypeNode) { + unset($node->types[1]); + } + + return $node; + } + + }; + + yield [ + '/** @var A|B|C */', + '/** @var A|C */', + $unsetSecond, + ]; + + yield [ + self::nowdoc(' + /** + * @param Foo $foo + * @param Bar $bar + * @param Baz $baz + */'), + self::nowdoc(' + /** + * @param Foo $foo + * @param Baz $baz + */'), + $unsetSecond, + ]; } /** @@ -2941,6 +2979,15 @@ public function enterNode(Node $node) $node->setAttribute(Attribute::ORIGINAL_NODE, null); $node->setAttribute(Attribute::COMMENTS, null); + // the printed result is compared with a node that can have gaps in its lists + if ($node instanceof PhpDocNode) { + $node->children = array_values($node->children); + } + + if ($node instanceof UnionTypeNode) { + $node->types = array_values($node->types); + } + return $node; }