Skip to content

fix: keep trailing whitespace in heredoc and nowdoc bodies - #2550

Open
wleeaf wants to merge 1 commit into
prettier:mainfrom
wleeaf:heredoc-trailing-whitespace
Open

wleeaf wants to merge 1 commit into
prettier:mainfrom
wleeaf:heredoc-trailing-whitespace

Conversation

@wleeaf

@wleeaf wleeaf commented Oct 25, 2026

Copy link
Copy Markdown

Bug: with phpVersion 7.3 or later, trailing spaces and tabs on heredoc and nowdoc lines are removed, which changes the string (#2026):

$foo = <<<EOT
foo   
EOT;

is printed with foo and no trailing spaces. A whitespace-only line inside an indented heredoc also becomes empty.

Cause: flexible heredocs and nowdocs are re-indented by joining their lines with hardline, and Prettier's doc printer trims trailing whitespace before every hardline. Before 7.3 they're joined with literalline, which doesn't trim, so the bug only shows up with flexible heredocs.

Fix: a new joinHeredocLines helper in src/printer.mjs joins the lines of a flexible heredoc string part or nowdoc body. A line that ends in a space or tab is followed by a literalline inside markAsRoot, so the next line still gets the current indentation and nothing is trimmed. All other lines are still joined with hardline, so heredocs without trailing whitespace print exactly as before.

Tests: added tests/encapsed/heredoc-trailing-whitespace.php and tests/nowdoc/trailing-whitespace.php, each with a top-level and an indented heredoc/nowdoc that have trailing spaces, a trailing tab and a whitespace-only line (the heredoc one also has an interpolation followed by spaces). Both run under the existing 7.0 and 7.3 specs. Without the fix, the two 7.3 snapshots fail. With it, yarn test:node passes (603 tests), AST_COMPARE=1 yarn test:node passes and yarn lint is clean.

I also formatted the --FILE-- sections of php-src's Zend/tests (5703 files) with and without the change. The only output that differs is Zend/tests/heredoc_nowdoc/nowdoc_013.phpt: it lost the trailing spaces of some string before and keeps them now, so its nikic/PHP-Parser AST matches the input's. Every other file is byte-identical.

Fixes #2026

Flexible heredocs and nowdocs (PHP >= 7.3) are re-indented with
`hardline`, and the doc printer trims trailing spaces and tabs before
every `hardline`. That whitespace is part of the string, so formatting
changed the value: `foo   ` became `foo`, and a whitespace-only line
became empty.

After a line that ends in whitespace, use a `literalline` under
`markAsRoot` instead, so the next line keeps the same indentation and
nothing is trimmed. Other lines still use `hardline`, so output is
unchanged for heredocs without trailing whitespace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Whitespace improperly removed from end of heredoc lines

1 participant