...
| Code Block |
|---|
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.expr.ClassExpression
import org.codehaus.groovy.ast.expr.Expression
import org.codehaus.groovy.ast.expr.ListExpression
currentType(mixins: annotatedBy(Mixin)).accept {
provider = "Mixin AST Transform"
for (AnnotationNode mixin in mixins) {
if (mixin instanceof AnnotationNode) {
Expression expr = mixin.getMember("value")
if (expr instanceof ClassExpression) {
delegatesTo expr
} else if (expr instanceof ListExpression) {
for (Expression ex in expr?.expressions) {
delegatesTo ex
}
}
}
}
}
|
Newify
Here is the @Newify DSLD. This matches whenever an enclosing field, method, or class is annotated by groovy.lang.Newify. We add both the Python-style constructors and the Ruby style cosntructors.
| Code Block |
|---|
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.ListExpression;
(enclosingMethod(newify: annotatedBy(Newify)) | enclosingClass(newify: annotatedBy(Newify)) | enclosingField(newify: annotatedBy(Newify))).accept {
provider = "Newify AST Transform"
for (AnnotationNode a : newify) {
def classes = findClasses(a)
println "CurrentType: " + currentType
// when there are no classes in the list, then applies to all classes
if (classes.isEmpty() || classes.contains(currentType)) {
// no arg constructor
// Python style
method name: "new", type: currentType, declaringType: currentType, isStatic: true
// Ruby style
method name: currentType.nameWithoutPackage, type: currentType, isStstic: true
for (cons in (currentType.declaredConstructors?: [])) {
def extractedParams = extractParams(cons)
// Python style
method name: "new", type: currentType, declaringType: currentType, params: extractedParams, isStatic: true
// Ruby style
method name: currentType.nameWithoutPackage, type: currentType, params: extractedParams, isStatic: true
}
}
}
}
// helpers
// convert to a list of class nodes
List<ClassNode> findClasses(AnnotationNode a) {
def value = a.getMember("value")
if (value instanceof ListExpression) {
return value.expressions.collect{ it.type }
} else if (value instanceof Expression) {
return [value.type]
} else {
return []
}
}
// Convert Parameters to a map if String -> ClassNode
def extractParams(ConstructorNode cons) {
def params = [ : ]
for (param in (cons.parameters ?: [] )) {
params."${param.name}" = param.type
}
params
}
|
SwingBuilder
Although this next example is quite long, it is fairly straight forward. We are just adding lots and lots and lots of methods to the SwingBuilder class. This script is only partially complete since we don't include documentation for all contributed methods. It might be possible to use BeanInfo to generate this script automatically.
...