Is it expected or a bug, that if you use `Variable...
# groovy
v
Is it expected or a bug, that if you use
VariableExpression.THIS_EXPRESSION
the STC and thus static-compile gets confused. We use this at some places in the Spock transform. While trying to make Spock specs compatible with STC and SC, it was observed that STC stores type information at the current node and using
VariableExpression.THIS_EXPRESSION
then causes conflicting casts when used inside and outside a closure. As a work-around we can instead use
new VariableExpression("this")
, but is this expected, or should it work properly and I should report a bug? As an example.
Copy code
class ASpec extends Specification {
  def "mock init closure"() {
    given:
    List<String> list = Mock(List) {
      size() >> 3
    }

    when:
    int size = list.size()

    then:
    size == 3
  }
}
compiles in semantic analysis to
Copy code
import spock.lang.*

@org.spockframework.runtime.model.SpecMetadata(filename = 'script.groovy', line = 1)
public class ASpec extends spock.lang.Specification {

    @org.spockframework.runtime.model.FeatureMetadata(name = 'mock init closure', ordinal = 0, line = 2, blocks = [@org.spockframework.runtime.model.BlockMetadata(kind = org.spockframework.runtime.model.BlockKind.SETUP, texts = []), @org.spockframework.runtime.model.BlockMetadata(kind = org.spockframework.runtime.model.BlockKind.WHEN, texts = []), @org.spockframework.runtime.model.BlockMetadata(kind = org.spockframework.runtime.model.BlockKind.THEN, texts = [])], parameterNames = [])
    public void $spock_feature_0_0() {
        org.spockframework.runtime.ValueRecorder $spock_valueRecorder = new org.spockframework.runtime.ValueRecorder()
        org.spockframework.runtime.ErrorCollector $spock_errorCollector = org.spockframework.runtime.ErrorRethrower.INSTANCE
        org.spockframework.runtime.SpockRuntime.callBlockEntered(this, 0)
        java.util.List<String> list = org.spockframework.runtime.SpecInternals.MockImpl(this, 'list', java.util.List, java.util.List, { ->
            this.getSpecificationContext().getMockController().addInteraction(new org.spockframework.mock.runtime.InteractionBuilder(5, 7, 'size() >> 3').addEqualTarget(it).addEqualMethodName('size').setArgListKind(true, false).addConstantResponse(3).build())
        })
        org.spockframework.runtime.SpockRuntime.callBlockExited(this, 0)
        org.spockframework.runtime.SpockRuntime.callBlockEntered(this, 1)
        java.lang.Integer size = list.size()
        org.spockframework.runtime.SpockRuntime.callBlockExited(this, 1)
        org.spockframework.runtime.SpockRuntime.callBlockEntered(this, 2)
        try {
            org.spockframework.runtime.SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'size == 3', 12, 5, null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(2), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), size) == $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), 3)))
        }
        catch (java.lang.Throwable $spock_condition_throwable) {
            org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'size == 3', 12, 5, null, $spock_condition_throwable)}
        finally {
        }
        org.spockframework.runtime.SpockRuntime.callBlockExited(this, 2)
        this.getSpecificationContext().getMockController().leaveScope()
    }

}
The important part here is the two
getSpecificationContext()
calls, one inside the mock init closure, one as last line in the feature method, both added by the Spock transform. If those use
VariableExpression._THIS_EXPRESSION_
then at runtime you get
java.lang.ClassCastException: apackage.ASpec cannot be cast to apackage.ASpec$__spock_feature_0_0_closure1
. If you use
new VariableExpression("this")
instead, it works as intended.
Assuming it is a bug, I reported it at issues.apache.org/jira/browse/GROOVY-12441