Skip to content

[Yaml Parser] Fix edge cases when parsing multiple documents #38228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 18, 2020
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
1 change: 1 addition & 0 deletions src/Symfony/Component/Yaml/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ public function parse($value, $flags = 0)
$this->refs = [];
$this->skippedLineNumbers = [];
$this->locallySkippedLineNumbers = [];
$this->totalNumberOfLines = null;

if (null !== $e) {
throw $e;
Expand Down
33 changes: 33 additions & 0 deletions src/Symfony/Component/Yaml/Tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2362,6 +2362,39 @@ public function testParseValueWithNegativeModifiers()
$this->parser->parse($yaml)
);
}

/**
* This is a regression test for a bug where a YAML block with a nested multiline string using | was parsed without
* a trailing \n when a shorter YAML document was parsed before.
*
* When a shorter document was parsed before, the nested string did not have a \n at the end of the string, because
* the Parser thought it was the end of the file, even though it is not.
*/
public function testParsingMultipleDocuments()
{
$shortDocument = 'foo: bar';
$longDocument = <<<YAML
a:
b: |
row
row2
c: d
YAML;

$expected = ['a' => ['b' => "row\nrow2\n"], 'c' => 'd'];

// The parser was not used before, so there is a new line after row2
$this->assertSame($expected, $this->parser->parse($longDocument));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't look needed to me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just added this to show that this is the actual result. But yes, it can be removed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand though I think that's rather confusing when reading the test and trying to understand what is going on IMO.


$parser = new Parser();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as far as I can see we can simply use $this->parser when parsing the two documents

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see #38235

// The first parsing set and fixed the totalNumberOfLines in the Parser before, so parsing the short document here
// to reproduce the issue. If the issue would not have been fixed, the next assertion will fail
$parser->parse($shortDocument);

// After the total number of lines has been rset the result will be the same as if a new parser was used
// (before, there was no \n after row2)
$this->assertSame($expected, $parser->parse($longDocument));
}
}

class B
Expand Down