New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Groovy Compilation error: Spock attempts to re-declare `$spock_errorCollector` #783

Closed
ColinHarrington opened this Issue Oct 17, 2017 · 5 comments

Comments

Projects
None yet
3 participants
@ColinHarrington

ColinHarrington commented Oct 17, 2017

Issue description

Spock attempts to re-declare $spock_errorCollector when using another AST Transform
The current scope already contains a variable of the name $spock_errorCollector (and $spock_valueRecorder)

We've found an issue when compiling a Specification that seems to be triggered by a couple factors:

  1. An assert statement within a closure
  2. An AST Transform applied to the test. We found it with Grails' TestForTransformation but even Groovy's @Log Transform can demonstrate the issue.

This results in two compile errors:

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.
/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.

How to reproduce

Here is a concise example of the compilation issue in action

import groovy.util.logging.Log
import spock.lang.Specification 
 
@Log
class NimoyIssueSpec extends Specification {
    def "assert within closure"() {
        given:
        Closure sq = { x ->
            assert 1 == 1
            x * x
        }

        expect:
        sq(1) == 2
    }
}

https://meetspock.appspot.com/script/5097210278576128

Additional Environment information

This issue doesn't seem to be very environment specific, but I'm happy to help quantify further if needed

Java/JDK

openjdk version "1.8.0_131"

Groovy version

2.4.11

Build tool version

Gradle

gradle -version

Operating System

Linux, OSX, SpockWebConsole

Build-tool dependencies used

Gradle/Grails

compile 'org.spockframework:spock-core:1.1-groovy-2.4'

Compiler debug stacktrace

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.org.codehaus.groovy.syntax.SyntaxException: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.addError(ClassCodeVisitorSupport.java:150)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:145)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:111)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:343)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitClosureExpression(CodeVisitorSupport.java:176)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClosureExpression(VariableScopeVisitor.java:431)
        at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:45)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:335)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:84)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:231)
        at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:44)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitConstructorOrMethod(VariableScopeVisitor.java:507)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
        at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1081)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClass(VariableScopeVisitor.java:475)
        at org.codehaus.groovy.transform.LogASTTransformation.visit(LogASTTransformation.java:180)
        at org.codehaus.groovy.transform.ASTTransformationVisitor.visitClass(ASTTransformationVisitor.java:134)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$2.call(ASTTransformationVisitor.java:178)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:537)
        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$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:73)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:64)
        at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:29)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerDaemonServer.execute(AbstractDaemonCompiler.java:91)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:88)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        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:147)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.org.codehaus.groovy.syntax.SyntaxException: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.addError(ClassCodeVisitorSupport.java:150)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:145)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:111)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:343)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitClosureExpression(CodeVisitorSupport.java:176)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClosureExpression(VariableScopeVisitor.java:431)
        at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:45)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:335)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:84)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:231)
        at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:44)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitConstructorOrMethod(VariableScopeVisitor.java:507)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
        at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1081)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClass(VariableScopeVisitor.java:475)
        at org.codehaus.groovy.transform.LogASTTransformation.visit(LogASTTransformation.java:180)
        at org.codehaus.groovy.transform.ASTTransformationVisitor.visitClass(ASTTransformationVisitor.java:134)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$2.call(ASTTransformationVisitor.java:178)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:537)
        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$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:73)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:64)
        at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:29)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerDaemonServer.execute(AbstractDaemonCompiler.java:91)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:88)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        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:147)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
@leonard84

This comment has been minimized.

Show comment
Hide comment
@leonard84

leonard84 Oct 17, 2017

Member

It's a known issue that Spock currently is incompatible with Groovys log annotations @Log/@Slf4j/...
However, I don't see a compelling use-case of adding log statements into tests themselves. Do you have other AST-transforms that are affected?

Member

leonard84 commented Oct 17, 2017

It's a known issue that Spock currently is incompatible with Groovys log annotations @Log/@Slf4j/...
However, I don't see a compelling use-case of adding log statements into tests themselves. Do you have other AST-transforms that are affected?

@ColinHarrington

This comment has been minimized.

