Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/Printer/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,7 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes,
$insertStr = $this->listInsertionMap[$mapKey] ?? null;
$result = '';
$beforeFirstKeepOrReplace = true;
$skipRemovedNode = false;
$delayedAdd = [];

$insertNewline = false;
Expand Down Expand Up @@ -643,7 +644,12 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes,
$commentStartPos = count($origComments) > 0 ? $origComments[0]->startIndex : $itemStartPos;
assert($commentStartPos >= 0);

$result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos);
if ($skipRemovedNode) {
// the separator after the removed first item belongs to it
$skipRemovedNode = false;
} else {
$result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos);
}

if (count($delayedAdd) > 0) {
foreach ($delayedAdd as $delayedAddNode) {
Expand Down Expand Up @@ -760,12 +766,18 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes,
if ($i === 0) {
// If we're removing from the start, keep the tokens before the node and drop those after it,
// instead of the other way around.
$originalTokensArray = $originalTokens->getTokens();
for ($j = $tokenIndex; $j < $itemStartPos; $j++) {
if ($originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) {
break;
if ($mapKey === PhpDocNode::class . '->children') {
// the line of the removed child is dropped, the next child keeps its own line
$originalTokensArray = $originalTokens->getTokens();
for ($j = $tokenIndex; $j < $itemStartPos; $j++) {
if ($originalTokensArray[$j][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) {
break;
}
$result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET];
}
$result .= $originalTokensArray[$j][Lexer::VALUE_OFFSET];
} else {
$result .= $originalTokens->getContentBetween($tokenIndex, $itemStartPos);
$skipRemovedNode = true;
}
}

Expand Down
49 changes: 49 additions & 0 deletions tests/PHPStan/Printer/PrinterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
use PHPUnit\Framework\TestCase;
use function array_map;
use function array_pop;
use function array_shift;
use function array_slice;
use function array_splice;
use function array_unshift;
Expand Down Expand Up @@ -2850,6 +2851,54 @@ public function enterNode(Node $node)
*/'),
$addCommentToObjectShapeItemMiddle,
];

$removeFirstType = new class extends AbstractNodeVisitor {

public function enterNode(Node $node)
{
if ($node instanceof UnionTypeNode || $node instanceof IntersectionTypeNode) {
array_shift($node->types);
}

return $node;
}

};

yield [
'/** @var A|B|C */',
'/** @var B|C */',
$removeFirstType,
];

yield [
'/** @var A | B | C */',
'/** @var B | C */',
$removeFirstType,
];

yield [
'/** @var (A & B & C) */',
'/** @var (B & C) */',
$removeFirstType,
];

yield [
'/** @var A|B|C|D */',
'/** @var C|D */',
new class extends AbstractNodeVisitor {

public function enterNode(Node $node)
{
if ($node instanceof UnionTypeNode) {
$node->types = [$node->types[2], $node->types[3]];
}

return $node;
}

},
];
}

/**
Expand Down
Loading