我希望在我的groovy脚本中转储所有变量并显示所有值。
我想动态地这样做,因为我想通过 try / catch 包围我所有的巨型groovies。在 catch 部分中,我想使用stacktrace转储所有变量状态。代码应该是所有groovies的通用。
问题是 this.getBinding()。getVariables()没有返回正确的变量状态。
我制作了一个小脚本来说明情况:
def test1 = 1;
test1 = 2;
int test2 = 1;
test2 = 2;
test3 = 1;
test3 = 2;
def errLog=new File("c:/temp/groovy_debug.txt");
errLog.append("--------------------------------------------------------" + "\n");
errLog.append(" Context ["+getBinding().getVariables()+" ] \n");
errLog.append("--------" + "\n") ;
执行后我得到一个非常奇怪的结果
--------------------------------------------------------
Context [[[creationStackTrace= <not available>], test1:null, errLog:null, test2:null, test3:2] ]
--------
这意味着声明的变量总是报告为null或第一次赋值,但对于非类型变量,它获取最后一个值。 我想得到所有变量的最后一种情况(值= 2)。
有可能得到它们吗?
答案 0 :(得分:0)
Tim Yates'answer说明了为什么你在访问非全局变量时遇到困难。对于像您这样的简单案例,您只需要分配和声明,您可以使用访问者来收集结果,例如
import org.codehaus.groovy.ast.expr.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.control.*
import org.codehaus.groovy.classgen.*
import java.security.CodeSource
def scriptText = '''
def test1 = 1;
test1 = 2;
int test2 = 1;
test2 = 2;
test3 = 1;
test3 = 2;
'''
class VariableVisitor extends ClassCodeVisitorSupport {
def vars = [:]
void visitExpressionStatement(ExpressionStatement statement) {
if (statement.expression instanceof BinaryExpression)
vars.put(statement.expression.leftExpression.name, statement.expression.rightExpression.value)
super.visitExpressionStatement(statement)
}
void visitReturnStatement(ReturnStatement statement) {
if (statement.expression instanceof BinaryExpression)
vars.put(statement.expression.leftExpression.name, statement.expression.rightExpression.value)
super.visitReturnStatement(statement)
}
protected SourceUnit getSourceUnit() {
return source;
}
}
class CustomSourceOperation extends CompilationUnit.PrimaryClassNodeOperation {
CodeVisitorSupport visitor
void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
classNode.visitContents(visitor)
}
}
class MyClassLoader extends GroovyClassLoader {
CodeVisitorSupport visitor
protected CompilationUnit createCompilationUnit(CompilerConfiguration config, CodeSource source) {
CompilationUnit cu = super.createCompilationUnit(config, source)
cu.addPhaseOperation(new CustomSourceOperation(visitor: visitor), Phases.CLASS_GENERATION)
return cu
}
}
def visitor = new VariableVisitor()
def myCL = new MyClassLoader(visitor: visitor)
def script = myCL.parseClass(scriptText)
assert visitor.vars == ["test1":2, "test2":2, "test3":2]
但是,如果你的脚本有更复杂的东西(比如条件赋值),你需要更复杂的东西。您需要实际运行脚本并收集结果。