Show comment
Hide comment
@ColinHarrington

ColinHarrington Oct 17, 2017

@leonard84 The original use case was using Grails' testing transformations aka @TestFor(MyController) I found that @Log has the same behavior. Putting that demo test in a grails app and using @TestFor(..) instead will reproduce the same results. The weird part is that the compilation error only happens when you add an assert statement within a closure. The stacktrace that I see when using @TestFor is very similar:

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.org.codehaus.groovy.syntax.SyntaxException: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.addError(ClassCodeVisitorSupport.java:150)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:145)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:111)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:343)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitClosureExpression(CodeVisitorSupport.java:176)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClosureExpression(VariableScopeVisitor.java:431)
        at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:45)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:335)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:84)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:231)
        at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:44)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitConstructorOrMethod(VariableScopeVisitor.java:507)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
        at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1081)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClass(VariableScopeVisitor.java:475)
        at org.codehaus.groovy.transform.LogASTTransformation.visit(LogASTTransformation.java:180)
        at org.grails.compiler.logging.LoggingTransformer.performInjectionOnAnnotatedClass(LoggingTransformer.java:72)
        at org.grails.compiler.injection.test.TestForTransformation.testFor(TestForTransformation.java:204)
        at org.grails.compiler.injection.test.TestForTransformation.handleTestForAnnotation(TestForTransformation.java:131)
        at org.grails.compiler.injection.test.TestForTransformation.visit(TestForTransformation.java:123)
        at org.codehaus.groovy.transform.ASTTransformationVisitor.visitClass(ASTTransformationVisitor.java:134)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$2.call(ASTTransformationVisitor.java:178)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:537)
        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$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:73)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:64)
        at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:29)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerDaemonServer.execute(AbstractDaemonCompiler.java:91)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:88)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        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:147)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.org.codehaus.groovy.syntax.SyntaxException: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.addError(ClassCodeVisitorSupport.java:150)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:145)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:111)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:343)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitClosureExpression(CodeVisitorSupport.java:176)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClosureExpression(VariableScopeVisitor.java:431)
        at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:45)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:335)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:84)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:231)
        at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:44)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitConstructorOrMethod(VariableScopeVisitor.java:507)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
        at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1081)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClass(VariableScopeVisitor.java:475)
        at org.codehaus.groovy.transform.LogASTTransformation.visit(LogASTTransformation.java:180)
        at org.grails.compiler.logging.LoggingTransformer.performInjectionOnAnnotatedClass(LoggingTransformer.java:72)
        at org.grails.compiler.injection.test.TestForTransformation.testFor(TestForTransformation.java:204)
        at org.grails.compiler.injection.test.TestForTransformation.handleTestForAnnotation(TestForTransformation.java:131)
        at org.grails.compiler.injection.test.TestForTransformation.visit(TestForTransformation.java:123)
        at org.codehaus.groovy.transform.ASTTransformationVisitor.visitClass(ASTTransformationVisitor.java:134)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$2.call(ASTTransformationVisitor.java:178)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:537)
        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$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:73)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:64)
        at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:29)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerDaemonServer.execute(AbstractDaemonCompiler.java:91)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:88)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        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:147)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

ColinHarrington commented Oct 17, 2017

@leonard84 The original use case was using Grails' testing transformations aka @TestFor(MyController) I found that @Log has the same behavior. Putting that demo test in a grails app and using @TestFor(..) instead will reproduce the same results. The weird part is that the compilation error only happens when you add an assert statement within a closure. The stacktrace that I see when using @TestFor is very similar:

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.org.codehaus.groovy.syntax.SyntaxException: The current scope already contains a variable of the name $spock_errorCollector
 @ line -1, column -1.
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.addError(ClassCodeVisitorSupport.java:150)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:145)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:111)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:343)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitClosureExpression(CodeVisitorSupport.java:176)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClosureExpression(VariableScopeVisitor.java:431)
        at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:45)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:335)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:84)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:231)
        at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:44)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitConstructorOrMethod(VariableScopeVisitor.java:507)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
        at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1081)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClass(VariableScopeVisitor.java:475)
        at org.codehaus.groovy.transform.LogASTTransformation.visit(LogASTTransformation.java:180)
        at org.grails.compiler.logging.LoggingTransformer.performInjectionOnAnnotatedClass(LoggingTransformer.java:72)
        at org.grails.compiler.injection.test.TestForTransformation.testFor(TestForTransformation.java:204)
        at org.grails.compiler.injection.test.TestForTransformation.handleTestForAnnotation(TestForTransformation.java:131)
        at org.grails.compiler.injection.test.TestForTransformation.visit(TestForTransformation.java:123)
        at org.codehaus.groovy.transform.ASTTransformationVisitor.visitClass(ASTTransformationVisitor.java:134)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$2.call(ASTTransformationVisitor.java:178)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:537)
        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$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:73)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:64)
        at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:29)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerDaemonServer.execute(AbstractDaemonCompiler.java:91)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:88)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        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:147)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

