diff --git a/UPGRADE-3.2.md b/UPGRADE-3.2.md index 39b5ba0dca..9599fd7b70 100644 --- a/UPGRADE-3.2.md +++ b/UPGRADE-3.2.md @@ -74,8 +74,8 @@ Validator Yaml ---- - * Support for silently ignoring duplicate keys in YAML has been deprecated and - will lead to a `ParseException` in Symfony 4.0. + * Support for silently ignoring duplicate mapping keys in YAML has been + deprecated and will lead to a `ParseException` in Symfony 4.0. * Mappings with a colon that is not followed by a space are deprecated and will lead to a `ParseException` in Symfony 4.0. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 014d2393e0..4bdf15b276 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -233,8 +233,7 @@ Yaml * The `!!php/object` tag to indicate dumped PHP objects was removed in favor of the `!php/object` tag. - * Duplicate keys in YAML leads to a `ParseException`. - + * Duplicate mapping keys lead to a `ParseException`. Validator --------- diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index b321cf0ca8..35917c13c8 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -13,8 +13,8 @@ CHANGELOG Yaml::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT); ``` - * Support for silently ignoring duplicate keys in YAML has been deprecated and - will lead to a `ParseException` in Symfony 4.0. + * Support for silently ignoring duplicate mapping keys in YAML has been + deprecated and will lead to a `ParseException` in Symfony 4.0. 3.1.0 ----- diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 2a9ba39f94..d0bab16bb2 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -25,6 +25,8 @@ class Inline { const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\']*(?:\'\'[^\']*)*)\')'; + public static $parsedLineNumber; + private static $exceptionOnInvalidType = false; private static $objectSupport = false; private static $objectForMap = false; @@ -476,7 +478,7 @@ class Inline if (!isset($output[$key])) { $output[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); } $done = true; break; @@ -489,7 +491,7 @@ class Inline if (!isset($output[$key])) { $output[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); } $done = true; break; @@ -504,7 +506,7 @@ class Inline if (!isset($output[$key])) { $output[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); } $done = true; --$i; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 6bd56073f6..217103dd82 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -156,6 +156,7 @@ class Parser // force correct settings Inline::parse(null, $flags, $this->refs); try { + Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); $key = Inline::parseScalar($values['key']); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); @@ -242,16 +243,18 @@ class Parser if ($allowOverwrite || !isset($data[$key])) { $data[$key] = null; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } } else { + // remember the parsed line number here in case we need it to provide some contexts in error messages below + $realCurrentLineNbKey = $this->getRealCurrentLineNb(); $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags); // Spec: Keys MUST be unique; first one wins. // But overwriting is allowed when a merge node is used in current block. if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $realCurrentLineNbKey + 1), E_USER_DEPRECATED); } } } else { @@ -261,7 +264,7 @@ class Parser if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } } if ($isRef) { @@ -276,6 +279,7 @@ class Parser // 1-liner optionally followed by newline(s) if (is_string($value) && $this->lines[0] === trim($value)) { try { + Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); $value = Inline::parse($this->lines[0], $flags, $this->refs); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); @@ -578,6 +582,7 @@ class Parser } try { + Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); $parsedValue = Inline::parse($value, $flags, $this->refs); if ('mapping' === $context && is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) { diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index d8c0718142..bb014e2d99 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -813,9 +813,9 @@ EOD; * @requires function Symfony\Bridge\PhpUnit\ErrorAssert::assertDeprecationsAreTriggered * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ - public function testParseExceptionOnDuplicate($input, $duplicate_key) + public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber) { - ErrorAssert::assertDeprecationsAreTriggered(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicates in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $duplicate_key), function () use ($input) { + ErrorAssert::assertDeprecationsAreTriggered(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $duplicateKey, $lineNumber), function () use ($input) { Yaml::parse($input); }); } @@ -827,25 +827,25 @@ EOD; $yaml = <<