1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package org.codehaus.groovy.syntax.parser;
35
36 import java.util.Iterator;
37 import java.util.List;
38
39 import org.codehaus.groovy.ast.ClassNode;
40 import org.codehaus.groovy.ast.MethodNode;
41 import org.codehaus.groovy.ast.ModuleNode;
42 import org.codehaus.groovy.ast.expr.BinaryExpression;
43 import org.codehaus.groovy.ast.expr.ClassExpression;
44 import org.codehaus.groovy.ast.expr.ClosureExpression;
45 import org.codehaus.groovy.ast.expr.ConstantExpression;
46 import org.codehaus.groovy.ast.expr.Expression;
47 import org.codehaus.groovy.ast.expr.MapEntryExpression;
48 import org.codehaus.groovy.ast.expr.MapExpression;
49 import org.codehaus.groovy.ast.expr.VariableExpression;
50 import org.codehaus.groovy.ast.stmt.BlockStatement;
51 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
52 import org.codehaus.groovy.ast.stmt.ForStatement;
53 import org.codehaus.groovy.ast.stmt.IfStatement;
54 import org.codehaus.groovy.ast.stmt.ReturnStatement;
55 import org.codehaus.groovy.control.CompilationFailedException;
56 import org.codehaus.groovy.runtime.InvokerHelper;
57 import org.codehaus.groovy.syntax.SyntaxException;
58 import org.codehaus.groovy.syntax.Types;
59 import org.codehaus.groovy.syntax.lexer.UnexpectedCharacterException;
60
61 /***
62 * Test case for the AST builder
63 *
64 * @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
65 * @version $Revision: 1.32 $
66 */
67 public class ASTBuilderTest extends TestParserSupport {
68
69 public void testStatementParsing() throws Exception {
70 ModuleNode module =
71 parse("import cheddar.cheese.Toast as Bread\n x = [1, 2, 3]; System.out.println(x)", "foo/Cheese.groovy");
72
73 BlockStatement block = module.getStatementBlock();
74 assertTrue("Contains some statements", !block.getStatements().isEmpty());
75
76
77 }
78
79 public void testBlock() throws Exception {
80 ModuleNode module =
81 parse("class Foo { void testMethod() { x = someMethod(); callMethod(x) } }", "Dummy.groovy");
82 BlockStatement statement = getCode(module, "testMethod");
83
84 assertEquals("Statements size: " + statement.getStatements(), 2, statement.getStatements().size());
85
86 System.out.println(statement.getStatements());
87 }
88
89 public void testSubscript() throws Exception {
90 ModuleNode module =
91 parse("class Foo { void testMethod() { x = 1\n [1].each { println(it) }} }", "Dummy.groovy");
92 BlockStatement statement = getCode(module, "testMethod");
93
94 assertEquals("Statements size: " + statement.getStatements(), 2, statement.getStatements().size());
95
96 for (Iterator iter = statement.getStatements().iterator(); iter.hasNext();) {
97 System.out.println(iter.next());
98 }
99 }
100
101 public void testNewlinesInsideExpresssions() throws Exception {
102 ModuleNode module = parse("class Foo { void testMethod() { x = 1 +\n 5 * \n 2 / \n 5 } }", "Dummy.groovy");
103 BlockStatement statement = getCode(module, "testMethod");
104
105 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
106
107 for (Iterator iter = statement.getStatements().iterator(); iter.hasNext();) {
108 System.out.println(iter.next());
109 }
110 }
111
112 public void testMethodCalls() throws Exception {
113 ModuleNode module =
114 parse(
115 "class Foo { void testMethod() { def array = getMockArguments()\n \n dummyMethod(array) } }",
116 "Dummy.groovy");
117 BlockStatement statement = getCode(module, "testMethod");
118
119 assertEquals("Statements size: " + statement.getStatements(), 2, statement.getStatements().size());
120
121 for (Iterator iter = statement.getStatements().iterator(); iter.hasNext();) {
122 System.out.println(iter.next());
123 }
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public void testForLoopWithType() throws Exception {
155 ModuleNode module = parse("class Foo { void testMethod() { for (Foo x in foo) { println x } } }", "Dummy.groovy");
156 BlockStatement statement = getCode(module, "testMethod");
157
158 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
159
160 ForStatement stmt = (ForStatement) statement.getStatements().get(0);
161 assertEquals("x", stmt.getVariable());
162 assertEquals("Foo", stmt.getVariableType().getName());
163 assertFalse(stmt.getVariableType().isDynamic());
164 System.out.println(stmt);
165 }
166
167 public void testSubscriptAssignment() throws Exception {
168 ModuleNode module = parse("class Foo { void testMethod() { x[12] = 'abc' } }", "Dummy.groovy");
169 BlockStatement statement = getCode(module, "testMethod");
170
171 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
172
173 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
174 Expression exp = exprStmt.getExpression();
175 System.out.println(exp);
176
177 assertTrue(exp instanceof BinaryExpression);
178 BinaryExpression binExpr = (BinaryExpression) exp;
179 assertTrue("RHS is constant", binExpr.getRightExpression() instanceof ConstantExpression);
180
181 Expression lhs = binExpr.getLeftExpression();
182 assertTrue("LHS is binary expression", lhs instanceof BinaryExpression);
183
184 BinaryExpression lhsBinExpr = (BinaryExpression) lhs;
185 assertEquals(Types.LEFT_SQUARE_BRACKET, lhsBinExpr.getOperation().getType());
186
187 assertTrue("Left of LHS is a variable", lhsBinExpr.getLeftExpression() instanceof VariableExpression);
188 assertTrue("Right of LHS is a constant", lhsBinExpr.getRightExpression() instanceof ConstantExpression);
189
190 }
191
192 public void testNoReturn() throws Exception {
193 ModuleNode module = parse("class Foo { void testMethod() { x += 5 } }", "Dummy.groovy");
194 BlockStatement statement = getCode(module, "testMethod");
195
196 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
197
198 System.out.println(statement.getStatements());
199
200 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
201 Expression exp = exprStmt.getExpression();
202
203 System.out.println("expr: " + exp);
204 }
205
206 public void testCastExpression() throws Exception {
207 ModuleNode module = parse("class Foo { void testMethod() { x = (Short) 5 } }", "Dummy.groovy");
208 BlockStatement statement = getCode(module, "testMethod");
209
210 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
211
212 System.out.println(statement.getStatements());
213
214 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
215 Expression exp = exprStmt.getExpression();
216
217 System.out.println("expr: " + exp);
218 }
219
220 public void testTernaryExpression() throws Exception {
221 ModuleNode module = parse("class Foo { void testMethod() { foo() ? 'a' : 'b' } }", "Dummy.groovy");
222 BlockStatement statement = getCode(module, "testMethod");
223
224 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
225
226 System.out.println(statement.getStatements());
227
228 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
229 Expression exp = exprStmt.getExpression();
230
231 System.out.println("expr: " + exp);
232 }
233
234 public void testClosureWithJustIdentifierBug() throws Exception {
235 ModuleNode module = parse("class Foo { void testMethod() { return {a} } }", "Dummy.groovy");
236 BlockStatement statement = getCode(module, "testMethod");
237
238 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
239
240 System.out.println(statement.getStatements());
241
242 ReturnStatement returnStmt = (ReturnStatement)statement.getStatements().get(0);
243 Expression exp = returnStmt.getExpression();
244
245 System.out.println("expr: " + exp);
246 }
247
248 public void testClosureWithJustIdentifierInMapBug() throws Exception {
249 ModuleNode module = parse("class Foo { void testMethod() { ['x':{a}, 'd':123] } }", "Dummy.groovy");
250 BlockStatement statement = getCode(module, "testMethod");
251
252 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
253
254 System.out.println(statement.getStatements());
255
256 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
257
258 MapExpression mapExp = (MapExpression) exprStmt.getExpression();
259 MapEntryExpression entryExp = (MapEntryExpression) mapExp.getMapEntryExpressions().get(0);
260 ClosureExpression closureExp = (ClosureExpression) entryExp.getValueExpression();
261 assertEquals("Parameters on closure", 0, closureExp.getParameters().length);
262 System.out.println("expr: " + closureExp);
263 }
264
265 public void testArrayExpression() throws Exception {
266 ModuleNode module = parse("class Foo { void testMethod() { def foo = ['a', 'b', 'c'] as String[]\n assert foo != null } }", "Dummy.groovy");
267 BlockStatement statement = getCode(module, "testMethod");
268
269 assertEquals("Statements size: " + statement.getStatements(), 2, statement.getStatements().size());
270
271 System.out.println(statement.getStatements());
272
273 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
274 Expression exp = exprStmt.getExpression();
275
276 System.out.println("expr: " + exp);
277 }
278
279 public void testArrayExpression2() throws Exception {
280 ModuleNode module = parse("class Foo { void testMethod() { String[] foo = ['a', 'b', 'c']\n assert foo != null } }", "Dummy.groovy");
281 BlockStatement statement = getCode(module, "testMethod");
282
283 assertEquals("Statements size: " + statement.getStatements(), 2, statement.getStatements().size());
284
285 System.out.println(statement.getStatements());
286
287 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
288 Expression exp = exprStmt.getExpression();
289
290 System.out.println("expr: " + exp);
291 }
292
293 public void testTypedVariableExpression() throws Exception {
294 ModuleNode module = parse("class Foo { void testMethod() { Short x = 5 } }", "Dummy.groovy");
295 BlockStatement statement = getCode(module, "testMethod");
296
297 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
298
299 System.out.println(statement.getStatements());
300
301 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
302 Expression exp = exprStmt.getExpression();
303
304 System.out.println("expr: " + exp);
305 }
306
307 public void testFullyQualifiedType() throws Exception {
308 ModuleNode module = parse("class Foo { void testMethod() { com.acme.Foo } }", "Dummy.groovy");
309 BlockStatement statement = getCode(module, "testMethod");
310
311 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
312
313 System.out.println(statement.getStatements());
314
315 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
316 Expression exp = exprStmt.getExpression();
317
318 System.out.println("expr: " + exp);
319
320 System.out.println("text: " + exp.getText());
321 }
322
323 public void testDoubleSubscript() throws Exception {
324 ModuleNode module = parse("class Foo { void testMethod() { x = foo[0][0] } }", "Dummy.groovy");
325 BlockStatement statement = getCode(module, "testMethod");
326
327 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
328
329 System.out.println(statement.getStatements());
330
331 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
332 Expression exp = exprStmt.getExpression();
333
334 System.out.println("expr: " + exp);
335
336 System.out.println("text: " + exp.getText());
337 }
338
339 public void testMethodCallWithDotAndNoParenthesis() throws Exception {
340 ModuleNode module = parse("class Foo { void testMethod() { foo.someMethod 1 } }", "Dummy.groovy");
341 BlockStatement statement = getCode(module, "testMethod");
342
343 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
344
345 System.out.println(statement.getStatements());
346
347 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
348 Expression exp = exprStmt.getExpression();
349
350 System.out.println("expr: " + exp);
351
352 System.out.println("text: " + exp.getText());
353 }
354
355 public void testMethodCallWithNoParenthesis() throws Exception {
356 ModuleNode module = parse("class Foo { void testMethod() { someMethod 1 } }", "Dummy.groovy");
357 BlockStatement statement = getCode(module, "testMethod");
358
359 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
360
361 System.out.println(statement.getStatements());
362
363 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
364 Expression exp = exprStmt.getExpression();
365
366 System.out.println("expr: " + exp);
367
368 System.out.println("text: " + exp.getText());
369 }
370
371 public void testScriptMethodCallWithNoParenthesis() throws Exception {
372 ModuleNode module = parse("someMethod 1", "Dummy.groovy");
373 BlockStatement statement = getCode(module, "run");
374
375 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
376
377 System.out.println(statement.getStatements());
378
379 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
380 Expression exp = exprStmt.getExpression();
381
382 System.out.println("expr: " + exp);
383
384 System.out.println("text: " + exp.getText());
385 }
386
387 public void testScriptWithMethodDeclaration() throws Exception {
388 ModuleNode module = parse("def foo(a) { return a + 1}\n foo(123)", "Dummy.groovy");
389 BlockStatement statement = getCode(module, "run");
390
391 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
392
393 System.out.println(statement.getStatements());
394
395 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
396 Expression exp = exprStmt.getExpression();
397
398 System.out.println("expr: " + exp);
399
400 System.out.println("text: " + exp.getText());
401 }
402
403 public void testSubscriptThenMethod() throws Exception {
404 ModuleNode module = parse("class Foo { void testMethod() { x = foo[0].foo() } }", "Dummy.groovy");
405 BlockStatement statement = getCode(module, "testMethod");
406
407 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
408
409 System.out.println(statement.getStatements());
410
411 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
412 Expression exp = exprStmt.getExpression();
413
414 System.out.println("expr: " + exp);
415
416 System.out.println("text: " + exp.getText());
417 }
418
419 public void testSubscriptThenOperation() throws Exception {
420 ModuleNode module = parse("class Foo { void testMethod() { foo[0] += 5 } }", "Dummy.groovy");
421 BlockStatement statement = getCode(module, "testMethod");
422
423 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
424
425 System.out.println(statement.getStatements());
426
427 ExpressionStatement exprStmt = (ExpressionStatement) statement.getStatements().get(0);
428 Expression exp = exprStmt.getExpression();
429
430 System.out.println("expr: " + exp);
431
432 System.out.println("text: " + exp.getText());
433 }
434
435
436 public void testRodsBug() throws Exception {
437 ModuleNode module = parse("class Foo { void testMethod() { if (x) { String n = 'foo' } } }", "Dummy.groovy");
438 BlockStatement statement = getCode(module, "testMethod");
439
440 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
441
442 System.out.println(statement.getStatements());
443
444 IfStatement ifStmt = (IfStatement) statement.getStatements().get(0);
445 BlockStatement trueStmt = (BlockStatement) ifStmt.getIfBlock();
446
447 System.out.println("trueStmt: " + trueStmt);
448
449
450 assertEquals(1, trueStmt.getStatements().size());
451 }
452
453 public void testStaticMethodCallBug() throws Exception {
454 ModuleNode module =
455 parse("class Foo { void testMethod() { ASTBuilderTest.mockHelperMethod() } }", "Dummy.groovy");
456 BlockStatement statement = getCode(module, "testMethod");
457
458 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
459
460 System.out.println(statement.getStatements());
461 }
462
463 public void testInstanceofBug() throws Exception {
464 ModuleNode module =
465 parse("class Foo { void testMethod() { if (foo instanceof java.util.List) { println('hello') } } }", "Dummy.groovy");
466 BlockStatement statement = getCode(module, "testMethod");
467
468 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
469
470 System.out.println(statement.getStatements());
471
472 IfStatement ifStmt = (IfStatement) statement.getStatements().get(0);
473 BinaryExpression exp = (BinaryExpression) ifStmt.getBooleanExpression().getExpression();
474
475 System.out.println("exp: " + exp);
476
477 Expression rhs = exp.getRightExpression();
478 assertTrue("RHS should be a class expression", rhs instanceof ClassExpression);
479
480 ClassExpression classExp = (ClassExpression) rhs;
481 assertEquals("java.util.List", classExp.getType());
482 }
483
484 public void testMethodCallWithoutParensBug() throws Exception {
485 ModuleNode module = parse("class Foo { void testMethod() { println 3, 5 } }", "Dummy.groovy");
486 BlockStatement statement = getCode(module, "testMethod");
487
488 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
489
490 System.out.println(statement.getStatements());
491 }
492
493 public void testReturnMethodClosure() throws Exception {
494 ModuleNode module = parse("class Foo { void testMethod() { System.out.println\n}}", "Dummy.groovy");
495 BlockStatement statement = getCode(module, "testMethod");
496
497 assertEquals("Statements size: " + statement.getStatements(), 1, statement.getStatements().size());
498
499 System.out.println(statement.getStatements());
500 }
501
502 public void testDionsTypo() throws Exception {
503 String script = "class Foo { void testMethod() { println ${foo}\n}}";
504 try {
505 ModuleNode module = parse(script, "Dummy.groovy");
506 } catch (Exception e) {
507
508
509
510 return;
511
512
513 }
514 fail(script+" should fail because the { was unexpected after the dollar sign.");
515 }
516
517 public void testMethodWithArrayTypeParam() throws Exception {
518 ModuleNode module = parse("class Foo { void main(String[] args) { println(args) } }", "Dummy.groovy");
519
520 MethodNode method = getMethod(module, "main");
521
522 System.out.println("Parameters: " + InvokerHelper.toString(method.getParameters()));
523 }
524
525 private void ensureOutOfRange(String script) throws Exception {
526 try {
527 ModuleNode module = parse(script, "Dummy.groovy");
528 } catch (Exception e) {
529
530
531
532 return;
533
534
535 }
536 fail(script+" should fail because the number is out of range.");
537 }
538
539 private void ensureInRange(String script) throws Exception {
540 ModuleNode module = parse(script, "Dummy.groovy");
541 }
542
543 public void testLiteralIntegerRange() throws Exception {
544 ensureInRange( "def x = 2147483647I;");
545 ensureOutOfRange("def x = 2147483648I;");
546
547 ensureInRange( "def x = -2147483648I;");
548 ensureOutOfRange("def x = -2147483649I;");
549 }
550
551 public void testLiteralLongRange() throws Exception {
552 ensureInRange( "def x = 9223372036854775807L;");
553 ensureOutOfRange("def x = 9223372036854775808L;");
554
555 ensureInRange( "def x = -9223372036854775808L;");
556 ensureOutOfRange("def x = -9223372036854775809L;");
557 }
558
559 public void testLiteralDoubleRange() throws Exception {
560 ensureInRange( "def x = 1.7976931348623157E308D;");
561 ensureOutOfRange("def x = 1.7976931348623167E308D;");
562
563 ensureInRange( "def x = -1.7976931348623157E308D;");
564 ensureOutOfRange("def x = -1.7976931348623167E308D;");
565 }
566
567 public void testLiteralFloatRange() throws Exception {
568 ensureInRange( "def x = 3.4028235e+38f;");
569 ensureOutOfRange("def x = 3.4028236e+38f;");
570
571 ensureInRange( "def x = -3.4028235e+38f;");
572 ensureOutOfRange("def x = -3.4028236e+38f;");
573 }
574
575 public void testLiteralIntegerBadSuffix() throws Exception {
576 try {
577 ModuleNode module = parse("def x = 2147483648J;", "Dummy.groovy");
578 } catch (Exception e) {
579
580
581
582 return;
583
584
585 }
586 fail("x = 2147483648J, should fail because J is an invalid numeric literal suffix.");
587 }
588
589 public void testLiteralBadExponent() throws Exception {
590 try {
591 ModuleNode module = parse("def x = 2.3e;", "Dummy.groovy");
592 } catch (Exception e) {
593
594
595
596 return;
597
598
599 }
600 fail("x = 2.3e, should fail because no exponent is specified.");
601 }
602
603 public static Object mockHelperMethod() {
604 return "cheese";
605 }
606
607 protected BlockStatement getCode(ModuleNode module, String name) {
608 MethodNode method = getMethod(module, name);
609
610 BlockStatement statement = (BlockStatement) method.getCode();
611 assertNotNull(statement);
612 return statement;
613 }
614
615 protected MethodNode getMethod(ModuleNode module, String name) {
616 assertEquals("class count", 1, module.getClasses().size());
617
618 ClassNode node = (ClassNode) module.getClasses().get(0);
619
620 assertNotNull(node);
621
622 List methods = node.getDeclaredMethods(name);
623 assertTrue(methods.size() > 0);
624 return (MethodNode) methods.get(0);
625 }
626 }