/home/user/app/src/test/groovy/app/NimoyIssueSpec.groovy: -1: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.org.codehaus.groovy.syntax.SyntaxException: The current scope already contains a variable of the name $spock_valueRecorder
 @ line -1, column -1.
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.addError(ClassCodeVisitorSupport.java:150)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:145)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.declare(VariableScopeVisitor.java:111)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:343)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitClosureExpression(CodeVisitorSupport.java:176)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClosureExpression(VariableScopeVisitor.java:431)
        at org.codehaus.groovy.ast.expr.ClosureExpression.visit(ClosureExpression.java:45)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitDeclarationExpression(VariableScopeVisitor.java:335)
        at org.codehaus.groovy.ast.expr.DeclarationExpression.visit(DeclarationExpression.java:89)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitExpressionStatement(CodeVisitorSupport.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitExpressionStatement(ClassCodeVisitorSupport.java:196)
        at org.codehaus.groovy.ast.stmt.ExpressionStatement.visit(ExpressionStatement.java:42)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitTryCatchFinally(CodeVisitorSupport.java:84)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitTryCatchFinally(ClassCodeVisitorSupport.java:231)
        at org.codehaus.groovy.ast.stmt.TryCatchStatement.visit(TryCatchStatement.java:44)
        at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitBlockStatement(ClassCodeVisitorSupport.java:166)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitBlockStatement(VariableScopeVisitor.java:308)
        at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:71)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClassCodeContainer(ClassCodeVisitorSupport.java:104)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitConstructorOrMethod(VariableScopeVisitor.java:507)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitMethod(ClassCodeVisitorSupport.java:126)
        at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:1081)
        at org.codehaus.groovy.ast.ClassCodeVisitorSupport.visitClass(ClassCodeVisitorSupport.java:53)
        at org.codehaus.groovy.classgen.VariableScopeVisitor.visitClass(VariableScopeVisitor.java:475)
        at org.codehaus.groovy.transform.LogASTTransformation.visit(LogASTTransformation.java:180)
        at org.grails.compiler.logging.LoggingTransformer.performInjectionOnAnnotatedClass(LoggingTransformer.java:72)
        at org.grails.compiler.injection.test.TestForTransformation.testFor(TestForTransformation.java:204)
        at org.grails.compiler.injection.test.TestForTransformation.handleTestForAnnotation(TestForTransformation.java:131)
        at org.grails.compiler.injection.test.TestForTransformation.visit(TestForTransformation.java:123)
        at org.codehaus.groovy.transform.ASTTransformationVisitor.visitClass(ASTTransformationVisitor.java:134)
        at org.codehaus.groovy.transform.ASTTransformationVisitor$2.call(ASTTransformationVisitor.java:178)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:537)
        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$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:73)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerWorkerAdapter.execute(AbstractDaemonCompiler.java:64)
        at org.gradle.workers.internal.WorkerDaemonServer.execute(WorkerDaemonServer.java:29)
        at org.gradle.api.internal.tasks.compile.daemon.AbstractDaemonCompiler$CompilerDaemonServer.execute(AbstractDaemonCompiler.java:91)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.process.internal.worker.request.WorkerAction.run(WorkerAction.java:88)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        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:147)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
