Björn Kautler created GROOVY-12441:
--------------------------------------

             Summary: STC gets confused when THIS_EXPRESSION is used
                 Key: GROOVY-12441
                 URL: https://issues.apache.org/jira/browse/GROOVY-12441
             Project: Groovy
          Issue Type: Bug
    Affects Versions: 6.0.0, 5.1.3, 4.0.33, 3.0.25, 2.5.23
            Reporter: Björn Kautler


If you use {{VariableExpression.THIS_EXPRESSION}} the STC  and thus 
static-compile gets confused.
I assume this is a bug, if it is expected, sorry for the noise.
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 
I guess this actually is a bug, thus this report.

As an example.
{code:java}
class ASpec extends Specification {
  def "mock init closure"() {
    given:
    List<String> list = Mock(List) {
      size() >> 3
    }

    when:
    int size = list.size()

    then:
    size == 3
  }
}
{code}
compiles in semantic analysis to
{code:java}
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()
    }

}
{code}
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.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to