Great now I run into another problem, spock uses groovy-all, which
repackages asm.
The BytecodeExpression has a MethodVisitor from asm, which is now in
groovyjarjarasm.asm.MethodVisitor
This compiles fine, but when the AST transforms are executed it breaks
down with this exception:
Caused by: java.lang.LinkageError: loader constraint violation: loader
(instance of groovy/lang/GroovyClassLoader) previously initiated loading
for a different type with name "groovyjarjarasm/asm/MethodVisitor"
at
org.spockframework.compiler.DeepBlockRewriter$1.visit(DeepBlockRewriter.java:190)
at
org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:174)
at
org.gradle.api.internal.tasks.compile.ApiGroovyCompiler.execute(ApiGroovyCompiler.java:56)
at
org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerRunnable.run(AbstractDaemonCompiler.java:87)
at
org.gradle.workers.internal.DefaultWorkerServer.execute(DefaultWorkerServer.java:36)
at
org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:46)
at
org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:30)
at
org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:100)
at
org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at
org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at
org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
at
org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
at
org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
I tried using the non-repackaged classes, but then it doesn't even
compile since BytecodeExpression wants groovyjarjarasm.
Thanks
-Leo
Am 22.11.2017 um 00:49 schrieb Jochen Theodorou:
On 21.11.2017 21:43, Leonard Brünings wrote:
Hi Jochen,
your first suggestion might do the trick and if closures disappear
then there will be much more that doesn't work.
We currently do something like this:
public void replaceImplicitThis(Expression invocation) {
if (invocation instanceof MethodCallExpression) {
MethodCallExpression methodCallExpression =
(MethodCallExpression)invocation;
if (methodCallExpression.isImplicitThis()) {
Expression target = referenceToCurrentClosure();
methodCallExpression.setObjectExpression(target);
}
}
}
private MethodCallExpression referenceToCurrentClosure() {
return new MethodCallExpression(
new VariableExpression("this"),
new ConstantExpression("each"),
new ArgumentListExpression(
new PropertyExpression(
new
ClassExpression(ClassHelper.makeWithoutCaching(Closure.class)),
new ConstantExpression("IDENTITY")
)
)
);
}
This looks a similar to your second suggestion.
similar in that both get the current reference, yes.
Could you give me a hint on how to write a BytecodeExpersion for
"ALOAD 0"? Could I just use this in place of the other
MethodCallExpression from referenceToCurrentClosure?
You use it in place of referenceToCurrentClosure,yes. Something like
new BytecodeExpression(ClassHelper.CLOSURE) {
public void visit(MethodVisitor mv) {
mv.visitVarInsn(ALOAD, 0);
}
});
frankly this is using a feature I do not like so much and that is that
Groovy handles a call on a closure instance the same way as a call
from within that closure instance (well, not 100% the same, there are
differences).But in this case you profit from it. Otherwise you would
need a way to express the implicit this as parameter... Maybe this is
actually something we should do..
bye Jochen