From fc854359159c6e040bbaea7507978bdaec1c8766 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 29 Aug 2014 13:30:22 +0200 Subject: [PATCH] fix handling of empty sequence items When a line contains only a dash it cannot safely be assumed that it contains a nested list or an embedded mapping. If the next line starts with a dash at the same indentation, the current line's item is to be treated as `null`. --- src/Symfony/Component/Yaml/Parser.php | 21 ++++++++++++---- .../Yaml/Tests/Fixtures/YtsBasicTests.yml | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index addb387a48..5c578e35d3 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -93,7 +93,7 @@ class Parser $c = $this->getRealCurrentLineNb() + 1; $parser = new Parser($c); $parser->refs =& $this->refs; - $data[] = $parser->parse($this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport); + $data[] = $parser->parse($this->getNextEmbedBlock(null, true), $exceptionOnInvalidType, $objectSupport); } else { if (isset($values['leadspaces']) && ' ' == $values['leadspaces'] @@ -281,15 +281,20 @@ class Parser /** * Returns the next embed block of YAML. * - * @param int $indentation The indent level at which the block is to be read, or null for default + * @param int $indentation The indent level at which the block is to be read, or null for default + * @param bool $inSequence True if the enclosing data structure is a sequence * * @return string A YAML string * * @throws ParseException When indentation problem are detected */ - private function getNextEmbedBlock($indentation = null) + private function getNextEmbedBlock($indentation = null, $inSequence = false) { - $this->moveToNextLine(); + $oldLineIndentation = $this->getCurrentLineIndentation(); + + if (!$this->moveToNextLine()) { + return; + } if (null === $indentation) { $newIndent = $this->getCurrentLineIndentation(); @@ -305,6 +310,14 @@ class Parser $data = array(substr($this->currentLine, $newIndent)); + if ($inSequence && $oldLineIndentation === $newIndent && '-' === $data[0][0]) { + // the previous line contained a dash but no item content, this line is a sequence item with the same indentation + // and therefore no nested list or mapping + $this->moveToPreviousLine(); + + return; + } + $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem($this->currentLine); // Comments must not be removed inside a string block (ie. after a line ending with "|") diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml index ac0efa88d1..dfd93021d1 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsBasicTests.yml @@ -11,6 +11,30 @@ yaml: | php: | array('apple', 'banana', 'carrot') --- +test: Sequence With Item Being Null In The Middle +brief: | + You can specify a list in YAML by placing each + member of the list on a new line with an opening + dash. These lists are called sequences. +yaml: | + - apple + - + - carrot +php: | + array('apple', null, 'carrot') +--- +test: Sequence With Last Item Being Null +brief: | + You can specify a list in YAML by placing each + member of the list on a new line with an opening + dash. These lists are called sequences. +yaml: | + - apple + - banana + - +php: | + array('apple', 'banana', null) +--- test: Nested Sequences brief: | You can include a sequence within another