Groovy 将整个方法体包装在闭包中的AST转换
我正在尝试做一些相当简单的事情。我想将整个方法代码包装成一个额外的闭包块,用于测量执行时间。现在我收到了一条非常没有帮助的错误消息:Groovy 将整个方法体包装在闭包中的AST转换,groovy,abstract-syntax-tree,Groovy,Abstract Syntax Tree,我正在尝试做一些相当简单的事情。我想将整个方法代码包装成一个额外的闭包块,用于测量执行时间。现在我收到了一条非常没有帮助的错误消息: Error:Groovyc: NPE while processing Test.groovy 注释: @Retention(RetentionPolicy.SOURCE) @Target([ElementType.METHOD]) @GroovyASTTransformationClass(["WithTimingASTTransformation"]) pu
Error:Groovyc: NPE while processing Test.groovy
注释:
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.METHOD])
@GroovyASTTransformationClass(["WithTimingASTTransformation"])
public @interface WithTiming {
}
我的包装盒:
class Benchmark {
static def measureTime(Closure cl) {
def start = System.currentTimeMillis()
def result = cl()
def time = System.currentTimeMillis() - start
println "it took $time"
result
}
}
我的转变:
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
class WithTimingASTTransformation implements ASTTransformation {
@Override
void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
MethodNode method = astNodes[1]
method.code = wrap(method)
}
private Statement wrap(MethodNode method) {
def newBlock = new BlockStatement()
newBlock.addStatement(
new ExpressionStatement(
new StaticMethodCallExpression(
new ClassNode(Benchmark),
'measureTime',
new ArgumentListExpression(
new ClosureExpression(new Parameter[0], method.code)
))))
newBlock
}
}
我真的被困在这里,不知道如何调试这个问题
类似的主题也有答案(将整个方法体包装到一个try/catch块中)。这很好,但我的案例略有不同。在我的案例中,类似的NPE来自:
java.lang.NullPointerException
at org.codehaus.groovy.classgen.asm.ClosureWriter.createClosureClass(ClosureWriter.java:194)
at org.codehaus.groovy.classgen.asm.ClosureWriter.getOrAddClosureClass(ClosureWriter.java:159)
at org.codehaus.groovy.classgen.asm.ClosureWriter.writeClosure(ClosureWriter.java:90)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitClosureExpression(AsmClassGenerator.java:673)
鉴于:
if (parameters == null || expression.getVariableScope() == null) {
parameters = Parameter.EMPTY_ARRAY;
} else if (parameters.length == 0) {
// let's create a default 'it' parameter
Parameter it = new Parameter(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL);
parameters = new Parameter[]{it};
Variable ref = expression.getVariableScope().getDeclaredVariable("it");
if (ref != null) it.setClosureSharedVariable(ref.isClosureSharedVariable());
}
第194行(截至)为:
因此,您需要为ClosureExpression定义一个VariableScope。我必须将跟踪添加到org.codehaus.groovy.ast.ClosureWriter中才能找到这一点,因为在类生成阶段存在异常显示问题—在IntelliJ Idea和groovy控制台中—它没有显示正确的代码行
此外,我认为ClosureWriter或ClosureExpression构造函数都可以在默认情况下固定为工作对齐,而无需此NPE。我可能会为此向Groovy Jira提交一个问题
现在我可以在代码中注入闭包表达式了。但是,我们很难称之为终结
获取:
groovy.lang.MissingMethodException: No signature of method: com.a9ae0b01f0ffc.VSMSGEN.implementation.T_visa_recon_generator$_convert_vts_log_to_ctf_closure2.call() is applicable for argument types: () values: []
在我的案例中,类似的NPE来自:
java.lang.NullPointerException
at org.codehaus.groovy.classgen.asm.ClosureWriter.createClosureClass(ClosureWriter.java:194)
at org.codehaus.groovy.classgen.asm.ClosureWriter.getOrAddClosureClass(ClosureWriter.java:159)
at org.codehaus.groovy.classgen.asm.ClosureWriter.writeClosure(ClosureWriter.java:90)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitClosureExpression(AsmClassGenerator.java:673)
鉴于:
if (parameters == null || expression.getVariableScope() == null) {
parameters = Parameter.EMPTY_ARRAY;
} else if (parameters.length == 0) {
// let's create a default 'it' parameter
Parameter it = new Parameter(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL);
parameters = new Parameter[]{it};
Variable ref = expression.getVariableScope().getDeclaredVariable("it");
if (ref != null) it.setClosureSharedVariable(ref.isClosureSharedVariable());
}
第194行(截至)为:
因此,您需要为ClosureExpression定义一个VariableScope。我必须将跟踪添加到org.codehaus.groovy.ast.ClosureWriter中才能找到这一点,因为在类生成阶段存在异常显示问题—在IntelliJ Idea和groovy控制台中—它没有显示正确的代码行
此外,我认为ClosureWriter或ClosureExpression构造函数都可以在默认情况下固定为工作对齐,而无需此NPE。我可能会为此向Groovy Jira提交一个问题
现在我可以在代码中注入闭包表达式了。但是,我们很难称之为终结
获取:
groovy.lang.MissingMethodException: No signature of method: com.a9ae0b01f0ffc.VSMSGEN.implementation.T_visa_recon_generator$_convert_vts_log_to_ctf_closure2.call() is applicable for argument types: () values: []
您是否在单元测试(转换测试)期间尝试调试转换以查看NPE来自何处?您是否在单元测试(转换测试)期间尝试调试转换以查看NPE来自何处?