4 * This file is part of Twig.
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
11 class Twig_Tests_LexerTest extends \PHPUnit\Framework\TestCase
16 public function testLegacyConstructorSignature()
18 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
19 $stream = $lexer->tokenize('{{ foo }}', 'foo');
20 $this->assertEquals('foo', $stream->getFilename());
21 $this->assertEquals('{{ foo }}', $stream->getSource());
24 public function testNameLabelForTag()
26 $template = '{% § %}';
28 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
29 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
31 $stream->expect(Twig_Token::BLOCK_START_TYPE);
32 $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
35 public function testNameLabelForFunction()
37 $template = '{{ §() }}';
39 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
40 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
42 $stream->expect(Twig_Token::VAR_START_TYPE);
43 $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue());
46 public function testBracketsNesting()
48 $template = '{{ {"a":{"b":"c"}} }}';
50 $this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '{'));
51 $this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '}'));
54 protected function countToken($template, $type, $value = null)
56 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
57 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
60 while (!$stream->isEOF()) {
61 $token = $stream->next();
62 if ($type === $token->getType()) {
63 if (null === $value || $value === $token->getValue()) {
72 public function testLineDirective()
81 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
82 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
85 $this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
86 // \n (after {% line %})
87 $this->assertSame(10, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
89 $this->assertSame(11, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine());
91 $this->assertSame(12, $stream->expect(Twig_Token::NAME_TYPE)->getLine());
94 public function testLineDirectiveInline()
97 ."bar{% line 10 %}{{\n"
101 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
102 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
105 $this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine());
107 $this->assertSame(10, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine());
109 $this->assertSame(11, $stream->expect(Twig_Token::NAME_TYPE)->getLine());
112 public function testLongComments()
114 $template = '{# '.str_repeat('*', 100000).' #}';
116 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
117 $lexer->tokenize(new Twig_Source($template, 'index'));
119 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
120 // can be executed without throwing any exceptions
121 $this->addToAssertionCount(1);
124 public function testLongVerbatim()
126 $template = '{% verbatim %}'.str_repeat('*', 100000).'{% endverbatim %}';
128 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
129 $lexer->tokenize(new Twig_Source($template, 'index'));
131 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
132 // can be executed without throwing any exceptions
133 $this->addToAssertionCount(1);
136 public function testLongVar()
138 $template = '{{ '.str_repeat('x', 100000).' }}';
140 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
141 $lexer->tokenize(new Twig_Source($template, 'index'));
143 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
144 // can be executed without throwing any exceptions
145 $this->addToAssertionCount(1);
148 public function testLongBlock()
150 $template = '{% '.str_repeat('x', 100000).' %}';
152 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
153 $lexer->tokenize(new Twig_Source($template, 'index'));
155 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
156 // can be executed without throwing any exceptions
157 $this->addToAssertionCount(1);
160 public function testBigNumbers()
162 $template = '{{ 922337203685477580700 }}';
164 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
165 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
167 $node = $stream->next();
168 $this->assertEquals('922337203685477580700', $node->getValue());
171 public function testStringWithEscapedDelimiter()
174 "{{ 'foo \' bar' }}" => 'foo \' bar',
175 '{{ "foo \" bar" }}' => 'foo " bar',
177 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
178 foreach ($tests as $template => $expected) {
179 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
180 $stream->expect(Twig_Token::VAR_START_TYPE);
181 $stream->expect(Twig_Token::STRING_TYPE, $expected);
183 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
184 // can be executed without throwing any exceptions
185 $this->addToAssertionCount(1);
189 public function testStringWithInterpolation()
191 $template = 'foo {{ "bar #{ baz + 1 }" }}';
193 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
194 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
195 $stream->expect(Twig_Token::TEXT_TYPE, 'foo ');
196 $stream->expect(Twig_Token::VAR_START_TYPE);
197 $stream->expect(Twig_Token::STRING_TYPE, 'bar ');
198 $stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
199 $stream->expect(Twig_Token::NAME_TYPE, 'baz');
200 $stream->expect(Twig_Token::OPERATOR_TYPE, '+');
201 $stream->expect(Twig_Token::NUMBER_TYPE, '1');
202 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
203 $stream->expect(Twig_Token::VAR_END_TYPE);
205 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
206 // can be executed without throwing any exceptions
207 $this->addToAssertionCount(1);
210 public function testStringWithEscapedInterpolation()
212 $template = '{{ "bar \#{baz+1}" }}';
214 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
215 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
216 $stream->expect(Twig_Token::VAR_START_TYPE);
217 $stream->expect(Twig_Token::STRING_TYPE, 'bar #{baz+1}');
218 $stream->expect(Twig_Token::VAR_END_TYPE);
220 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
221 // can be executed without throwing any exceptions
222 $this->addToAssertionCount(1);
225 public function testStringWithHash()
227 $template = '{{ "bar # baz" }}';
229 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
230 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
231 $stream->expect(Twig_Token::VAR_START_TYPE);
232 $stream->expect(Twig_Token::STRING_TYPE, 'bar # baz');
233 $stream->expect(Twig_Token::VAR_END_TYPE);
235 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
236 // can be executed without throwing any exceptions
237 $this->addToAssertionCount(1);
241 * @expectedException Twig_Error_Syntax
242 * @expectedExceptionMessage Unclosed """
244 public function testStringWithUnterminatedInterpolation()
246 $template = '{{ "bar #{x" }}';
248 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
249 $lexer->tokenize(new Twig_Source($template, 'index'));
252 public function testStringWithNestedInterpolations()
254 $template = '{{ "bar #{ "foo#{bar}" }" }}';
256 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
257 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
258 $stream->expect(Twig_Token::VAR_START_TYPE);
259 $stream->expect(Twig_Token::STRING_TYPE, 'bar ');
260 $stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
261 $stream->expect(Twig_Token::STRING_TYPE, 'foo');
262 $stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
263 $stream->expect(Twig_Token::NAME_TYPE, 'bar');
264 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
265 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
266 $stream->expect(Twig_Token::VAR_END_TYPE);
268 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
269 // can be executed without throwing any exceptions
270 $this->addToAssertionCount(1);
273 public function testStringWithNestedInterpolationsInBlock()
275 $template = '{% foo "bar #{ "foo#{bar}" }" %}';
277 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
278 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
279 $stream->expect(Twig_Token::BLOCK_START_TYPE);
280 $stream->expect(Twig_Token::NAME_TYPE, 'foo');
281 $stream->expect(Twig_Token::STRING_TYPE, 'bar ');
282 $stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
283 $stream->expect(Twig_Token::STRING_TYPE, 'foo');
284 $stream->expect(Twig_Token::INTERPOLATION_START_TYPE);
285 $stream->expect(Twig_Token::NAME_TYPE, 'bar');
286 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
287 $stream->expect(Twig_Token::INTERPOLATION_END_TYPE);
288 $stream->expect(Twig_Token::BLOCK_END_TYPE);
290 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
291 // can be executed without throwing any exceptions
292 $this->addToAssertionCount(1);
295 public function testOperatorEndingWithALetterAtTheEndOfALine()
297 $template = "{{ 1 and\n0}}";
299 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
300 $stream = $lexer->tokenize(new Twig_Source($template, 'index'));
301 $stream->expect(Twig_Token::VAR_START_TYPE);
302 $stream->expect(Twig_Token::NUMBER_TYPE, 1);
303 $stream->expect(Twig_Token::OPERATOR_TYPE, 'and');
305 // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above
306 // can be executed without throwing any exceptions
307 $this->addToAssertionCount(1);
311 * @expectedException Twig_Error_Syntax
312 * @expectedExceptionMessage Unclosed "variable" in "index" at line 3
314 public function testUnterminatedVariable()
325 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
326 $lexer->tokenize(new Twig_Source($template, 'index'));
330 * @expectedException Twig_Error_Syntax
331 * @expectedExceptionMessage Unclosed "block" in "index" at line 3
333 public function testUnterminatedBlock()
344 $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
345 $lexer->tokenize(new Twig_Source($template, 'index'));