ParserTest.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\ExpressionLanguage\Tests;
  11. use PHPUnit\Framework\TestCase;
  12. use Symfony\Component\ExpressionLanguage\Lexer;
  13. use Symfony\Component\ExpressionLanguage\Node;
  14. use Symfony\Component\ExpressionLanguage\Parser;
  15. class ParserTest extends TestCase
  16. {
  17. /**
  18. * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError
  19. * @expectedExceptionMessage Variable "foo" is not valid around position 1 for expression `foo`.
  20. */
  21. public function testParseWithInvalidName()
  22. {
  23. $lexer = new Lexer();
  24. $parser = new Parser([]);
  25. $parser->parse($lexer->tokenize('foo'));
  26. }
  27. /**
  28. * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError
  29. * @expectedExceptionMessage Variable "foo" is not valid around position 1 for expression `foo`.
  30. */
  31. public function testParseWithZeroInNames()
  32. {
  33. $lexer = new Lexer();
  34. $parser = new Parser([]);
  35. $parser->parse($lexer->tokenize('foo'), [0]);
  36. }
  37. /**
  38. * @dataProvider getParseData
  39. */
  40. public function testParse($node, $expression, $names = [])
  41. {
  42. $lexer = new Lexer();
  43. $parser = new Parser([]);
  44. $this->assertEquals($node, $parser->parse($lexer->tokenize($expression), $names));
  45. }
  46. public function getParseData()
  47. {
  48. $arguments = new Node\ArgumentsNode();
  49. $arguments->addElement(new Node\ConstantNode('arg1'));
  50. $arguments->addElement(new Node\ConstantNode(2));
  51. $arguments->addElement(new Node\ConstantNode(true));
  52. return [
  53. [
  54. new Node\NameNode('a'),
  55. 'a',
  56. ['a'],
  57. ],
  58. [
  59. new Node\ConstantNode('a'),
  60. '"a"',
  61. ],
  62. [
  63. new Node\ConstantNode(3),
  64. '3',
  65. ],
  66. [
  67. new Node\ConstantNode(false),
  68. 'false',
  69. ],
  70. [
  71. new Node\ConstantNode(true),
  72. 'true',
  73. ],
  74. [
  75. new Node\ConstantNode(null),
  76. 'null',
  77. ],
  78. [
  79. new Node\UnaryNode('-', new Node\ConstantNode(3)),
  80. '-3',
  81. ],
  82. [
  83. new Node\BinaryNode('-', new Node\ConstantNode(3), new Node\ConstantNode(3)),
  84. '3 - 3',
  85. ],
  86. [
  87. new Node\BinaryNode('*',
  88. new Node\BinaryNode('-', new Node\ConstantNode(3), new Node\ConstantNode(3)),
  89. new Node\ConstantNode(2)
  90. ),
  91. '(3 - 3) * 2',
  92. ],
  93. [
  94. new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode('bar', true), new Node\ArgumentsNode(), Node\GetAttrNode::PROPERTY_CALL),
  95. 'foo.bar',
  96. ['foo'],
  97. ],
  98. [
  99. new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode('bar', true), new Node\ArgumentsNode(), Node\GetAttrNode::METHOD_CALL),
  100. 'foo.bar()',
  101. ['foo'],
  102. ],
  103. [
  104. new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode('not', true), new Node\ArgumentsNode(), Node\GetAttrNode::METHOD_CALL),
  105. 'foo.not()',
  106. ['foo'],
  107. ],
  108. [
  109. new Node\GetAttrNode(
  110. new Node\NameNode('foo'),
  111. new Node\ConstantNode('bar', true),
  112. $arguments,
  113. Node\GetAttrNode::METHOD_CALL
  114. ),
  115. 'foo.bar("arg1", 2, true)',
  116. ['foo'],
  117. ],
  118. [
  119. new Node\GetAttrNode(new Node\NameNode('foo'), new Node\ConstantNode(3), new Node\ArgumentsNode(), Node\GetAttrNode::ARRAY_CALL),
  120. 'foo[3]',
  121. ['foo'],
  122. ],
  123. [
  124. new Node\ConditionalNode(new Node\ConstantNode(true), new Node\ConstantNode(true), new Node\ConstantNode(false)),
  125. 'true ? true : false',
  126. ],
  127. [
  128. new Node\BinaryNode('matches', new Node\ConstantNode('foo'), new Node\ConstantNode('/foo/')),
  129. '"foo" matches "/foo/"',
  130. ],
  131. // chained calls
  132. [
  133. $this->createGetAttrNode(
  134. $this->createGetAttrNode(
  135. $this->createGetAttrNode(
  136. $this->createGetAttrNode(new Node\NameNode('foo'), 'bar', Node\GetAttrNode::METHOD_CALL),
  137. 'foo', Node\GetAttrNode::METHOD_CALL),
  138. 'baz', Node\GetAttrNode::PROPERTY_CALL),
  139. '3', Node\GetAttrNode::ARRAY_CALL),
  140. 'foo.bar().foo().baz[3]',
  141. ['foo'],
  142. ],
  143. [
  144. new Node\NameNode('foo'),
  145. 'bar',
  146. ['foo' => 'bar'],
  147. ],
  148. ];
  149. }
  150. private function createGetAttrNode($node, $item, $type)
  151. {
  152. return new Node\GetAttrNode($node, new Node\ConstantNode($item, Node\GetAttrNode::ARRAY_CALL !== $type), new Node\ArgumentsNode(), $type);
  153. }
  154. /**
  155. * @dataProvider getInvalidPostfixData
  156. * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError
  157. */
  158. public function testParseWithInvalidPostfixData($expr, $names = [])
  159. {
  160. $lexer = new Lexer();
  161. $parser = new Parser([]);
  162. $parser->parse($lexer->tokenize($expr), $names);
  163. }
  164. public function getInvalidPostfixData()
  165. {
  166. return [
  167. [
  168. 'foo."#"',
  169. ['foo'],
  170. ],
  171. [
  172. 'foo."bar"',
  173. ['foo'],
  174. ],
  175. [
  176. 'foo.**',
  177. ['foo'],
  178. ],
  179. [
  180. 'foo.123',
  181. ['foo'],
  182. ],
  183. ];
  184. }
  185. /**
  186. * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError
  187. * @expectedExceptionMessage Did you mean "baz"?
  188. */
  189. public function testNameProposal()
  190. {
  191. $lexer = new Lexer();
  192. $parser = new Parser([]);
  193. $parser->parse($lexer->tokenize('foo > bar'), ['foo', 'baz']);
  194. }
  195. }