mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-31 12:37:15 +00:00
Make {} optional for the types tag
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# 3.19.0 (2025-XX-XX)
|
||||
|
||||
* Make `{}` optional for the `types` tag
|
||||
* Add `LastModifiedExtensionInterface` and implementation in `AbstractExtension` to track modification of runtime classes
|
||||
|
||||
# 3.18.0 (2024-12-29)
|
||||
|
||||
+22
-9
@@ -6,17 +6,23 @@
|
||||
The ``types`` tag was added in Twig 3.13. This tag is **experimental** and
|
||||
can change based on usage and feedback.
|
||||
|
||||
The ``types`` tag declares the types of template variables.
|
||||
Use the ``types`` tag to declare the type of a variable:
|
||||
|
||||
.. note::
|
||||
.. code-block:: twig
|
||||
|
||||
The types declared in a template are local to that template and must not be
|
||||
propagated to included templates. This is because a template can be
|
||||
included from multiple different places, each potentially having different
|
||||
variable types.
|
||||
{% types is_correct: 'boolean' %}
|
||||
{% types score: 'number' %}
|
||||
|
||||
Here is how to declare that ``is_correct`` is a boolean, while ``score`` is a
|
||||
number (see note below):
|
||||
Or multiple variables:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
{% types
|
||||
is_correct: 'boolean',
|
||||
score: 'number',
|
||||
%}
|
||||
|
||||
You can also enclose types with ``{}``:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
@@ -25,7 +31,7 @@ number (see note below):
|
||||
score: 'number',
|
||||
} %}
|
||||
|
||||
You can declare variables as optional by adding the ``?`` suffix:
|
||||
Declare optional variables by adding a ``?`` suffix:
|
||||
|
||||
.. code-block:: twig
|
||||
|
||||
@@ -43,6 +49,13 @@ validate variables or their types, this tag enables extensions to do this.
|
||||
Additionally, :ref:`Twig extensions <creating_extensions>` can analyze these
|
||||
tags to perform compile-time and runtime analysis of templates.
|
||||
|
||||
.. note::
|
||||
|
||||
The types declared in a template are local to that template and must not be
|
||||
propagated to included templates. This is because a template can be
|
||||
included from multiple different places, each potentially having different
|
||||
variable types.
|
||||
|
||||
.. note::
|
||||
|
||||
The syntax for and contents of type strings are intentionally left out of
|
||||
|
||||
@@ -31,9 +31,7 @@ final class TypesTokenParser extends AbstractTokenParser
|
||||
public function parse(Token $token): Node
|
||||
{
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
$types = $this->parseSimpleMappingExpression($stream);
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new TypesNode($types, $token->getLine());
|
||||
@@ -46,17 +44,15 @@ final class TypesTokenParser extends AbstractTokenParser
|
||||
*/
|
||||
private function parseSimpleMappingExpression(TokenStream $stream): array
|
||||
{
|
||||
$stream->expect(Token::PUNCTUATION_TYPE, '{', 'A mapping element was expected');
|
||||
|
||||
$enclosed = null !== $stream->nextIf(Token::PUNCTUATION_TYPE, '{');
|
||||
$types = [];
|
||||
|
||||
$first = true;
|
||||
while (!$stream->test(Token::PUNCTUATION_TYPE, '}')) {
|
||||
while (!($stream->test(Token::PUNCTUATION_TYPE, '}') || $stream->test(Token::BLOCK_END_TYPE))) {
|
||||
if (!$first) {
|
||||
$stream->expect(Token::PUNCTUATION_TYPE, ',', 'A type string must be followed by a comma');
|
||||
|
||||
// trailing ,?
|
||||
if ($stream->test(Token::PUNCTUATION_TYPE, '}')) {
|
||||
if ($stream->test(Token::PUNCTUATION_TYPE, '}') || $stream->test(Token::BLOCK_END_TYPE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +74,10 @@ final class TypesTokenParser extends AbstractTokenParser
|
||||
'optional' => $isOptional,
|
||||
];
|
||||
}
|
||||
$stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened mapping is not properly closed');
|
||||
|
||||
if ($enclosed) {
|
||||
$stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened mapping is not properly closed');
|
||||
}
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,15 @@ class TypesTokenParserTest extends TestCase
|
||||
'baz' => ['type' => 'baz', 'optional' => false],
|
||||
],
|
||||
],
|
||||
|
||||
// without {} enclosing
|
||||
[
|
||||
'{% types foo: "foo", bar: "bar" %}',
|
||||
[
|
||||
'foo' => ['type' => 'foo', 'optional' => false],
|
||||
'bar' => ['type' => 'bar', 'optional' => false],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user