From 21d6e6f9b9cf652fc70bbaf95885abfe312ded66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Mirtes?= Date: Wed, 28 Oct 2026 10:28:54 +0000 Subject: [PATCH] Printer: new empty line in docblock without trailing space A new empty PhpDocTextNode was printed as " * ". print() prints " *". Amp-Thread-ID: https://ampcode.com/threads/T-01a17930-0285-73c5-a957-4325c77aa1b2 --- src/Printer/Printer.php | 19 ++++++++++++++++--- tests/PHPStan/Printer/PrinterTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Printer/Printer.php b/src/Printer/Printer.php index a54e9ea6..a85a769c 100644 --- a/src/Printer/Printer.php +++ b/src/Printer/Printer.php @@ -672,7 +672,7 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes, } } - $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens); + $result = $this->appendNode($result, $this->printNodeFormatPreserving($delayedAddNode, $originalTokens), $afterAsteriskIndent); if ($parenthesesNeeded) { $result .= ')'; } @@ -747,7 +747,7 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes, $result .= '('; } - $result .= $this->printNodeFormatPreserving($arrItem, $originalTokens); + $result = $this->appendNode($result, $this->printNodeFormatPreserving($arrItem, $originalTokens), $afterAsteriskIndent); if ($parenthesesNeeded) { $result .= ')'; } @@ -818,7 +818,7 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes, } } - $result .= $this->printNodeFormatPreserving($delayedAddNode, $originalTokens); + $result = $this->appendNode($result, $this->printNodeFormatPreserving($delayedAddNode, $originalTokens), $afterAsteriskIndent); $first = false; } $result .= $extraRight; @@ -827,6 +827,19 @@ private function printArrayFormatPreserving(array $nodes, array $originalNodes, return $result; } + /** + * A new empty line in a docblock is " *", without the space after the asterisk + */ + private function appendNode(string $result, string $printedNode, string $afterAsteriskIndent): string + { + $lineStart = '*' . $afterAsteriskIndent; + if ($printedNode !== '' || $afterAsteriskIndent === '' || substr($result, -strlen($lineStart)) !== $lineStart) { + return $result . $printedNode; + } + + return substr($result, 0, -strlen($afterAsteriskIndent)); + } + /** * @param list $comments */ diff --git a/tests/PHPStan/Printer/PrinterTest.php b/tests/PHPStan/Printer/PrinterTest.php index 4cee45e0..5261f5ab 100644 --- a/tests/PHPStan/Printer/PrinterTest.php +++ b/tests/PHPStan/Printer/PrinterTest.php @@ -2937,6 +2937,32 @@ public function enterNode(Node $node) */'), $unsetSecond, ]; + + yield [ + self::nowdoc(' + /** + * Text. + */'), + self::nowdoc(' + /** + * Text. + * + * @return int + */'), + new class extends AbstractNodeVisitor { + + public function enterNode(Node $node) + { + if ($node instanceof PhpDocNode) { + $node->children[] = new PhpDocTextNode(''); + $node->children[] = new PhpDocTagNode('@return', new ReturnTagValueNode(new IdentifierTypeNode('int'), '')); + } + + return $node; + } + + }, + ]; } /**