bug #17159 [Yaml] recognize when a block scalar is left (xabbuh)

This PR was merged into the 2.3 branch.

Discussion
----------

[Yaml] recognize when a block scalar is left

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #17116
| License       | MIT
| Doc PR        |

The parser did not recognize when the block scalar was completely parsed
and thus treated following comments as they need to be kept leading to
parse errors on the following lines.

Commits
-------

3a22165 [Yaml] recognize when a block scalar is left
This commit is contained in:
Fabien Potencier 2016-01-04 12:01:16 +01:00
commit e738227d63
2 changed files with 67 additions and 15 deletions

View File

@ -303,7 +303,11 @@ class Parser
private function getNextEmbedBlock($indentation = null, $inSequence = false) private function getNextEmbedBlock($indentation = null, $inSequence = false)
{ {
$oldLineIndentation = $this->getCurrentLineIndentation(); $oldLineIndentation = $this->getCurrentLineIndentation();
$insideBlockScalar = $this->isBlockScalarHeader(); $blockScalarIndentations = array();
if ($this->isBlockScalarHeader()) {
$blockScalarIndentations[] = $this->getCurrentLineIndentation();
}
if (!$this->moveToNextLine()) { if (!$this->moveToNextLine()) {
return; return;
@ -340,8 +344,8 @@ class Parser
$isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem();
if (!$insideBlockScalar) { if (empty($blockScalarIndentations) && $this->isBlockScalarHeader()) {
$insideBlockScalar = $this->isBlockScalarHeader(); $blockScalarIndentations[] = $this->getCurrentLineIndentation();
} }
$previousLineIndentation = $this->getCurrentLineIndentation(); $previousLineIndentation = $this->getCurrentLineIndentation();
@ -349,8 +353,17 @@ class Parser
while ($this->moveToNextLine()) { while ($this->moveToNextLine()) {
$indent = $this->getCurrentLineIndentation(); $indent = $this->getCurrentLineIndentation();
if (!$insideBlockScalar && $indent === $previousLineIndentation) { // terminate all block scalars that are more indented than the current line
$insideBlockScalar = $this->isBlockScalarHeader(); if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && trim($this->currentLine) !== '') {
foreach ($blockScalarIndentations as $key => $blockScalarIndentation) {
if ($blockScalarIndentation >= $this->getCurrentLineIndentation()) {
unset($blockScalarIndentations[$key]);
}
}
}
if (empty($blockScalarIndentations) && !$this->isCurrentLineComment() && $this->isBlockScalarHeader()) {
$blockScalarIndentations[] = $this->getCurrentLineIndentation();
} }
$previousLineIndentation = $indent; $previousLineIndentation = $indent;
@ -366,7 +379,7 @@ class Parser
} }
// we ignore "comment" lines only when we are not inside a scalar block // we ignore "comment" lines only when we are not inside a scalar block
if (!$insideBlockScalar && $this->isCurrentLineComment()) { if (empty($blockScalarIndentations) && $this->isCurrentLineComment()) {
continue; continue;
} }
@ -523,7 +536,7 @@ class Parser
$previousLineIndented = false; $previousLineIndented = false;
$previousLineBlank = false; $previousLineBlank = false;
for ($i = 0; $i < count($blockLines); $i++) { for ($i = 0; $i < count($blockLines); ++$i) {
if ('' === $blockLines[$i]) { if ('' === $blockLines[$i]) {
$text .= "\n"; $text .= "\n";
$previousLineIndented = false; $previousLineIndented = false;
@ -618,7 +631,7 @@ class Parser
//checking explicitly the first char of the trim is faster than loops or strpos //checking explicitly the first char of the trim is faster than loops or strpos
$ltrimmedLine = ltrim($this->currentLine, ' '); $ltrimmedLine = ltrim($this->currentLine, ' ');
return $ltrimmedLine[0] === '#'; return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#';
} }
/** /**

View File

@ -737,7 +737,9 @@ EOF;
public function getCommentLikeStringInScalarBlockData() public function getCommentLikeStringInScalarBlockData()
{ {
$yaml1 = <<<'EOT' $tests = array();
$yaml = <<<'EOT'
pages: pages:
- -
title: some title title: some title
@ -752,7 +754,7 @@ pages:
footer # comment3 footer # comment3
EOT; EOT;
$expected1 = array( $expected = array(
'pages' => array( 'pages' => array(
array( array(
'title' => 'some title', 'title' => 'some title',
@ -771,8 +773,9 @@ EOT
), ),
), ),
); );
$tests[] = array($yaml, $expected);
$yaml2 = <<<'EOT' $yaml = <<<'EOT'
test: | test: |
foo foo
# bar # bar
@ -787,7 +790,7 @@ collection:
# bar # bar
baz baz
EOT; EOT;
$expected2 = array( $expected = array(
'test' => <<<'EOT' 'test' => <<<'EOT'
foo foo
# bar # bar
@ -814,11 +817,47 @@ EOT
), ),
), ),
); );
$tests[] = array($yaml, $expected);
return array( $yaml = <<<EOT
array($yaml1, $expected1), foo:
array($yaml2, $expected2), bar:
scalar-block: >
line1
line2>
baz:
# comment
foobar: ~
EOT;
$expected = array(
'foo' => array(
'bar' => array(
'scalar-block' => 'line1 line2>',
),
'baz' => array(
'foobar' => null,
),
),
); );
$tests[] = array($yaml, $expected);
$yaml = <<<'EOT'
a:
b: hello
# c: |
# first row
# second row
d: hello
EOT;
$expected = array(
'a' => array(
'b' => 'hello',
'd' => 'hello',
),
);
$tests[] = array($yaml, $expected);
return $tests;
} }
public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks() public function testBlankLinesAreParsedAsNewLinesInFoldedBlocks()