Perl-Critic / PPI

53 stars 44 forks source link

Heredocs are stripped from stringified Document object #288

Open h3xx opened 1 year ago

h3xx commented 1 year ago

Problem description

Stringifying the PPI::Document object (same as calling ->content() on it) strips out the content of heredocs, giving back an un-parseable document.

Example code:

#!/usr/bin/perl
use strict;
use warnings;
require PPI;
my $content = "my \$heredoc = <<~HERE;\n\tLine 1\n\n\tLine 3\n\tHERE\n";
my $doc = PPI::Document->new(\$content);
print $doc;

Which prints:

my $heredoc = <<~HERE;

Expected to print:

my $heredoc = <<~HERE;
        Line 1

        Line 3
        HERE

From what I've seen, the other tokens in the code are preserved, it's just heredocs that I found were affected.

Workaround

A workaround I've found is to call $doc->serialize instead. But this begs the question as to why the object stringifies at all if it produces broken code.

Notes

I investigated, and apparently the PPI::Token::HereDoc object only sets ->{content} to the first line. It should set it to the entire heredoc contents to fix the issue.

Possible other fix is to do use overload '""' => 'serialize' instead of => 'content'.

oalders commented 1 year ago

I encountered the same issue in perlimports:

https://metacpan.org/release/OALDERS/App-perlimports-0.000052/source/lib/App/perlimports/Document.pm#L1004-1006