|
Groovy example source code file (AstBuilderFromSpecificationTest.groovy)
The Groovy AstBuilderFromSpecificationTest.groovy source codepackage org.codehaus.groovy.ast.builder import org.codehaus.groovy.syntax.Token import org.codehaus.groovy.syntax.Types import org.codehaus.groovy.ast.* import org.codehaus.groovy.ast.expr.* import org.codehaus.groovy.ast.stmt.* import static org.objectweb.asm.Opcodes.ACC_PUBLIC import static org.objectweb.asm.Opcodes.ACC_STATIC /** * Unit test for the AST from Psuedo-specification feature. * @author Hamlet D'Arcy */ public class AstBuilderFromSpecificationTest extends GroovyTestCase { public void testSimpleMethodCall() { def result = new AstBuilder().buildFromSpec { methodCall { variable "this" constant "println" argumentList { constant "Hello" } } } def expected = new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( [new ConstantExpression("Hello")] ) ) AstAssert.assertSyntaxTree([expected], result) } public void testErrorHandling_TooManyArguments() { def message = shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { methodCall { constant "four arguments" constant "is too" constant "many for" constant "this method" } } } assertTrue("Unhelpful error message: $message", message.contains('methodCall could not be invoked')) assertTrue("Unhelpful error message: $message", message.contains('Expected to receive')) assertTrue("Unhelpful error message: $message", message.contains('but found')) } public void testErrorHandling_WrongArgumentTypes() { def message = shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { methodCall { returnStatement { constant 1 } constant "ignored" empty() } } } assertTrue("Unhelpful error message: $message", message.contains('methodCall could not be invoked')) assertTrue("Unhelpful error message: $message", message.contains('Expected to receive')) assertTrue("Unhelpful error message: $message", message.contains('but found')) } public void testAnnotationConstantExpression() { def result = new AstBuilder().buildFromSpec { annotationConstant { annotation Override } } def expected = new AnnotationConstantExpression( new AnnotationNode( ClassHelper.make(Override.class, false) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testArgumentListExpression_NoArgs() { def result = new AstBuilder().buildFromSpec { argumentList() } def expected = new ArgumentListExpression() AstAssert.assertSyntaxTree([expected], result) } public void testArgumentListExpression_OneListArg() { def result = new AstBuilder().buildFromSpec { argumentList { constant "constant1" constant "constant2" constant "constant3" constant "constant4" } } def expected = new ArgumentListExpression( [new ConstantExpression("constant1"), new ConstantExpression("constant2"), new ConstantExpression("constant3"), new ConstantExpression("constant4"), ] ) AstAssert.assertSyntaxTree([expected], result) } public void testAttributeExpression() { // represents foo.bar attribute invocation def result = new AstBuilder().buildFromSpec { attribute { variable "foo" constant "bar" } } def expected = new AttributeExpression( new VariableExpression("foo"), new ConstantExpression("bar") ) AstAssert.assertSyntaxTree([expected], result) } /** * Test for code: * if (foo == bar) println "Hello" else println "World" */ public void testIfStatement() { // if (foo == bar) println "Hello" else println "World" def result = new AstBuilder().buildFromSpec { ifStatement { booleanExpression { binary { variable "foo" token "==" variable "bar" } } //if block expression { // NOTE: if block and else block are order dependent and same type methodCall { variable "this" constant "println" argumentList { constant "Hello" } } } //else block expression { methodCall { variable "this" constant "println" argumentList { constant "World" } } } } } def expected = new IfStatement( new BooleanExpression( new BinaryExpression( new VariableExpression("foo"), new Token(Types.COMPARE_EQUAL, "==", -1, -1), new VariableExpression("bar") ) ), new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( [new ConstantExpression("Hello")] ) ) ), new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( [new ConstantExpression("World")] ) ) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testDeclarationAndListExpression() { // represents def foo = [1, 2, 3] def result = new AstBuilder().buildFromSpec { declaration { variable "foo" token "=" list { constant 1 constant 2 constant 3 } } } def expected = new DeclarationExpression( new VariableExpression("foo"), new Token(Types.EQUALS, "=", -1, -1), new ListExpression( [new ConstantExpression(1), new ConstantExpression(2), new ConstantExpression(3),] ) ) AstAssert.assertSyntaxTree([expected], result) } public void testArrayExpression() { // new Integer[]{1, 2, 3} def result = new AstBuilder().buildFromSpec { array(Integer) { constant 1 constant 2 constant 3 } } def expected = new ArrayExpression( ClassHelper.make(Integer, false), [ new ConstantExpression(1), new ConstantExpression(2), new ConstantExpression(3),] ) AstAssert.assertSyntaxTree([expected], result) } public void testBitwiseNegationExpression() { def result = new AstBuilder().buildFromSpec { bitwiseNegation { constant 1 } } def expected = new BitwiseNegationExpression( new ConstantExpression(1) ) AstAssert.assertSyntaxTree([expected], result) } public void testCastExpression() { def result = new AstBuilder().buildFromSpec { cast(Integer) { constant "" } } def expected = new CastExpression( ClassHelper.make(Integer, false), new ConstantExpression("") ) AstAssert.assertSyntaxTree([expected], result) } public void testClosureExpression() { // { parm -> println parm } def result = new AstBuilder().buildFromSpec { closure { parameters { parameter 'parm': Object.class } block { expression { methodCall { variable "this" constant "println" argumentList { variable "parm" } } } } } } def expected = new ClosureExpression( [new Parameter( ClassHelper.make(Object, false), "parm" )] as Parameter[], new BlockStatement( [new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( new VariableExpression("parm") ) ) )], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testClosureExpression_MultipleParameters() { // { x,y,z -> println z } def result = new AstBuilder().buildFromSpec { closure { parameters { parameter 'x': Object.class parameter 'y': Object.class parameter 'z': Object.class } block { expression { methodCall { variable "this" constant "println" argumentList { variable "z" } } } } } } def expected = new ClosureExpression( [ new Parameter(ClassHelper.make(Object, false), "x"), new Parameter(ClassHelper.make(Object, false), "y"), new Parameter(ClassHelper.make(Object, false), "z")] as Parameter[], new BlockStatement( [new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( new VariableExpression("z") ) ) )], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testConstructorCallExpression() { // new Integer(4) def result = new AstBuilder().buildFromSpec { constructorCall(Integer) { argumentList { constant 4 } } } def expected = new ConstructorCallExpression( ClassHelper.make(Integer, false), new ArgumentListExpression( new ConstantExpression(4) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testNotExpression() { // !true def result = new AstBuilder().buildFromSpec { not { constant true } } def expected = new NotExpression( new ConstantExpression(true) ) AstAssert.assertSyntaxTree([expected], result) } public void testPostfixExpression() { // 1++ def result = new AstBuilder().buildFromSpec { postfix { constant 1 token "++" } } def expected = new PostfixExpression( new ConstantExpression(1), new Token(Types.PLUS_PLUS, "++", -1, -1) ) AstAssert.assertSyntaxTree([expected], result) } public void testPrefixExpression() { // ++1 def result = new AstBuilder().buildFromSpec { prefix { token "++" constant 1 } } def expected = new PrefixExpression( new Token(Types.PLUS_PLUS, "++", -1, -1), new ConstantExpression(1) ) AstAssert.assertSyntaxTree([expected], result) } public void testUnaryMinusExpression() { // (-foo) def result = new AstBuilder().buildFromSpec { unaryMinus { variable "foo" } } def expected = new UnaryMinusExpression( new VariableExpression("foo") ) AstAssert.assertSyntaxTree([expected], result) } public void testUnaryPlusExpression() { // (+foo) def result = new AstBuilder().buildFromSpec { unaryPlus { variable "foo" } } def expected = new UnaryPlusExpression( new VariableExpression("foo") ) AstAssert.assertSyntaxTree([expected], result) } public void testClassExpression() { // def foo = String def result = new AstBuilder().buildFromSpec { declaration { variable "foo" token "=" classExpression String } } def expected = new DeclarationExpression( new VariableExpression("foo"), new Token(Types.EQUALS, "=", -1, -1), new ClassExpression(ClassHelper.make(String, false)) ) AstAssert.assertSyntaxTree([expected], result) } public void testFieldExpression() { // public static String foo = "a value" def result = new AstBuilder().buildFromSpec { field { fieldNode "foo", ACC_PUBLIC & ACC_STATIC, String, this.class, { constant "a value" } } } def expected = new FieldExpression( new FieldNode( "foo", ACC_PUBLIC & ACC_STATIC, ClassHelper.make(String, false), ClassHelper.make(this.class, false), new ConstantExpression("a value") ) ) AstAssert.assertSyntaxTree([expected], result) } public void testMapAndMapEntryExpression() { // [foo: 'bar', baz: 'buz'] def result = new AstBuilder().buildFromSpec { map { mapEntry { constant 'foo' constant 'bar' } mapEntry { constant 'baz' constant 'buz' } } } def expected = new MapExpression( [ new MapEntryExpression( new ConstantExpression('foo'), new ConstantExpression('bar') ), new MapEntryExpression( new ConstantExpression('baz'), new ConstantExpression('buz') ), ] ) AstAssert.assertSyntaxTree([expected], result) } public void testMapAndMapEntryExpression_SimpleCase() { // [foo: 'bar', baz: 'buz'] def result = new AstBuilder().buildFromSpec { map { mapEntry 'foo': 'bar' // NOTE: this really only works for constants. mapEntry 'baz': 'buz' mapEntry 'qux': 'quux', 'corge': 'grault' } } def expected = new MapExpression( [ new MapEntryExpression( new ConstantExpression('foo'), new ConstantExpression('bar') ), new MapEntryExpression( new ConstantExpression('baz'), new ConstantExpression('buz') ), new MapEntryExpression( new ConstantExpression('qux'), new ConstantExpression('quux') ), new MapEntryExpression( new ConstantExpression('corge'), new ConstantExpression('grault') ), ] ) AstAssert.assertSyntaxTree([expected], result) } public void testGStringExpression() { // "$foo" def result = new AstBuilder().buildFromSpec { gString '$foo astring $bar', { strings { constant '' constant ' astring ' constant '' } values { variable 'foo' variable 'bar' } } } def expected = new GStringExpression('$foo astring $bar', [new ConstantExpression(''), new ConstantExpression(' astring '), new ConstantExpression('')], [new VariableExpression('foo'), new VariableExpression('bar')]) AstAssert.assertSyntaxTree([expected], result) } public void testMethodPointerExpression() { // Integer.&toString def result = new AstBuilder().buildFromSpec { methodPointer { classExpression Integer constant "toString" } } def expected = new MethodPointerExpression( new ClassExpression(ClassHelper.make(Integer, false)), new ConstantExpression("toString") ) AstAssert.assertSyntaxTree([expected], result) } public void testRangeExpression() { // (0..10) def result = new AstBuilder().buildFromSpec { range { constant 0 constant 10 inclusive true } } def expected = new RangeExpression( new ConstantExpression(0), new ConstantExpression(10), true ) AstAssert.assertSyntaxTree([expected], result) } public void testRangeExpression_Exclusive() { // (0..10) def result = new AstBuilder().buildFromSpec { range { constant 0 constant 10 inclusive false } } def expected = new RangeExpression( new ConstantExpression(0), new ConstantExpression(10), false ) AstAssert.assertSyntaxTree([expected], result) } public void testRangeExpression_SimpleForm() { // (0..10) def result = new AstBuilder().buildFromSpec { range(0..10) } def expected = new RangeExpression( new ConstantExpression(0), new ConstantExpression(10), true ) AstAssert.assertSyntaxTree([expected], result) } public void testPropertyExpression() { // foo.bar def result = new AstBuilder().buildFromSpec { property { // this name conflicts with PropertyNode. variable "foo" constant "bar" } } def expected = new PropertyExpression( new VariableExpression("foo"), new ConstantExpression("bar") ) AstAssert.assertSyntaxTree([expected], result) } public void testSwitchAndCaseAndBreakStatements() { /* switch (foo) { case 0: break "some label" case 1: case 2: println "<3" break; default: println ">2" } */ def result = new AstBuilder().buildFromSpec { switchStatement { //NOTE: switchStatement is abnormal pattern variable "foo" defaultCase { // NOTE: this creates a block statement expression { //NOTE: default branch is problematic b/c it is order dependent methodCall { variable "this" constant "println" argumentList { constant ">2" } } } } caseStatement { constant 0 breakStatement "some label" // label parameter is optional } caseStatement { constant 1 empty() } caseStatement { constant 2 block { expression { methodCall { variable "this" constant "println" argumentList { constant "<3" } } } breakStatement() } } } } def expected = new SwitchStatement( new VariableExpression("foo"), [ new CaseStatement( new ConstantExpression(0), new BreakStatement("some label") ), new CaseStatement( new ConstantExpression(1), new EmptyStatement() ), new CaseStatement( new ConstantExpression(2), new BlockStatement( [ new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( [new ConstantExpression("<3")] ) ) ), new BreakStatement() ], new VariableScope() ) ) ], new BlockStatement( [new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( [new ConstantExpression(">2")] ) ) )], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testAssertStatement() { /* assert true : "should always be true" assert 1 == 2 */ def result = new AstBuilder().buildFromSpec { block { assertStatement { booleanExpression { constant true } constant "should always be true" } assertStatement { booleanExpression { binary { constant 1 token "==" constant 2 } } } } } def expected = new BlockStatement( [ new AssertStatement( new BooleanExpression( new ConstantExpression(true) ), new ConstantExpression("should always be true") ), new AssertStatement( new BooleanExpression( new BinaryExpression( new ConstantExpression(1), new Token(Types.COMPARE_EQUAL, "==", -1, -1), new ConstantExpression(2) ) ) ), ], new VariableScope() ) AstAssert.assertSyntaxTree([expected], result) } public void testReturnAndSynchronizedStatement() { /* synchronized (this) { return 1 } */ def result = new AstBuilder().buildFromSpec { synchronizedStatement { variable "this" block { returnStatement { constant 1 } } } } def expected = new SynchronizedStatement( new VariableExpression("this"), new BlockStatement( [new ReturnStatement( new ConstantExpression(1) )], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testTryCatchAndCatchAndThrowStatements() { /* try { return 1 } catch (Exception e) { throw e } */ def result = new AstBuilder().buildFromSpec { tryCatch { block { returnStatement { constant 1 } } empty() //finally block must be specified? catchStatement { parameter 'e': Exception.class block { throwStatement { variable "e" } } } } } TryCatchStatement expected = new TryCatchStatement( new BlockStatement( [new ReturnStatement( new ConstantExpression(1) )], new VariableScope() ), new EmptyStatement() ) expected.addCatch( new CatchStatement( new Parameter( ClassHelper.make(Exception, false), "e" ), new BlockStatement( [new ThrowStatement( new VariableExpression("e") )], new VariableScope() ) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testFinallyStatement() { /* try { return 1 } finally { x.close() } */ def result = new AstBuilder().buildFromSpec { tryCatch { block { returnStatement { constant 1 } } block { block { expression { methodCall { variable 'x' constant 'close' argumentList() } } } } } } TryCatchStatement expected = new TryCatchStatement( new BlockStatement( [new ReturnStatement( new ConstantExpression(1) )], new VariableScope() ), new BlockStatement( [ new BlockStatement( [ new ExpressionStatement( new MethodCallExpression( new VariableExpression('x'), 'close', new ArgumentListExpression() ) ) ], new VariableScope()) ], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testForStatementAndClosureListExpression() { /* for (int x = 0; x < 10; x++) { println x } */ def result = new AstBuilder().buildFromSpec { forStatement { parameter 'forLoopDummyParameter': Object.class closureList { declaration { variable 'x' token '=' constant 0 } binary { variable 'x' token '<' constant 10 } postfix { variable 'x' token '++' } } block { expression { methodCall { variable 'this' constant 'println' argumentList { variable 'x' } } } } } } def expected = new ForStatement( new Parameter(ClassHelper.make(Object, false), "forLoopDummyParameter"), new ClosureListExpression( [ new DeclarationExpression( new VariableExpression("x"), new Token(Types.EQUALS, "=", -1, -1), new ConstantExpression(0) ), new BinaryExpression( new VariableExpression("x"), new Token(Types.COMPARE_LESS_THAN, "<", -1, -1), new ConstantExpression(10) ), new PostfixExpression( new VariableExpression("x"), new Token(Types.PLUS_PLUS, "++", -1, -1) ) ] ), new BlockStatement( [ new ExpressionStatement( new MethodCallExpression( new VariableExpression("this"), new ConstantExpression("println"), new ArgumentListExpression( new VariableExpression("x"), ) ) ) ], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testStaticMethodCallExpression_MethodAsString() { // Math.min(1,2) def result = new AstBuilder().buildFromSpec { staticMethodCall(Math, "min") { argumentList { constant 1 constant 2 } } } def expected = new StaticMethodCallExpression( ClassHelper.make(Math, false), "min", new ArgumentListExpression( new ConstantExpression(1), new ConstantExpression(2) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testStaticMethodCallExpression_PassingMethodPointer() { // Math.min(1,2) def result = new AstBuilder().buildFromSpec { staticMethodCall(Math.&min) { // more terse way to call existing methods argumentList { constant 1 constant 2 } } } def expected = new StaticMethodCallExpression( ClassHelper.make(Math, false), "min", new ArgumentListExpression( new ConstantExpression(1), new ConstantExpression(2) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testSpreadExpression() { // todo: what source code generates this node type? def result = new AstBuilder().buildFromSpec { spread { list { constant 'foo' constant 'bar' } } } def expected = new SpreadExpression( new ListExpression([ new ConstantExpression('foo'), new ConstantExpression('bar'), ]) ) AstAssert.assertSyntaxTree([expected], result) } public void testSpreadMapExpression() { // func (*:m) def result = new AstBuilder().buildFromSpec { methodCall { variable 'this' constant 'func' mapEntry { spreadMap { variable 'm' } variable 'm' } } } def expected = new MethodCallExpression( new VariableExpression('this', ClassHelper.make(Object, false)), 'func', new MapEntryExpression( new SpreadMapExpression( new VariableExpression('m', ClassHelper.make(Object, false)) ), new VariableExpression('m', ClassHelper.make(Object, false)) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testTernaryExpression() { // true ? "male" : "female" def result = new AstBuilder().buildFromSpec { ternary { booleanExpression { constant true } constant 'male' constant 'female' } } def expected = new TernaryExpression( new BooleanExpression( new ConstantExpression(true) ), new ConstantExpression('male'), new ConstantExpression('female') ) AstAssert.assertSyntaxTree([expected], result) } public void testDoWhileStatement() { // DoWhileStatement doesn't seemed to be used, and the do/while source doesn't compile either } public void testStatement() { // Statement is used as an abstract class within the groovy source and is never instantiated } public void testWhileStatementAndContinueStatement() { /* while (true) { x++ continue } */ def result = new AstBuilder().buildFromSpec { whileStatement { booleanExpression { constant true } block { expression { postfix { variable 'x' token '++' } } continueStatement() } } } def expected = new WhileStatement( new BooleanExpression( new ConstantExpression(true) ), new BlockStatement( [ new ExpressionStatement( new PostfixExpression( new VariableExpression("x"), new Token(Types.PLUS_PLUS, "++", -1, -1), ) ), new ContinueStatement() ], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testWhileStatementAndContinueToLabelStatement() { /* while (true) { x++ continue "some label" } */ def result = new AstBuilder().buildFromSpec { whileStatement { booleanExpression { constant true } block { expression { postfix { variable 'x' token '++' } } continueStatement { label "some label" } } } } def expected = new WhileStatement( new BooleanExpression( new ConstantExpression(true) ), new BlockStatement( [ new ExpressionStatement( new PostfixExpression( new VariableExpression("x"), new Token(Types.PLUS_PLUS, "++", -1, -1), ) ), new ContinueStatement("some label") ], new VariableScope() ) ) AstAssert.assertSyntaxTree([expected], result) } public void testElvisOperatorExpression() { // name ?: 'Anonymous' def result = new AstBuilder().buildFromSpec { elvisOperator { booleanExpression { variable 'name' } constant 'Anonymous' } } def expected = new ElvisOperatorExpression( new BooleanExpression( new VariableExpression('name') ), new ConstantExpression('Anonymous') ) AstAssert.assertSyntaxTree([expected], result) } public void testNamedArgumentListExpression() { // new String(foo: 'bar') def result = new AstBuilder().buildFromSpec { constructorCall(String) { tuple { namedArgumentList { mapEntry { constant 'foo' constant 'bar' } } } } } def expected = new ConstructorCallExpression( ClassHelper.make(String), new TupleExpression( new NamedArgumentListExpression( [ new MapEntryExpression( new ConstantExpression('foo'), new ConstantExpression('bar'), ) ] ) ) ) AstAssert.assertSyntaxTree([expected], result) } public void testParameters_DefaultValues() { /* public String myMethod(String parameter = null) { 'some result' } */ def result = new AstBuilder().buildFromSpec { method('myMethod', ACC_PUBLIC, String) { parameters { parameter 'parameter': String.class, { constant null } } exceptions {} block { returnStatement { constant 'some result' } } annotations {} } } def expected = new MethodNode( "myMethod", ACC_PUBLIC, ClassHelper.make(String.class, false), [new Parameter(ClassHelper.make(String, false), "parameter", new ConstantExpression(null))] as Parameter[], [] as ClassNode[], new BlockStatement( [new ReturnStatement( new ConstantExpression('some result') )], new VariableScope() )) AstAssert.assertSyntaxTree([expected], result) } public void testParameters_VarArgs() { /* public String myMethod(String... parameters) { 'some result' } */ // vararg methods are just array methods. def result = new AstBuilder().buildFromSpec { method('myMethod', ACC_PUBLIC, String) { parameters { parameter 'parameters': String[].class } exceptions {} block { returnStatement { constant 'some result' } } } } def expected = new MethodNode( "myMethod", ACC_PUBLIC, ClassHelper.make(String.class, false), [new Parameter(ClassHelper.make(String[], false), "parameters")] as Parameter[], [] as ClassNode[], new BlockStatement( [new ReturnStatement( new ConstantExpression('some result') )], new VariableScope() )) AstAssert.assertSyntaxTree([expected], result) } public void testInnerClassNode() { /* class Foo { static class Bar { } } */ def result = new AstBuilder().buildFromSpec { innerClass 'Foo$Bar', ACC_PUBLIC, { //outer class classNode 'Foo', ACC_PUBLIC, { classNode Object //superclass interfaces { classNode GroovyObject } mixins {} } classNode Object //superclass interfaces { classNode GroovyObject } mixins {} } } def expected = new InnerClassNode( new ClassNode( "Foo", ACC_PUBLIC, ClassHelper.make(Object, false), [ClassHelper.make(GroovyObject, false)] as ClassNode[], [] as MixinNode[] ), 'Foo$Bar', ACC_PUBLIC, ClassHelper.make(Object, false), [ClassHelper.make(GroovyObject, false)] as ClassNode[], [] as MixinNode[] ) AstAssert.assertSyntaxTree([expected], result) } public void testAnnotatedNode() { // this class is never instantiated. It is used as an abstract class but not marked as such. } public void testConstructorNode() { // public <init>(String foo, Integer bar) throws IOException, Exception {} def result = new AstBuilder().buildFromSpec { constructor(ACC_PUBLIC) { parameters { parameter 'foo': String.class parameter 'bar': Integer.class } exceptions { classNode Exception classNode IOException } block { } } } def expected = new ConstructorNode( ACC_PUBLIC, [ new Parameter(ClassHelper.make(String, false), "foo"), new Parameter(ClassHelper.make(Integer, false), "bar") ] as Parameter[], [ ClassHelper.make(Exception, false), ClassHelper.make(IOException, false) ] as ClassNode[], new BlockStatement() ) AstAssert.assertSyntaxTree([expected], result) } public void testGenericsType() { // class MyClass<T, U extends Number> {} def result = new AstBuilder().buildFromSpec { classNode 'MyClass', ACC_PUBLIC, { classNode Object //superclass interfaces { classNode GroovyObject } mixins {} genericsTypes { genericsType Object genericsType Number, { upperBound { classNode Number } } } } } def expected = new ClassNode( "MyClass", ACC_PUBLIC, ClassHelper.make(Object, false) ) expected.setGenericsTypes( [ new GenericsType(ClassHelper.make(Object, false)), new GenericsType(ClassHelper.make(Number, false), [ClassHelper.make(Number, false)] as ClassNode[], null), ] as GenericsType[] ) AstAssert.assertSyntaxTree([expected], result) } public void testGenericsType_WithLowerBounds() { // class MyClass<T, U extends Number> {} def result = new AstBuilder().buildFromSpec { classNode 'MyClass', ACC_PUBLIC, { classNode Object //superclass interfaces { classNode GroovyObject } mixins {} genericsTypes { genericsType Object genericsType Number, { upperBound { classNode Number //upper bound 1 classNode Comparable //upper bound 2 } lowerBound Integer } } } } def expected = new ClassNode( "MyClass", ACC_PUBLIC, ClassHelper.make(Object, false) ) expected.setGenericsTypes( [ new GenericsType(ClassHelper.make(Object, false)), new GenericsType( ClassHelper.make(Number, false), [ClassHelper.make(Number, false), ClassHelper.make(Comparable, false)] as ClassNode[], ClassHelper.make(Integer, false)), ] as GenericsType[] ) AstAssert.assertSyntaxTree([expected], result) } public void testImportNode() { // what source will trigger this node? def result = new AstBuilder().buildFromSpec { importNode String, "string" importNode Integer } def expected = [ new ImportNode(ClassHelper.make(String, false), "string"), new ImportNode(ClassHelper.make(Integer, false), null) ] AstAssert.assertSyntaxTree(expected, result) } public void testMethodNode() { /* @Override public String myMethod(String parameter) throws Exception, IOException { 'some result' } } */ def result = new AstBuilder().buildFromSpec { method('myMethod', ACC_PUBLIC, String) { parameters { parameter 'parameter': String.class } exceptions { classNode Exception classNode IOException } block { returnStatement { constant 'some result' } } annotations { annotation Override } } } def expected = new MethodNode( "myMethod", ACC_PUBLIC, ClassHelper.make(String, false), [new Parameter(ClassHelper.make(String, false), "parameter")] as Parameter[], [ClassHelper.make(Exception, false), ClassHelper.make(IOException, false)] as ClassNode[], new BlockStatement( [new ReturnStatement( new ConstantExpression('some result') )], new VariableScope() )) expected.addAnnotation(new AnnotationNode(ClassHelper.make(Override, false))) AstAssert.assertSyntaxTree([expected], result) } public void testAnnotation_WithParameter() { // @org.junit.Test(timeout=50L) def myMethod() {} def result = new AstBuilder().buildFromSpec { method 'myMethod', ACC_PUBLIC, Object, { parameters {} exceptions {} block { } annotations { annotation(Override) { member 'timeout', { constant 50L } } } } } def expected = new MethodNode( "myMethod", ACC_PUBLIC, ClassHelper.make(Object, false), [] as Parameter[], [] as ClassNode[], new BlockStatement([], new VariableScope())) def annotation = new AnnotationNode(ClassHelper.make(Override, false)) annotation.setMember('timeout', new ConstantExpression(50L)) expected.addAnnotation(annotation) AstAssert.assertSyntaxTree([expected], result) } public void testMixinNode() { // todo: what source code will generate a MixinNode? def result = new AstBuilder().buildFromSpec { classNode 'MyClass', ACC_PUBLIC, { classNode Object //superclass interfaces { classNode GroovyObject } mixins { mixin "ClassA", ACC_PUBLIC, { classNode String } mixin "ClassB", ACC_PUBLIC, { classNode String interfaces { classNode GroovyObject } } } } } def expected = new ClassNode( "MyClass", ACC_PUBLIC, ClassHelper.make(Object, false), [ClassHelper.make(GroovyObject, false)] as ClassNode[], [ new MixinNode("ClassA", ACC_PUBLIC, ClassHelper.make(String, false)), new MixinNode( "ClassB", ACC_PUBLIC, ClassHelper.make(String, false), [ClassHelper.make(GroovyObject, false)] as ClassNode[]), // interfaces ] as MixinNode[] ) AstAssert.assertSyntaxTree([expected], result) } public void testModuleNode() { // todo: what source code creates a ModuleNode? ModuleNode has a ton of setters that aren't currently being tested. Should this even be part of the DSL? } public void testPropertyNode() { // def myField = "foo" def result = new AstBuilder().buildFromSpec { propertyNode "MY_VALUE", ACC_PUBLIC, String, this.class, { constant "foo" } } def expected = new PropertyNode( "MY_VALUE", ACC_PUBLIC, ClassHelper.make(String, false), ClassHelper.make(this.class, false), new ConstantExpression("foo"), null, null //todo: do we need to support getter and setter blocks? ) AstAssert.assertSyntaxTree([expected], result) } public void testMethodCallContract_TooManyArguments() { def msg = shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { methodCall { variable "this" constant "println" argumentList { constant "Hello" } constant "illegal value" } } } assertEquals("Wrong exception message", "methodCall could not be invoked. Expected to receive parameters [class org.codehaus.groovy.ast.expr.Expression, class org.codehaus.groovy.ast.expr.Expression, class org.codehaus.groovy.ast.expr.Expression] but found [class org.codehaus.groovy.ast.expr.VariableExpression, class org.codehaus.groovy.ast.expr.ConstantExpression, class org.codehaus.groovy.ast.expr.ArgumentListExpression, class org.codehaus.groovy.ast.expr.ConstantExpression]", msg) } public void testMethodCallContract_TooFewArguments() { def msg = shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { methodCall { variable "this" constant "println" // missing argument list! } } } assertEquals("Wrong exception message", "methodCall could not be invoked. Expected to receive parameters [class org.codehaus.groovy.ast.expr.Expression, class org.codehaus.groovy.ast.expr.Expression, class org.codehaus.groovy.ast.expr.Expression] but found [class org.codehaus.groovy.ast.expr.VariableExpression, class org.codehaus.groovy.ast.expr.ConstantExpression]", msg) } public void testAnnotationConstantExpressionContract_TooFewArguments() { shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { annotationConstant { // missing argument } } } } public void testAnnotationConstantExpressionContract_TooManyArguments() { shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { annotationConstant { annotation Override constant 'illegal parameter' } } } } public void testConstructorCallExpressionContract_TooFewParameters() { shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { constructorCall(Integer) { // missing argument list } } } } public void testConstructorCallExpressionContract_TooManyParameters() { shouldFail(IllegalArgumentException) { new AstBuilder().buildFromSpec { constructorCall(Integer) { argumentList { constant 4 } constant 'illegal argument' } } } } } Other Groovy examples (source code examples)Here is a short list of links related to this Groovy AstBuilderFromSpecificationTest.groovy source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.