From e849da99e534612cada7ac4db295308313e3f0cb Mon Sep 17 00:00:00 2001 From: Paul King Date: Tue, 17 Jun 2014 14:28:04 +1000 Subject: [PATCH] GROOVY-4941: Static methods cannot be called during AST transformation via AstBuilder.buildFromSpec() --- .../builder/AstSpecificationCompiler.groovy | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/src/main/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy b/src/main/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy index 8eb0e80a20..2fa124be8a 100644 --- a/src/main/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy +++ b/src/main/org/codehaus/groovy/ast/builder/AstSpecificationCompiler.groovy @@ -374,6 +374,13 @@ class AstSpecificationCompiler implements GroovyInterceptable { expression << new ImportNode(ClassHelper.make(target), alias) } + /** + * Creates an ImportNode. + */ + void importNode(ClassNode target, String alias = null) { + expression << new ImportNode(target, alias) + } + /** * Creates a CatchStatement. */ @@ -646,6 +653,13 @@ class AstSpecificationCompiler implements GroovyInterceptable { expression << new ClassExpression(ClassHelper.make(type)) } + /** + * Creates a ClassExpression. + */ + void classExpression(ClassNode type) { + expression << new ClassExpression(type) + } + /** * Creates a UnaryMinusExpression */ @@ -739,6 +753,32 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates a Parameter. + */ + void parameter(String name, Class type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) { + if (argBlock) { + captureAndCreateNode("Parameter", argBlock) { + new Parameter(ClassHelper.make(type), name, expression[0]) + } + } else { + expression << (new Parameter(ClassHelper.make(type), name)) + } + } + + /** + * Creates a Parameter. + */ + void parameter(String name, ClassNode type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) { + if (argBlock) { + captureAndCreateNode("Parameter", argBlock) { + new Parameter(type, name, expression[0]) + } + } else { + expression << (new Parameter(type, name)) + } + } + /** * Creates an ArrayExpression. */ @@ -748,6 +788,15 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates an ArrayExpression. + */ + void array(ClassNode type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) { + captureAndCreateNode("ArrayExpression", argBlock) { + new ArrayExpression(type, new ArrayList(expression)) + } + } + /** * Creates a GenericsType. */ @@ -761,6 +810,19 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates a GenericsType. + */ + void genericsType(ClassNode type, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) { + if (argBlock) { + captureAndCreateNode("GenericsType", argBlock) { + new GenericsType(type, expression[0] as ClassNode[], expression[1]) + } + } else { + expression << new GenericsType(ClassHelper.make(type)) + } + } + /** * Creates a list of upperBound ClassNodes. */ @@ -775,6 +837,13 @@ class AstSpecificationCompiler implements GroovyInterceptable { expression << ClassHelper.make(target) } + /** + * Create lowerBound ClassNode. + */ + void lowerBound(ClassNode target) { + expression << target + } + /** * Creates a 2 element list of name and Annotation. Used with Annotation Members. */ @@ -813,6 +882,24 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates an AnnotationNode. + */ + void annotation(ClassNode target, @DelegatesTo(AstSpecificationCompiler) Closure argBlock = null) { + if (argBlock) { + //todo: add better error handling + captureAndCreateNode("ArgumentListExpression", argBlock) { + def node = new AnnotationNode(target) + expression?.each { + node.addMember(it[0], it[1]) + } + node + } + } else { + expression << new AnnotationNode(target) + } + } + /** * Creates a MixinNode. */ @@ -923,6 +1010,20 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates a MethodNode. + */ + void method(String name, int modifiers, ClassNode returnType, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) { + captureAndCreateNode("MethodNode", argBlock) { + //todo: enforce contract + def result = new MethodNode(name, modifiers, returnType, expression[0], expression[1], expression[2]) + if (expression[3]) { + result.addAnnotations(new ArrayList(expression[3])) + } + result + } + } + /** * Creates a token. */ @@ -995,6 +1096,28 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates a FieldNode. + */ + void fieldNode(String name, int modifiers, ClassNode type, ClassNode owner, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) { + captureAndCreateNode("FieldNode", argBlock) { + def annotations = null + if (expression.size() > 1) { + annotations = expression[1] + expression.remove(1) + } + expression.add(0, owner) + expression.add(0, type) + expression.add(0, modifiers) + expression.add(0, name) + def result = new FieldNode(*enforceConstraints('fieldNode', [String, Integer, ClassNode, ClassNode, Expression])) + if (annotations) { + result.addAnnotations(new ArrayList(annotations)) + } + result + } + } + /** * Creates an inner class. */ @@ -1034,6 +1157,29 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates a PropertyNode. + */ + void propertyNode(String name, int modifiers, ClassNode type, ClassNode owner, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) { + //todo: improve error handling? + captureAndCreateNode("PropertyNode", argBlock) { + def annotations = null + // check if the last expression looks like annotations + if (List.isAssignableFrom(expression[-1].getClass())) { + annotations = expression[-1] + expression.remove(expression.size() - 1) + } + def result = new PropertyNode(name, modifiers, type, owner, + expression[0], // initial value (possibly null) + expression[1], // getter block (possibly null) + expression[2]) // setter block (possibly null) + if (annotations) { + result.addAnnotations(new ArrayList(annotations)) + } + result + } + } + /** * Creates a StaticMethodCallExpression. */ @@ -1045,6 +1191,17 @@ class AstSpecificationCompiler implements GroovyInterceptable { } } + /** + * Creates a StaticMethodCallExpression. + */ + void staticMethodCall(ClassNode target, String name, @DelegatesTo(AstSpecificationCompiler) Closure argBlock) { + captureAndCreateNode("StaticMethodCallExpression", argBlock) { + expression.add(0, name) + expression.add(0, target) + new StaticMethodCallExpression(*enforceConstraints('staticMethodCall', [ClassNode, String, Expression])) + } + } + /** * Creates a StaticMethodCallExpression. */