Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Yaml] parse mappings with a colon in a key #20841

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions src/Symfony/Component/Yaml/Inline.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,23 @@ public static function parseScalar($scalar, $delimiters = null, $stringDelimiter

if (null !== $delimiters) {
$tmp = ltrim(substr($scalar, $i), ' ');
if (!in_array($tmp[0], $delimiters)) {
$delimiterFound = false;

foreach ($delimiters as $delimiter) {
// usually, delimiters should be one-character strings
// in this case, we can save some function calls
if ($tmp[0] === $delimiter) {
$delimiterFound = true;
break;
}

if (substr($tmp, 0, strlen($delimiter)) === $delimiter) {
$delimiterFound = true;
break;
}
}

if (!$delimiterFound) {
throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)));
}
}
Expand Down Expand Up @@ -382,7 +398,15 @@ private static function parseMapping($mapping, &$i = 0, $references = array())
}

// key
$key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $i, false);
try {
// colons after YAML keys must be followed by a space
$positionBeforeKeyParsing = $i;
$key = self::parseScalar($mapping, array(': ', ' '), array('"', "'"), $i, false);
} catch (ParseException $e) {
// fall back to search for colons without a following space to support the legacy behavior
$key = self::parseScalar($mapping, array(':', ' '), array('"', "'"), $positionBeforeKeyParsing, false);
$i = $positionBeforeKeyParsing;
}

// value
$done = false;
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Component/Yaml/Tests/InlineTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ public function getTestsForParse()
array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')),
array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', array('foo\'' => 'bar', 'bar"' => 'foo: bar')),
array('{\'foo: \': \'bar\', "bar: ": \'foo: bar\'}', array('foo: ' => 'bar', 'bar: ' => 'foo: bar')),
array('{foo:bar: "baz"}', array('foo:bar' => 'baz')),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stof This was parsed differently before (it would have been parsed as ['foo' => 'bar: baz']).

Actually, I am really mixed about what to do here. But I could live with merging it into master to be completely safe.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as it was accepted before, we should indeed do it in master.

changing the behavior in a 2.7 patch release is too likely to break things silently.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, in master, it should still parse as before and generate a deprecation notice, and the behavior changed in 4.0.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then let's postpone this PR for 4.0. The deprecation should already be covered by #19504 if I didn't overlook any edge cases.

Copy link
Contributor

@GuilhemN GuilhemN Dec 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current deprecation is in part wrong, values such as {foo:[bar]} or {foo:} are valid, but the deprecation is triggered ({foo:} is not supported by the parser currently so for this one, I guess it's ok).

And what about replacing its message by The behaviour of colon not followed by an indicator (e.g " ", ",", "{", "}", "[", "]") is deprecated since 3.2. It will be considered as part of the value in 4.0.?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GuilhemN #20855 should fix that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, this is not valid YAML at all. However, we have to improve the deprecation handling (see #22829).

array('{foo:bar:baz}', array('foo' => 'bar:baz')),

// nested sequences and mappings
array('[foo, [bar, foo]]', array('foo', array('bar', 'foo'))),
Expand Down