@ColinHarrington

This comment has been minimized.

Show comment
Hide comment
@ColinHarrington

ColinHarrington Oct 18, 2017

Looks like the TestForTransformation does end up applying the LogASTTransformation to the test class.
I'm not sure if this is an issue with the LogASTTransformation revisiting the code inside the closure or if Spock is doing something wrong in its transforms that are triggering the error.

It does look like Spock is calling defineRecorders if there are any items in the block to be rewritten. When decompiling the bytecode, the$spock_errorCollector and $spock_valueRecorder are being declared again inside the closure too. Is that expected behavior? Why redefine the recorders vs use the scoped ones from the test block?

Looks like that becomes a problem when LogASTTransformation revisits the block. If you wrote that with plain Groovy it won't compile with a similar error: The current scope already contains a variable of the name spock_errorCollector

class NimoyIssueSpec extends Specification {
    def "I think it is a spock bug"() {
        ErrorCollector spock_errorCollector = new ErrorCollector()

        given:
            Closure sq = { x ->
                ErrorCollector spock_errorCollector = new ErrorCollector()
                assert 1 == 1
                x * x
            }
        expect:
            sq(1) == 2
    }
}

So it appears that Spock is generating bytecode that can't be revisited in via the original VariableScope like the @LogASTTransformation expects.

I wonder if we could influence the order of the transforms to apply the Log one first if that would help.

For reference this issue was mentioned in the code: https://issues.apache.org/jira/browse/GROOVY-6373

ColinHarrington commented Oct 18, 2017

Looks like the TestForTransformation does end up applying the LogASTTransformation to the test class.
I'm not sure if this is an issue with the LogASTTransformation revisiting the code inside the closure or if Spock is doing something wrong in its transforms that are triggering the error.

It does look like Spock is calling defineRecorders if there are any items in the block to be rewritten. When decompiling the bytecode, the$spock_errorCollector and $spock_valueRecorder are being declared again inside the closure too. Is that expected behavior? Why redefine the recorders vs use the scoped ones from the test block?

Looks like that becomes a problem when LogASTTransformation revisits the block. If you wrote that with plain Groovy it won't compile with a similar error: The current scope already contains a variable of the name spock_errorCollector

class NimoyIssueSpec extends Specification {
    def "I think it is a spock bug"() {
        ErrorCollector spock_errorCollector = new ErrorCollector()

        given:
            Closure sq = { x ->
                ErrorCollector spock_errorCollector = new ErrorCollector()
                assert 1 == 1
                x * x
            }
        expect:
            sq(1) == 2
    }
}

So it appears that Spock is generating bytecode that can't be revisited in via the original VariableScope like the @LogASTTransformation expects.

I wonder if we could influence the order of the transforms to apply the Log one first if that would help.

For reference this issue was mentioned in the code: https://issues.apache.org/jira/browse/GROOVY-6373

@leonard84

This comment has been minimized.

Show comment
Hide comment
@leonard84

leonard84 Oct 18, 2017

Member

Why redefine the recorders vs use the scoped ones from the test block?

  1. The outer scope may not contain a collector.
  2. The collector has two modes, so you can't just reuse an "unrelated" collector
@CompileStatic
class SomeSpec extends Specification {
  def "test"() {
    expect:
    with('a') {
      it == 'a'
    }
    verifyAll('b') {
      it == 'b'
    }
  }
}

Is transformed to

