From 5157402a779638b9bb804435ddd2faab08bb294a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 16 Jun 2024 17:59:12 +0200 Subject: [PATCH] Rename hash to mapping --- CHANGELOG | 2 ++ doc/coding_standards.rst | 6 ++--- doc/deprecated.rst | 6 +++++ doc/filters/merge.rst | 4 ++-- doc/filters/replace.rst | 2 +- doc/tags/with.rst | 6 ++--- doc/templates.rst | 12 +++++----- doc/tests/empty.rst | 2 +- src/ExpressionParser.php | 24 +++++++++++++------ src/Node/WithNode.php | 2 +- tests/ExpressionParserTest.php | 10 ++++---- ...ator.test => spread_mapping_operator.test} | 2 +- ...with_no_hash.test => with_no_mapping.test} | 6 ++--- 13 files changed, 51 insertions(+), 33 deletions(-) rename tests/Fixtures/expressions/{spread_hash_operator.test => spread_mapping_operator.test} (95%) rename tests/Fixtures/tags/with/{with_no_hash.test => with_no_mapping.test} (56%) diff --git a/CHANGELOG b/CHANGELOG index 73bf3ba61..54d3a847b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,8 @@ # 3.11.0 (2024-XX-XX) * Deprecate the second argument of `Twig\Node\Expression\CallExpression::compileArguments()` + * Deprecate `Twig\ExpressionParser\parseHashExpression()` in favor of + `Twig\ExpressionParser::parseMappingExpression()` # 3.10.3 (2024-05-16) diff --git a/doc/coding_standards.rst b/doc/coding_standards.rst index 310cc8c43..f7bdb43c2 100644 --- a/doc/coding_standards.rst +++ b/doc/coding_standards.rst @@ -40,8 +40,8 @@ standards: {{ foo ~ bar }} {{ true ? true : false }} -* Put exactly one space after the ``:`` sign in hashes and ``,`` in - arrays and hashes: +* Put exactly one space after the ``:`` sign in mappings and ``,`` in arrays + and mappings: .. code-block:: twig @@ -81,7 +81,7 @@ standards: {{ range(1..10) }} * Do not put any spaces before and after the opening and the closing of arrays - and hashes: + and mappings: .. code-block:: twig diff --git a/doc/deprecated.rst b/doc/deprecated.rst index 4b4493af5..91b6d9329 100644 --- a/doc/deprecated.rst +++ b/doc/deprecated.rst @@ -45,6 +45,12 @@ Node Visitors * The ``Twig\NodeVisitor\AbstractNodeVisitor`` class is deprecated, implement the ``Twig\NodeVisitor\NodeVisitorInterface`` interface instead. +Parser +------ + +* The ``Twig\ExpressionParser::parseHashExpression()`` method is deprecated, use + ``Twig\ExpressionParser::parseMappingExpression()`` instead. + Templates --------- diff --git a/doc/filters/merge.rst b/doc/filters/merge.rst index b1d75c40b..633dcf75f 100644 --- a/doc/filters/merge.rst +++ b/doc/filters/merge.rst @@ -13,7 +13,7 @@ The ``merge`` filter merges an array with another array: New values are added at the end of the existing ones. -The ``merge`` filter also works on hashes: +The ``merge`` filter also works on mappings: .. code-block:: twig @@ -23,7 +23,7 @@ The ``merge`` filter also works on hashes: {# items now contains {'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car', 'renault': 'car'} #} -For hashes, the merging process occurs on the keys: if the key does not +For mappings, the merging process occurs on the keys: if the key does not already exist, it is added but if the key already exists, its value is overridden. diff --git a/doc/filters/replace.rst b/doc/filters/replace.rst index 0c38b73bf..63e7f4800 100644 --- a/doc/filters/replace.rst +++ b/doc/filters/replace.rst @@ -17,7 +17,7 @@ format is free-form): Arguments --------- -* ``from``: The placeholder values as a hash +* ``from``: The placeholder values as a mapping .. seealso:: diff --git a/doc/tags/with.rst b/doc/tags/with.rst index 420c82ac6..268bb373d 100644 --- a/doc/tags/with.rst +++ b/doc/tags/with.rst @@ -13,8 +13,8 @@ scope are not visible outside of the scope: foo is not visible here any longer Instead of defining variables at the beginning of the scope, you can pass a -hash of variables you want to define in the ``with`` tag; the previous example -is equivalent to the following one: +mapping of variables you want to define in the ``with`` tag; the previous +example is equivalent to the following one: .. code-block:: twig @@ -23,7 +23,7 @@ is equivalent to the following one: {% endwith %} foo is not visible here any longer - {# it works with any expression that resolves to a hash #} + {# it works with any expression that resolves to a mapping #} {% set vars = {foo: 42} %} {% with vars %} ... diff --git a/doc/templates.rst b/doc/templates.rst index 1026dd8ea..0acc1c8d9 100644 --- a/doc/templates.rst +++ b/doc/templates.rst @@ -534,7 +534,7 @@ exist: * ``["foo", "bar"]``: Arrays are defined by a sequence of expressions separated by a comma (``,``) and wrapped with squared brackets (``[]``). -* ``{"foo": "bar"}``: Hashes are defined by a list of keys and values +* ``{"foo": "bar"}``: Mappings are defined by a list of keys and values separated by a comma (``,``) and wrapped with curly braces (``{}``): .. code-block:: twig @@ -542,7 +542,7 @@ exist: {# keys as string #} {'foo': 'foo', 'bar': 'bar'} - {# keys as names (equivalent to the previous hash) #} + {# keys as names (equivalent to the previous mapping) #} {foo: 'foo', bar: 'bar'} {# keys as integer #} @@ -563,7 +563,7 @@ exist: * ``null``: ``null`` represents no specific value. This is the value returned when a variable does not exist. ``none`` is an alias for ``null``. -Arrays and hashes can be nested: +Arrays and mappings can be nested: .. code-block:: twig @@ -785,8 +785,8 @@ The following operators don't fit into any of the other categories: {# returns the value of foo if it is defined and not null, 'no' otherwise #} {{ foo ?? 'no' }} -* ``...``: The spread operator can be used to expand arrays or hashes (it cannot - be used to expand the arguments of a function call): +* ``...``: The spread operator can be used to expand arrays or mappings (it + cannot be used to expand the arguments of a function call): .. code-block:: twig @@ -827,7 +827,7 @@ Operator Score of precedence Description ``**`` 200 Raises a number to the power of another ``??`` 300 Default value when a variable is null ``+``, ``-`` 500 Unary operations on numbers -``|``,``[]``,``.`` - Filters, array, hash, and attribute access +``|``,``[]``,``.`` - Filters, array, mapping, and attribute access ============================= =================================== ===================================================== Without using any parentheses, the operator precedence rules are used to diff --git a/doc/tests/empty.rst b/doc/tests/empty.rst index 0233eca48..6348f92ae 100644 --- a/doc/tests/empty.rst +++ b/doc/tests/empty.rst @@ -2,7 +2,7 @@ ========= ``empty`` checks if a variable is an empty string, an empty array, an empty -hash, exactly ``false``, or exactly ``null``. +mapping, exactly ``false``, or exactly ``null``. For objects that implement the ``Countable`` interface, ``empty`` will check the return value of the ``count()`` method. diff --git a/src/ExpressionParser.php b/src/ExpressionParser.php index 4be649341..443c7daa1 100644 --- a/src/ExpressionParser.php +++ b/src/ExpressionParser.php @@ -280,7 +280,7 @@ class ExpressionParser if ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '[')) { $node = $this->parseArrayExpression(); } elseif ($token->test(/* Token::PUNCTUATION_TYPE */ 9, '{')) { - $node = $this->parseHashExpression(); + $node = $this->parseMappingExpression(); } elseif ($token->test(/* Token::OPERATOR_TYPE */ 8, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { throw new SyntaxError(\sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); } else { @@ -351,16 +351,26 @@ class ExpressionParser return $node; } + /** + * @deprecated since 3.11, use parseMappingExpression() instead + */ public function parseHashExpression() + { + trigger_deprecation('twig/twig', '3.11', 'Calling "%s()" is deprecated, use "parseMappingExpression()" instead.', __METHOD__); + + return $this->parseMappingExpression(); + } + + public function parseMappingExpression() { $stream = $this->parser->getStream(); - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '{', 'A hash element was expected'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '{', 'A mapping element was expected'); $node = new ArrayExpression([], $stream->getCurrent()->getLine()); $first = true; while (!$stream->test(/* Token::PUNCTUATION_TYPE */ 9, '}')) { if (!$first) { - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'A hash value must be followed by a comma'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ',', 'A mapping value must be followed by a comma'); // trailing ,? if ($stream->test(/* Token::PUNCTUATION_TYPE */ 9, '}')) { @@ -377,7 +387,7 @@ class ExpressionParser continue; } - // a hash key can be: + // a mapping key can be: // // * a number -- 12 // * a string -- 'a' @@ -399,15 +409,15 @@ class ExpressionParser } else { $current = $stream->getCurrent(); - throw new SyntaxError(\sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); + throw new SyntaxError(\sprintf('A mapping key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ':', 'A hash key must be followed by a colon (:)'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, ':', 'A mapping key must be followed by a colon (:)'); $value = $this->parseExpression(); $node->addElement($value, $key); } - $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '}', 'An opened hash is not properly closed'); + $stream->expect(/* Token::PUNCTUATION_TYPE */ 9, '}', 'An opened mapping is not properly closed'); return $node; } diff --git a/src/Node/WithNode.php b/src/Node/WithNode.php index c78136c81..a7b7e70d9 100644 --- a/src/Node/WithNode.php +++ b/src/Node/WithNode.php @@ -49,7 +49,7 @@ class WithNode extends Node ->raw(";\n") ->write(\sprintf("if (!is_iterable(\$%s)) {\n", $varsName)) ->indent() - ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.', ") + ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a mapping.', ") ->repr($node->getTemplateLine()) ->raw(", \$this->getSourceContext());\n") ->outdent() diff --git a/tests/ExpressionParserTest.php b/tests/ExpressionParserTest.php index bb000225a..e00c2598d 100644 --- a/tests/ExpressionParserTest.php +++ b/tests/ExpressionParserTest.php @@ -111,7 +111,7 @@ class ExpressionParserTest extends TestCase ], 1), ], - // simple hash + // simple mapping ['{{ {"a": "b", "b": "c"} }}', new ArrayExpression([ new ConstantExpression('a', 1), new ConstantExpression('b', 1), @@ -121,7 +121,7 @@ class ExpressionParserTest extends TestCase ], 1), ], - // hash with trailing , + // mapping with trailing , ['{{ {"a": "b", "b": "c", } }}', new ArrayExpression([ new ConstantExpression('a', 1), new ConstantExpression('b', 1), @@ -131,7 +131,7 @@ class ExpressionParserTest extends TestCase ], 1), ], - // hash in an array + // mapping in an array ['{{ [1, {"a": "b", "b": "c"}] }}', new ArrayExpression([ new ConstantExpression(0, 1), new ConstantExpression(1, 1), @@ -147,7 +147,7 @@ class ExpressionParserTest extends TestCase ], 1), ], - // array in a hash + // array in a mapping ['{{ {"a": [1, 2], "b": "c"} }}', new ArrayExpression([ new ConstantExpression('a', 1), new ArrayExpression([ @@ -181,7 +181,7 @@ class ExpressionParserTest extends TestCase $this->createNameExpression('foo', ['spread' => true]), ], 1)], - // hash with spread operator + // mapping with spread operator ['{{ {"a": "b", "b": "c", ...otherLetters} }}', new ArrayExpression([ new ConstantExpression('a', 1), diff --git a/tests/Fixtures/expressions/spread_hash_operator.test b/tests/Fixtures/expressions/spread_mapping_operator.test similarity index 95% rename from tests/Fixtures/expressions/spread_hash_operator.test rename to tests/Fixtures/expressions/spread_mapping_operator.test index c2429f00e..e944eee8a 100644 --- a/tests/Fixtures/expressions/spread_hash_operator.test +++ b/tests/Fixtures/expressions/spread_mapping_operator.test @@ -1,5 +1,5 @@ --TEST-- -Twig supports the spread operator on hashes +Twig supports the spread operator on mappings --TEMPLATE-- {% for key, value in { firstName: 'Ryan', lastName: 'Weaver', favoriteFood: 'popcorn', ...{favoriteFood: 'pizza', sport: 'running'} } %} {{ key }}: {{ value }} diff --git a/tests/Fixtures/tags/with/with_no_hash.test b/tests/Fixtures/tags/with/with_no_mapping.test similarity index 56% rename from tests/Fixtures/tags/with/with_no_hash.test rename to tests/Fixtures/tags/with/with_no_mapping.test index 7083050b4..7b22c5171 100644 --- a/tests/Fixtures/tags/with/with_no_hash.test +++ b/tests/Fixtures/tags/with/with_no_mapping.test @@ -1,10 +1,10 @@ --TEST-- -"with" tag with an expression that is not a hash +"with" tag with an expression that is not a mapping --TEMPLATE-- {% with vars %} {{ foo }}{{ bar }} {% endwith %} --DATA-- -return ['vars' => 'no-hash'] +return ['vars' => 'no-mapping'] --EXCEPTION-- -Twig\Error\RuntimeError: Variables passed to the "with" tag must be a hash in "index.twig" at line 2. +Twig\Error\RuntimeError: Variables passed to the "with" tag must be a mapping in "index.twig" at line 2.