diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 94af06cc3fd85..8e0bc86c8323a 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -36,6 +36,7 @@ class Parser private $skippedLineNumbers = []; private $locallySkippedLineNumbers = []; private $refsBeingParsed = []; + private $openMappingCount = 0; /** * Parses a YAML file into a PHP value. @@ -1208,18 +1209,12 @@ private function lexInlineMapping(string $yaml): string if ('' === $yaml || '{' !== $yaml[0]) { throw new \InvalidArgumentException(sprintf('"%s" is not a sequence.', $yaml)); } - - for ($i = 1; isset($yaml[$i]) && '}' !== $yaml[$i]; ++$i) { - } - - if (isset($yaml[$i]) && '}' === $yaml[$i]) { - return $yaml; - } - - $lines = [$yaml]; - - while ($this->moveToNextLine()) { - $lines[] = $this->currentLine; + $this->openMappingCount = 0; + $lines = [ + $this->calculateLineOpenMappings($yaml), + ]; + while (!$this->allMappingIsClosed() && $this->moveToNextLine()) { + $lines[] = $this->calculateLineOpenMappings($this->currentLine); } return implode("\n", $lines); @@ -1253,4 +1248,23 @@ private function lexInlineSequence(string $yaml): string return $value; } + + private function allMappingIsClosed(): bool + { + return 0 === $this->openMappingCount; + } + + private function calculateLineOpenMappings(string $yamlLine): string + { + for ($i = 0; isset($yamlLine[$i]); ++$i) { + if ('{' === $yamlLine[$i]) { + ++$this->openMappingCount; + } + if ('}' === $yamlLine[$i]) { + --$this->openMappingCount; + } + } + + return trim($yamlLine); + } } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 8d278d91023e1..b83c685321ce3 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -2414,6 +2414,46 @@ public function testParseValueWithNegativeModifiers() $this->parser->parse($yaml) ); } + + /** + * @dataProvider validMappingSequenceProvider + */ + public function testParametersAfterMappingSequence(string $yaml, array $parsed): void + { + self::assertSame($parsed, $this->parser->parse($yaml)); + } + + public function validMappingSequenceProvider(): iterable + { + $expected = [ + 'map' => [ + 'key' => 'value', + 'a' => 'b', + ], + 'param' => 'some', + ]; + $yaml = << [$yaml, $expected]; + + $yaml = << [$yaml, $expected]; + + $yaml = << [$yaml, $expected]; + } } class B