net.minecraftforge.gdi.transformer.ClosureEquivalentTransformer.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of groovydslimprover Show documentation
Show all versions of groovydslimprover Show documentation
Groovy Compiler Plugin to improve building Groovy based DSLs, like those used in Gradle.
The newest version!
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.gdi.transformer
import groovy.transform.CompileStatic
import groovyjarjarasm.asm.Opcodes
import net.minecraftforge.gdi.runtime.ClosureToAction
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.expr.Expression
import org.codehaus.groovy.ast.expr.VariableExpression
import org.codehaus.groovy.ast.tools.GeneralUtils
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.transform.AbstractASTTransformation
import org.codehaus.groovy.transform.GroovyASTTransformation
import org.codehaus.groovy.transform.sc.StaticCompileTransformation
import org.gradle.api.Action
import java.util.stream.Collectors
import java.util.stream.Stream
@CompileStatic
@GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
class ClosureEquivalentTransformer extends AbstractASTTransformation implements Opcodes {
private static final ClassNode ACTION = ClassHelper.make(Action)
private static final ClassNode CLOSURE_TO_ACTION = ClassHelper.make(ClosureToAction)
private static final ClassNode CSTATIC = ClassHelper.make(CompileStatic)
@Override
void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
this.init(astNodes, sourceUnit)
if (astNodes[1] !instanceof MethodNode) return
final method = (MethodNode) astNodes[1]
ClassNode clazz = method.declaringClass
if (clazz instanceof InnerClassNode && clazz.name.endsWith('Trait$Helper')) {
clazz = ((InnerClassNode) clazz).outerClass
}
final actionParam = method.parameters.find { it.type == ACTION }
final closureParam = DSLPropertyTransformer.Utils.closureParam(actionParam.type.genericsTypes[0].type)
final stmt = GeneralUtils.callX(VariableExpression.THIS_EXPRESSION, method.name, GeneralUtils.args(
Stream.of(method.parameters).filter { it.name != '$self' }.map {
it === actionParam ? asAction(GeneralUtils.varX(closureParam)) : GeneralUtils.varX(it)
}.collect(Collectors.toList())
))
final mtd = clazz.addMethod(
method.name, ACC_PUBLIC,
method.returnType, Stream.of(method.parameters).filter { it.name != '$self'}.map { it === actionParam ? closureParam : it }.toArray(Parameter[]::new),
method.exceptions,
method.returnType == ClassHelper.VOID_TYPE ? GeneralUtils.stmt(stmt) : GeneralUtils.returnS(stmt)
)
mtd.setGenericsTypes(method.genericsTypes)
final ann = new AnnotationNode(CSTATIC)
mtd.addAnnotation(ann)
new StaticCompileTransformation().visit(new ASTNode[] {
ann, mtd
}, sourceUnit)
}
static Expression asAction(Expression closure) {
GeneralUtils.callX(CLOSURE_TO_ACTION, 'delegateAndCall', closure)
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy