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)