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

View File

@ -737,7 +737,9 @@ EOF;
public function getCommentLikeStringInScalarBlockData()
{
$yaml1 = <<<'EOT'
$tests = array();
$yaml = <<<'EOT'
pages:
-
title: some title
@ -752,7 +754,7 @@ pages:
footer # comment3
EOT;
$expected1 = array(
$expected = array(
'pages' => array(
array(
'title' => 'some title',
@ -771,8 +773,9 @@ EOT
),
),
);
$tests[] = array($yaml, $expected);
$yaml2 = <<<'EOT'
$yaml = <<<'EOT'
test: |
foo
# bar
@ -787,7 +790,7 @@ collection:
# bar
baz
EOT;
$expected2 = array(
$expected = array(
'test' => <<<'EOT'
foo
# bar
@ -814,11 +817,47 @@ EOT
),
),
);
$tests[] = array($yaml, $expected);
return array(
array($yaml1, $expected1),
array($yaml2, $expected2),
$yaml = <<<EOT
foo:
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()