public void $spock_feature_0_0() {
        this.with('a', { 
            org.spockframework.runtime.ErrorCollector $spock_errorCollector = new org.spockframework.runtime.ErrorCollector(false)
            org.spockframework.runtime.ValueRecorder $spock_valueRecorder = new org.spockframework.runtime.ValueRecorder()
            try {
                try {
                    return org.spockframework.runtime.SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'it == \'a\'', 12, 7, null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEquals($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), it), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), 'a'))))
                } 
                catch (java.lang.Throwable throwable) {
                    return org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'it == \'a\'', 12, 7, null, throwable)
                } 
                finally { 
                } 
            } 
            finally { 
                $spock_errorCollector.validateCollectedErrors()} 
        })
        this.verifyAll('b', { 
            org.spockframework.runtime.ErrorCollector $spock_errorCollector = new org.spockframework.runtime.ErrorCollector(true)
            org.spockframework.runtime.ValueRecorder $spock_valueRecorder = new org.spockframework.runtime.ValueRecorder()
            try {
                try {
                    return org.spockframework.runtime.SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'it == \'b\'', 15, 7, null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEquals($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), it), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), 'b'))))
                } 
                catch (java.lang.Throwable throwable) {
                    return org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'it == \'b\'', 15, 7, null, throwable)
                } 
                finally { 
                } 
            } 
            finally { 
                $spock_errorCollector.validateCollectedErrors()} 
        })
        this.getSpecificationContext().getMockController().leaveScope()
    }

As you can see there is no outer collector, and the collector is initialized once with error collection enabled and once disabled. Furthermore, you can use these methods outside of a feature method, i.e. a helper method.

The only fix I see atm is to create and use unique names for the collector and recorder, however that would require some extensive rewrite of Spocks AST transform. Unfortunately Groovy does not offer a way to order AST transforms in the same phase.

Member

leonard84 commented Oct 18, 2017

Why redefine the recorders vs use the scoped ones from the test block?

  1. The outer scope may not contain a collector.
  2. The collector has two modes, so you can't just reuse an "unrelated" collector
@CompileStatic
class SomeSpec extends Specification {
  def "test"() {
    expect:
    with('a') {
      it == 'a'
    }
    verifyAll('b') {
      it == 'b'
    }
  }
}

Is transformed to

public void $spock_feature_0_0() {
        this.with('a', { 
            org.spockframework.runtime.ErrorCollector $spock_errorCollector = new org.spockframework.runtime.ErrorCollector(false)
            org.spockframework.runtime.ValueRecorder $spock_valueRecorder = new org.spockframework.runtime.ValueRecorder()
            try {
                try {
                    return org.spockframework.runtime.SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'it == \'a\'', 12, 7, null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEquals($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), it), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), 'a'))))
                } 
                catch (java.lang.Throwable throwable) {
                    return org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'it == \'a\'', 12, 7, null, throwable)
                } 
                finally { 
                } 
            } 
            finally { 
                $spock_errorCollector.validateCollectedErrors()} 
        })
        this.verifyAll('b', { 
            org.spockframework.runtime.ErrorCollector $spock_errorCollector = new org.spockframework.runtime.ErrorCollector(true)
            org.spockframework.runtime.ValueRecorder $spock_valueRecorder = new org.spockframework.runtime.ValueRecorder()
            try {
                try {
                    return org.spockframework.runtime.SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'it == \'b\'', 15, 7, null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEquals($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), it), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), 'b'))))
                } 
                catch (java.lang.Throwable throwable) {
                    return org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'it == \'b\'', 15, 7, null, throwable)
                } 
                finally { 
                } 
            } 
            finally { 
                $spock_errorCollector.validateCollectedErrors()} 
        })
        this.getSpecificationContext().getMockController().leaveScope()
    }

As you can see there is no outer collector, and the collector is initialized once with error collection enabled and once disabled. Furthermore, you can use these methods outside of a feature method, i.e. a helper method.

The only fix I see atm is to create and use unique names for the collector and recorder, however that would require some extensive rewrite of Spocks AST transform. Unfortunately Groovy does not offer a way to order AST transforms in the same phase.

@sbglasius sbglasius added the bug label Jun 20, 2018

leonard84 added a commit to leonard84/spock that referenced this issue Jul 7, 2018

leonard84 added a commit that referenced this issue Jul 7, 2018

@leonard84

This comment has been minimized.

Show comment
Hide comment
@leonard84

leonard84 Jul 7, 2018

Member

Took some time but now it is fixed. Keeping track of the number of defined recorders proved to be difficult to get right, so we just fix the names afterwards.

Member

leonard84 commented Jul 7, 2018

Took some time but now it is fixed. Keeping track of the number of defined recorders proved to be difficult to get right, so we just fix the names afterwards.

@leonard84 leonard84 closed this Jul 7, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment