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来自何处?