Skip to content

Commit b201c22

Browse files
committed
fix some edge cases with indented blocks
Now that comment-like lines are no longer ignored when subparsers are created, we need to ignore them in some functions (e.g. when detecting the indentation depth of the next block).
1 parent b783602 commit b201c22

File tree

2 files changed

+107
-11
lines changed

2 files changed

+107
-11
lines changed

src/Symfony/Component/Yaml/Parser.php

+45-11
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,27 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false)
537537
}
538538

539539
if (null === $indentation) {
540-
$newIndent = $this->getCurrentLineIndentation();
540+
$newIndent = null;
541+
$movements = 0;
542+
543+
do {
544+
$EOF = false;
545+
546+
// comment-like lines do not influence the indentation depth
547+
if ($this->isCurrentLineComment()) {
548+
$EOF = !$this->moveToNextLine();
549+
550+
if (!$EOF) {
551+
++$movements;
552+
}
553+
} else {
554+
$newIndent = $this->getCurrentLineIndentation();
555+
}
556+
} while (!$EOF && null === $newIndent);
557+
558+
for ($i = 0; $i < $movements; ++$i) {
559+
$this->moveToPreviousLine();
560+
}
541561

542562
$unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem();
543563

@@ -551,6 +571,8 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false)
551571
$data = array();
552572
if ($this->getCurrentLineIndentation() >= $newIndent) {
553573
$data[] = substr($this->currentLine, $newIndent);
574+
} elseif ($this->isCurrentLineComment()) {
575+
$data[] = $this->currentLine;
554576
} else {
555577
$this->moveToPreviousLine();
556578

@@ -866,19 +888,25 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0)
866888
private function isNextLineIndented()
867889
{
868890
$currentIndentation = $this->getCurrentLineIndentation();
869-
$EOF = !$this->moveToNextLine();
891+
$movements = 0;
870892

871-
while (!$EOF && $this->isCurrentLineEmpty()) {
893+
do {
872894
$EOF = !$this->moveToNextLine();
873-
}
895+
896+
if (!$EOF) {
897+
++$movements;
898+
}
899+
} while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()));
874900

875901
if ($EOF) {
876902
return false;
877903
}
878904

879905
$ret = $this->getCurrentLineIndentation() > $currentIndentation;
880906

881-
$this->moveToPreviousLine();
907+
for ($i = 0; $i < $movements; ++$i) {
908+
$this->moveToPreviousLine();
909+
}
882910

883911
return $ret;
884912
}
@@ -967,19 +995,25 @@ private function cleanup($value)
967995
private function isNextLineUnIndentedCollection()
968996
{
969997
$currentIndentation = $this->getCurrentLineIndentation();
970-
$notEOF = $this->moveToNextLine();
998+
$movements = 0;
971999

972-
while ($notEOF && $this->isCurrentLineEmpty()) {
973-
$notEOF = $this->moveToNextLine();
974-
}
1000+
do {
1001+
$EOF = !$this->moveToNextLine();
1002+
1003+
if (!$EOF) {
1004+
++$movements;
1005+
}
1006+
} while (!$EOF && ($this->isCurrentLineEmpty() || $this->isCurrentLineComment()));
9751007

976-
if (false === $notEOF) {
1008+
if ($EOF) {
9771009
return false;
9781010
}
9791011

9801012
$ret = $this->getCurrentLineIndentation() === $currentIndentation && $this->isStringUnIndentedCollectionItem();
9811013

982-
$this->moveToPreviousLine();
1014+
for ($i = 0; $i < $movements; ++$i) {
1015+
$this->moveToPreviousLine();
1016+
}
9831017

9841018
return $ret;
9851019
}

src/Symfony/Component/Yaml/Tests/ParserTest.php

+62
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,68 @@ public function testEvalRefException()
20132013
EOE;
20142014
$this->parser->parse($yaml);
20152015
}
2016+
2017+
/**
2018+
* @dataProvider indentedMappingData
2019+
*/
2020+
public function testParseIndentedMappings($yaml, $expected)
2021+
{
2022+
$this->assertSame($expected, $this->parser->parse($yaml));
2023+
}
2024+
2025+
public function indentedMappingData()
2026+
{
2027+
$tests = array();
2028+
2029+
$yaml = <<<YAML
2030+
foo:
2031+
- bar: "foobar"
2032+
# A comment
2033+
baz: "foobaz"
2034+
YAML;
2035+
$expected = array(
2036+
'foo' => array(
2037+
array(
2038+
'bar' => 'foobar',
2039+
'baz' => 'foobaz',
2040+
),
2041+
),
2042+
);
2043+
$tests['comment line is first line in indented block'] = array($yaml, $expected);
2044+
2045+
$yaml = <<<YAML
2046+
foo:
2047+
- bar:
2048+
# comment
2049+
baz: [1, 2, 3]
2050+
YAML;
2051+
$expected = array(
2052+
'foo' => array(
2053+
array(
2054+
'bar' => array(
2055+
'baz' => array(1, 2, 3),
2056+
),
2057+
),
2058+
),
2059+
);
2060+
$tests['mapping value on new line starting with a comment line'] = array($yaml, $expected);
2061+
2062+
$yaml = <<<YAML
2063+
foo:
2064+
-
2065+
bar: foobar
2066+
YAML;
2067+
$expected = array(
2068+
'foo' => array(
2069+
array(
2070+
'bar' => 'foobar',
2071+
),
2072+
),
2073+
);
2074+
$tests['mapping in sequence starting on a new line'] = array($yaml, $expected);
2075+
2076+
return $tests;
2077+
}
20162078
}
20172079

20182080
class B

0 commit comments

Comments
 (0)