feature #22762 [Yaml] Support tagged scalars (GuilhemN)

This PR was merged into the 4.0-dev branch.

Discussion
----------

[Yaml] Support tagged scalars

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes, replacement of deprecations
| BC breaks?    | yes
| Deprecations? | no <!-- don't forget updating UPGRADE-*.md files -->
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

Add support of tagged scalars in 4.0.

Commits
-------

b1e8ebc6ac [Yaml] Support tagged scalars
This commit is contained in:
Fabien Potencier 2017-07-06 13:27:33 +03:00
commit c5cbc83a59
4 changed files with 48 additions and 16 deletions

View File

@ -24,6 +24,12 @@ CHANGELOG
* the constructor arguments of the `Parser` class have been removed
* the `Inline` class is internal and no longer part of the BC promise
* removed support for the `!str` tag, use the `!!str` tag instead
* added support for tagged scalars.
```yml
Yaml::parse('!foo bar', Yaml::PARSE_CUSTOM_TAGS);
// returns TaggedValue('foo', 'bar');
```
3.4.0
-----

View File

@ -77,7 +77,7 @@ class Inline
$result = self::parseScalar($value, $flags, null, $i, null === $tag, $references);
}
if (null !== $tag) {
if (null !== $tag && '' !== $tag) {
return new TaggedValue($tag, $result);
}
@ -379,7 +379,7 @@ class Inline
--$i;
}
if (null !== $tag) {
if (null !== $tag && '' !== $tag) {
$value = new TaggedValue($tag, $value);
}
@ -489,7 +489,7 @@ class Inline
--$i;
}
if (null !== $tag) {
if (null !== $tag && '' !== $tag) {
$output[$key] = new TaggedValue($tag, $value);
} else {
$output[$key] = $value;
@ -582,7 +582,7 @@ class Inline
case 0 === strpos($scalar, '!!binary '):
return self::evaluateBinaryScalar(substr($scalar, 9));
default:
@trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar), E_USER_DEPRECATED);
throw new ParseException(sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar));
}
// Optimize for returning strings.
@ -650,20 +650,20 @@ class Inline
$nextOffset = $i + $tagLength + 1;
$nextOffset += strspn($value, ' ', $nextOffset);
// Is followed by a scalar
if (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) {
// Manage scalars in {@link self::evaluateScalar()}
// Is followed by a scalar and is a built-in tag
if ($tag && (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && ('!' === $tag[0] || 'str' === $tag || 0 === strpos($tag, 'php/const:') || 0 === strpos($tag, 'php/object:'))) {
// Manage in {@link self::evaluateScalar()}
return;
}
$i = $nextOffset;
// Built-in tags
if ($tag && '!' === $tag[0]) {
throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag));
}
if (Yaml::PARSE_CUSTOM_TAGS & $flags) {
$i = $nextOffset;
if ('' === $tag || Yaml::PARSE_CUSTOM_TAGS & $flags) {
return $tag;
}

View File

@ -621,12 +621,12 @@ class Parser
$data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers));
if ('' !== $matches['tag']) {
if ('' !== $matches['tag'] && '!' !== $matches['tag']) {
if ('!!binary' === $matches['tag']) {
return Inline::evaluateBinaryScalar($data);
} elseif ('!' !== $matches['tag']) {
@trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED);
}
return new TaggedValue(substr($matches['tag'], 1), $data);
}
return $data;

View File

@ -1542,6 +1542,18 @@ EOF;
public function taggedValuesProvider()
{
return array(
'scalars' => array(
array(
'foo' => new TaggedValue('inline', 'bar'),
'quz' => new TaggedValue('long', 'this is a long text'),
),
<<<YAML
foo: !inline bar
quz: !long >
this is a long
text
YAML
),
'sequences' => array(
array(new TaggedValue('foo', array('yaml')), new TaggedValue('quz', array('bar'))),
<<<YAML
@ -1569,6 +1581,11 @@ YAML
);
}
public function testNonSpecificTagSupport()
{
$this->assertSame('12', $this->parser->parse('! 12'));
}
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
* @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]").
@ -1579,12 +1596,21 @@ YAML
}
/**
* @group legacy
* @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
* @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator foo").
*/
public function testUnsupportedTagWithScalar()
{
$this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo'));
$this->parser->parse('!iterator foo');
}
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
* @expectedExceptionMessage The string "!!iterator foo" could not be parsed as it uses an unsupported built-in tag at line 1 (near "!!iterator foo").
*/
public function testUnsupportedBuiltInTagWithScalar()
{
$this->parser->parse('!!iterator foo');
}
/**