From 3c72fccc1b31a4799405cf713d0d81ddd95cf2ec Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 5 Dec 2015 11:55:16 +0100 Subject: [PATCH] [Yaml] do not remove "comments" in scalar blocks Inside scalar blocks, lines starting with a `#` character must be treated like every other strings and must not be ignored as comments. --- src/Symfony/Component/Yaml/Parser.php | 28 ++++-- .../Component/Yaml/Tests/ParserTest.php | 94 +++++++++++++++++++ 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 614bfedce5..efaaeaf710 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -303,6 +303,7 @@ class Parser private function getNextEmbedBlock($indentation = null, $inSequence = false) { $oldLineIndentation = $this->getCurrentLineIndentation(); + $insideBlockScalar = $this->isBlockScalarHeader(); if (!$this->moveToNextLine()) { return; @@ -339,17 +340,21 @@ class Parser $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); - // Comments must not be removed inside a block scalar - $removeCommentsPattern = '~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~'; - $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); + if (!$insideBlockScalar) { + $insideBlockScalar = $this->isBlockScalarHeader(); + } + + $previousLineIndentation = $this->getCurrentLineIndentation(); while ($this->moveToNextLine()) { $indent = $this->getCurrentLineIndentation(); - if ($indent === $newIndent) { - $removeComments = !preg_match($removeCommentsPattern, $this->currentLine); + if (!$insideBlockScalar && $indent === $previousLineIndentation) { + $insideBlockScalar = $this->isBlockScalarHeader(); } + $previousLineIndentation = $indent; + if ($isItUnindentedCollection && !$this->isStringUnIndentedCollectionItem() && $newIndent === $indent) { $this->moveToPreviousLine(); break; @@ -360,7 +365,8 @@ class Parser continue; } - if ($removeComments && $this->isCurrentLineComment()) { + // we ignore "comment" lines only when we are not inside a scalar block + if (!$insideBlockScalar && $this->isCurrentLineComment()) { continue; } @@ -672,4 +678,14 @@ class Parser { return 0 === strpos($this->currentLine, '- '); } + + /** + * Tests whether or not the current line is the header of a block scalar. + * + * @return bool + */ + private function isBlockScalarHeader() + { + return (bool) preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine); + } } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 0658dd295d..0ee1080d7a 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -726,6 +726,100 @@ EOF; $this->assertEquals($expected, $this->parser->parse($yaml)); } + + /** + * @dataProvider getCommentLikeStringInScalarBlockData + */ + public function testCommentLikeStringsAreNotStrippedInBlockScalars($yaml, $expectedParserResult) + { + $this->assertSame($expectedParserResult, $this->parser->parse($yaml)); + } + + public function getCommentLikeStringInScalarBlockData() + { + $yaml1 = << +

title

+ + + footer # comment3 +EOT; + $expected1 = array( + 'pages' => array( + array( + 'title' => 'some title', + 'content' => << +

title

+ + +footer # comment3 +EOT + , + ), + ), + ); + + $yaml2 = << << array( + array( + 'one' => << <<