Skip to content

Commit 44f8d89

Browse files
committed
Printer: support lists with gaps in keys
After unset() on a list, printFormatPreserving() gave "Undefined array key" warnings, because the differ reads the lists by position. Amp-Thread-ID: https://ampcode.com/threads/T-01a17930-0285-73c5-a957-4325c77aa1b2
1 parent a53805e commit 44f8d89

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

‎src/Printer/Printer.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
use PHPStan\PhpDocParser\Parser\TokenIterator;
7070
use function array_keys;
7171
use function array_map;
72+
use function array_values;
7273
use function assert;
7374
use function count;
7475
use function get_class;
@@ -598,6 +599,10 @@ private function printConstExpr(ConstExprNode $node): string
598599
*/
599600
private function printArrayFormatPreserving(array $nodes, array $originalNodes, TokenIterator $originalTokens, int &$tokenIndex, string $parentNodeClass, string $subNodeName): ?string
600601
{
602+
// unset() leaves gaps in the keys, the differ reads the lists by position
603+
$nodes = array_values($nodes);
604+
$originalNodes = array_values($originalNodes);
605+
601606
$diff = $this->differ->diffWithReplacements($originalNodes, $nodes);
602607
$mapKey = $parentNodeClass . '->' . $subNodeName;
603608
$insertStr = $this->listInsertionMap[$mapKey] ?? null;

‎tests/PHPStan/Printer/PrinterTest.php‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,6 +2899,44 @@ public function enterNode(Node $node)
28992899

29002900
},
29012901
];
2902+
2903+
$unsetSecond = new class extends AbstractNodeVisitor {
2904+
2905+
public function enterNode(Node $node)
2906+
{
2907+
if ($node instanceof PhpDocNode) {
2908+
unset($node->children[1]);
2909+
}
2910+
2911+
if ($node instanceof UnionTypeNode) {
2912+
unset($node->types[1]);
2913+
}
2914+
2915+
return $node;
2916+
}
2917+
2918+
};
2919+
2920+
yield [
2921+
'/** @var A|B|C */',
2922+
'/** @var A|C */',
2923+
$unsetSecond,
2924+
];
2925+
2926+
yield [
2927+
self::nowdoc('
2928+
/**
2929+
* @param Foo $foo
2930+
* @param Bar $bar
2931+
* @param Baz $baz
2932+
*/'),
2933+
self::nowdoc('
2934+
/**
2935+
* @param Foo $foo
2936+
* @param Baz $baz
2937+
*/'),
2938+
$unsetSecond,
2939+
];
29022940
}
29032941

29042942
/**
@@ -2941,6 +2979,15 @@ public function enterNode(Node $node)
29412979
$node->setAttribute(Attribute::ORIGINAL_NODE, null);
29422980
$node->setAttribute(Attribute::COMMENTS, null);
29432981

2982+
// the printed result is compared with a node that can have gaps in its lists
2983+
if ($node instanceof PhpDocNode) {
2984+
$node->children = array_values($node->children);
2985+
}
2986+
2987+
if ($node instanceof UnionTypeNode) {
2988+
$node->types = array_values($node->types);
2989+
}
2990+
29442991
return $node;
29452992
}
29462993

0 commit comments

Comments
 (0)