]>
Commit | Line | Data |
---|---|---|
4f5b44bd NL |
1 | <?php |
2 | ||
3 | /* | |
4 | * This file is part of Twig. | |
5 | * | |
6 | * (c) Fabien Potencier | |
7 | * | |
8 | * For the full copyright and license information, please view the LICENSE | |
9 | * file that was distributed with this source code. | |
10 | */ | |
11 | class Twig_Tests_LexerTest extends PHPUnit_Framework_TestCase | |
12 | { | |
13 | public function testNameLabelForTag() | |
14 | { | |
15 | $template = '{% § %}'; | |
16 | ||
17 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
18 | $stream = $lexer->tokenize($template); | |
19 | ||
20 | $stream->expect(Twig_Token::BLOCK_START_TYPE); | |
21 | $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue()); | |
22 | } | |
23 | ||
24 | public function testNameLabelForFunction() | |
25 | { | |
26 | $template = '{{ §() }}'; | |
27 | ||
28 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
29 | $stream = $lexer->tokenize($template); | |
30 | ||
31 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
32 | $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue()); | |
33 | } | |
34 | ||
35 | public function testBracketsNesting() | |
36 | { | |
37 | $template = '{{ {"a":{"b":"c"}} }}'; | |
38 | ||
39 | $this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '{')); | |
40 | $this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '}')); | |
41 | } | |
42 | ||
43 | protected function countToken($template, $type, $value = null) | |
44 | { | |
45 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
46 | $stream = $lexer->tokenize($template); | |
47 | ||
48 | $count = 0; | |
49 | $tokens = array(); | |
50 | while (!$stream->isEOF()) { | |
51 | $token = $stream->next(); | |
52 | if ($type === $token->getType()) { | |
53 | if (null === $value || $value === $token->getValue()) { | |
54 | ++$count; | |
55 | } | |
56 | } | |
57 | } | |
58 | ||
59 | return $count; | |
60 | } | |
61 | ||
62 | public function testLineDirective() | |
63 | { | |
64 | $template = "foo\n" | |
65 | . "bar\n" | |
66 | . "{% line 10 %}\n" | |
67 | . "{{\n" | |
68 | . "baz\n" | |
69 | . "}}\n"; | |
70 | ||
71 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
72 | $stream = $lexer->tokenize($template); | |
73 | ||
74 | // foo\nbar\n | |
75 | $this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine()); | |
76 | // \n (after {% line %}) | |
77 | $this->assertSame(10, $stream->expect(Twig_Token::TEXT_TYPE)->getLine()); | |
78 | // {{ | |
79 | $this->assertSame(11, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine()); | |
80 | // baz | |
81 | $this->assertSame(12, $stream->expect(Twig_Token::NAME_TYPE)->getLine()); | |
82 | } | |
83 | ||
84 | public function testLineDirectiveInline() | |
85 | { | |
86 | $template = "foo\n" | |
87 | . "bar{% line 10 %}{{\n" | |
88 | . "baz\n" | |
89 | . "}}\n"; | |
90 | ||
91 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
92 | $stream = $lexer->tokenize($template); | |
93 | ||
94 | // foo\nbar | |
95 | $this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine()); | |
96 | // {{ | |
97 | $this->assertSame(10, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine()); | |
98 | // baz | |
99 | $this->assertSame(11, $stream->expect(Twig_Token::NAME_TYPE)->getLine()); | |
100 | } | |
101 | ||
102 | public function testLongComments() | |
103 | { | |
104 | $template = '{# '.str_repeat('*', 100000).' #}'; | |
105 | ||
106 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
107 | $lexer->tokenize($template); | |
108 | ||
109 | // should not throw an exception | |
110 | } | |
111 | ||
112 | public function testLongRaw() | |
113 | { | |
114 | $template = '{% raw %}'.str_repeat('*', 100000).'{% endraw %}'; | |
115 | ||
116 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
117 | $stream = $lexer->tokenize($template); | |
118 | ||
119 | // should not throw an exception | |
120 | } | |
121 | ||
122 | public function testLongVar() | |
123 | { | |
124 | $template = '{{ '.str_repeat('x', 100000).' }}'; | |
125 | ||
126 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
127 | $stream = $lexer->tokenize($template); | |
128 | ||
129 | // should not throw an exception | |
130 | } | |
131 | ||
132 | public function testLongBlock() | |
133 | { | |
134 | $template = '{% '.str_repeat('x', 100000).' %}'; | |
135 | ||
136 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
137 | $stream = $lexer->tokenize($template); | |
138 | ||
139 | // should not throw an exception | |
140 | } | |
141 | ||
142 | public function testBigNumbers() | |
143 | { | |
144 | $template = '{{ 922337203685477580700 }}'; | |
145 | ||
146 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
147 | $stream = $lexer->tokenize($template); | |
148 | $node = $stream->next(); | |
149 | $node = $stream->next(); | |
150 | $this->assertEquals(922337203685477580700, $node->getValue()); | |
151 | } | |
152 | ||
153 | public function testStringWithEscapedDelimiter() | |
154 | { | |
155 | $tests = array( | |
156 | "{{ 'foo \' bar' }}" => 'foo \' bar', | |
157 | '{{ "foo \" bar" }}' => "foo \" bar", | |
158 | ); | |
159 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
160 | foreach ($tests as $template => $expected) { | |
161 | $stream = $lexer->tokenize($template); | |
162 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
163 | $stream->expect(Twig_Token::STRING_TYPE, $expected); | |
164 | } | |
165 | } | |
166 | ||
167 | public function testStringWithInterpolation() | |
168 | { | |
169 | $template = 'foo {{ "bar #{ baz + 1 }" }}'; | |
170 | ||
171 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
172 | $stream = $lexer->tokenize($template); | |
173 | $stream->expect(Twig_Token::TEXT_TYPE, 'foo '); | |
174 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
175 | $stream->expect(Twig_Token::STRING_TYPE, 'bar '); | |
176 | $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); | |
177 | $stream->expect(Twig_Token::NAME_TYPE, 'baz'); | |
178 | $stream->expect(Twig_Token::OPERATOR_TYPE, '+'); | |
179 | $stream->expect(Twig_Token::NUMBER_TYPE, '1'); | |
180 | $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); | |
181 | $stream->expect(Twig_Token::VAR_END_TYPE); | |
182 | } | |
183 | ||
184 | public function testStringWithEscapedInterpolation() | |
185 | { | |
186 | $template = '{{ "bar \#{baz+1}" }}'; | |
187 | ||
188 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
189 | $stream = $lexer->tokenize($template); | |
190 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
191 | $stream->expect(Twig_Token::STRING_TYPE, 'bar #{baz+1}'); | |
192 | $stream->expect(Twig_Token::VAR_END_TYPE); | |
193 | } | |
194 | ||
195 | public function testStringWithHash() | |
196 | { | |
197 | $template = '{{ "bar # baz" }}'; | |
198 | ||
199 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
200 | $stream = $lexer->tokenize($template); | |
201 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
202 | $stream->expect(Twig_Token::STRING_TYPE, 'bar # baz'); | |
203 | $stream->expect(Twig_Token::VAR_END_TYPE); | |
204 | } | |
205 | ||
206 | /** | |
207 | * @expectedException Twig_Error_Syntax | |
208 | * @expectedExceptionMessage Unclosed """ | |
209 | */ | |
210 | public function testStringWithUnterminatedInterpolation() | |
211 | { | |
212 | $template = '{{ "bar #{x" }}'; | |
213 | ||
214 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
215 | $stream = $lexer->tokenize($template); | |
216 | } | |
217 | ||
218 | public function testStringWithNestedInterpolations() | |
219 | { | |
220 | $template = '{{ "bar #{ "foo#{bar}" }" }}'; | |
221 | ||
222 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
223 | $stream = $lexer->tokenize($template); | |
224 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
225 | $stream->expect(Twig_Token::STRING_TYPE, 'bar '); | |
226 | $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); | |
227 | $stream->expect(Twig_Token::STRING_TYPE, 'foo'); | |
228 | $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); | |
229 | $stream->expect(Twig_Token::NAME_TYPE, 'bar'); | |
230 | $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); | |
231 | $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); | |
232 | $stream->expect(Twig_Token::VAR_END_TYPE); | |
233 | } | |
234 | ||
235 | public function testStringWithNestedInterpolationsInBlock() | |
236 | { | |
237 | $template = '{% foo "bar #{ "foo#{bar}" }" %}'; | |
238 | ||
239 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
240 | $stream = $lexer->tokenize($template); | |
241 | $stream->expect(Twig_Token::BLOCK_START_TYPE); | |
242 | $stream->expect(Twig_Token::NAME_TYPE, 'foo'); | |
243 | $stream->expect(Twig_Token::STRING_TYPE, 'bar '); | |
244 | $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); | |
245 | $stream->expect(Twig_Token::STRING_TYPE, 'foo'); | |
246 | $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); | |
247 | $stream->expect(Twig_Token::NAME_TYPE, 'bar'); | |
248 | $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); | |
249 | $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); | |
250 | $stream->expect(Twig_Token::BLOCK_END_TYPE); | |
251 | } | |
252 | ||
253 | public function testOperatorEndingWithALetterAtTheEndOfALine() | |
254 | { | |
255 | $template = "{{ 1 and\n0}}"; | |
256 | ||
257 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
258 | $stream = $lexer->tokenize($template); | |
259 | $stream->expect(Twig_Token::VAR_START_TYPE); | |
260 | $stream->expect(Twig_Token::NUMBER_TYPE, 1); | |
261 | $stream->expect(Twig_Token::OPERATOR_TYPE, 'and'); | |
262 | } | |
263 | ||
264 | /** | |
265 | * @expectedException Twig_Error_Syntax | |
266 | * @expectedExceptionMessage Unclosed "variable" at line 3 | |
267 | */ | |
268 | public function testUnterminatedVariable() | |
269 | { | |
270 | $template = ' | |
271 | ||
272 | {{ | |
273 | ||
274 | bar | |
275 | ||
276 | ||
277 | '; | |
278 | ||
279 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
280 | $stream = $lexer->tokenize($template); | |
281 | } | |
282 | ||
283 | /** | |
284 | * @expectedException Twig_Error_Syntax | |
285 | * @expectedExceptionMessage Unclosed "block" at line 3 | |
286 | */ | |
287 | public function testUnterminatedBlock() | |
288 | { | |
289 | $template = ' | |
290 | ||
291 | {% | |
292 | ||
293 | bar | |
294 | ||
295 | ||
296 | '; | |
297 | ||
298 | $lexer = new Twig_Lexer(new Twig_Environment()); | |
299 | $stream = $lexer->tokenize($template); | |
300 | } | |
301 | } |