I'm using java to modify some groovy code using reflection.
The original groovy code is of the form:
void method() {
A(processId);
B();
}
I need to modify this to inject processId:
void callMethod() {
int processId = rand();
invokeMethod(
{->
A(processId);
B();
}, processId);
}
void invokeMethod(Closure closure, int processId) {
doSomething(processId);
closure.call();
}
Note: invokeMethod() is an existing method and is not injected.
When I modified the original code as above, I'm getting this error: "groovy.lang.MissingPropertyException: No such property: processId"
I've tried setting the variableScope of the "callMethod" method to include the "processId" variable as a DeclaredVariable.
For reference, here is the code I used to do this:
private void wrapMethod(@NonNull MethodNode node)
{
VariableExpression var = new VariableExpression("processId", new ClassNode(Integer.class));
var.setClosureSharedVariable(true);
//Generate a statement that creates a processId
Statement statement = GeneralUtils.declS(var, GeneralUtils.callThisX("getUUID"));
ClosureExpression methodClosure = createMethodClosure(node);
ArgumentListExpression args = createArgumentListExpression(methodClosure,
varX("processId"));
MethodCallExpression method = GeneralUtils.callThisX("invokeMethod", args);
BlockStatement newMethodCode = GeneralUtils.block(statement, GeneralUtils.stmt(method));
newMethodCode.setVariableScope(methodClosure.getVariableScope().copy());
//Just to be safe, modifying the scope of the node as well.
VariableScope newScope = node.getVariableScope().copy();
newScope.putDeclaredVariable(var);
node.setCode(newMethodCode);
node.setVariableScope(newScope);
}
private ClosureExpression createMethodClosure(MethodNode node) {
//Get code from within node to dump into a closure.
BlockStatement block = (BlockStatement) node.getCode();
//Setting closureScope and adding processId
VariableScope closureScope = block.getVariableScope().copy();
closureScope.getReferencedLocalVariablesIterator()
.forEachRemaining(x -> x.setClosureSharedVariable(true));
Variable var = new VariableExpression("processId", new ClassNode(Integer.class));
var.setClosureSharedVariable(true);
closureScope.putDeclaredVariable(var);
ClosureExpression methodClosure = GeneralUtils.closureX(block);
methodClosure.setVariableScope(closureScope);
return methodClosure;
}
I've verified the code to check that 'processId' is accessible within the invokeMethod() block and that the resultant code from the injection is as expected.
Any ideas on why this is not working?
Aucun commentaire:
Enregistrer un commentaire