diff --git a/spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java b/spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java index 1f44bf4244..eae94e9dcd 100644 --- a/spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java +++ b/spock-core/src/main/java/org/spockframework/compiler/DeepBlockRewriter.java @@ -57,54 +57,6 @@ public DeepBlockRewriter(IRewriteResources resources) { @Override public void visit(Block block) { super.visit(block); - addBlockEnterCall(block); - } - - private void addBlockEnterCall(Block block) { - BlockParseInfo blockType = block.getParseInfo(); - if (blockType == BlockParseInfo.WHERE - || blockType == BlockParseInfo.METHOD_END - || blockType == BlockParseInfo.ANONYMOUS) return; - - // SpockRuntime.enterBlock(getSpecificationContext(), new BlockInfo(blockKind, [blockTexts])) - MethodCallExpression enterBlockCall = createBlockListenerCall(block, blockType, resources.getAstNodeCache().SpockRuntime_CallEnterBlock); - // SpockRuntime.exitedBlock(getSpecificationContext(), new BlockInfo(blockKind, [blockTexts])) - MethodCallExpression exitBlockCall = createBlockListenerCall(block, blockType, resources.getAstNodeCache().SpockRuntime_CallExitBlock); - - // As the cleanup block finalizes the specification, it would override any previous block in ErrorInfo, - // so we only call enterBlock if there is no error yet. - if (blockType == BlockParseInfo.CLEANUP) { - block.getAst().add(0, new IfStatement( - // if ($spock_feature_throwable == null) - new BooleanExpression(AstUtil.createVariableIsNullExpression(new VariableExpression(SpecRewriter.SPOCK_FEATURE_THROWABLE, resources.getAstNodeCache().Throwable))), - new ExpressionStatement(enterBlockCall), - EmptyStatement.INSTANCE - )); - } else { - block.getAst().add(0, new ExpressionStatement(enterBlockCall)); - } - block.getAst().add( new ExpressionStatement(exitBlockCall)); - } - - private MethodCallExpression createBlockListenerCall(Block block, BlockParseInfo blockType, MethodNode blockListenerMethod) { - return createDirectMethodCall( - new ClassExpression(resources.getAstNodeCache().SpockRuntime), - blockListenerMethod, - new ArgumentListExpression( - createDirectMethodCall(VariableExpression.THIS_EXPRESSION, - resources.getAstNodeCache().SpecInternals_GetSpecificationContext, - ArgumentListExpression.EMPTY_ARGUMENTS), - new ConstructorCallExpression(resources.getAstNodeCache().BlockInfo, - new ArgumentListExpression( - new PropertyExpression( - new ClassExpression(resources.getAstNodeCache().BlockKind), - blockType.name() - ), - new ListExpression( - block.getDescriptions().stream().map(ConstantExpression::new).collect(Collectors.toList()) - ) - )) - )); } @Override diff --git a/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java b/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java index d170b0a1b2..e542e7a8d5 100644 --- a/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java +++ b/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java @@ -22,6 +22,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.*; +import java.util.stream.Collectors; import org.codehaus.groovy.ast.*; import org.codehaus.groovy.ast.expr.*; @@ -384,8 +385,10 @@ public void visitMethodAgain(Method method) { this.block = null; if (!movedStatsBackToMethod) - for (Block b : method.getBlocks()) + for (Block b : method.getBlocks()) { + addBlockListeners(b); method.getStatements().addAll(b.getAst()); + } // for global required interactions if (method instanceof FeatureMethod) @@ -402,6 +405,54 @@ public void visitMethodAgain(Method method) { clearCurrentBlockOnExit(method.getStatements()); } + + private void addBlockListeners(Block block) { + BlockParseInfo blockType = block.getParseInfo(); + if (blockType == BlockParseInfo.WHERE + || blockType == BlockParseInfo.METHOD_END + || blockType == BlockParseInfo.ANONYMOUS) return; + + // SpockRuntime.enterBlock(getSpecificationContext(), new BlockInfo(blockKind, [blockTexts])) + MethodCallExpression enterBlockCall = createBlockListenerCall(block, blockType, nodeCache.SpockRuntime_CallEnterBlock); + // SpockRuntime.exitedBlock(getSpecificationContext(), new BlockInfo(blockKind, [blockTexts])) + MethodCallExpression exitBlockCall = createBlockListenerCall(block, blockType, nodeCache.SpockRuntime_CallExitBlock); + + // As the cleanup block finalizes the specification, it would override any previous block in ErrorInfo, + // so we only call enterBlock if there is no error yet. + if (blockType == BlockParseInfo.CLEANUP) { + block.getAst().add(0, new IfStatement( + // if ($spock_feature_throwable == null) + new BooleanExpression(AstUtil.createVariableIsNullExpression(new VariableExpression(SpecRewriter.SPOCK_FEATURE_THROWABLE, nodeCache.Throwable))), + new ExpressionStatement(enterBlockCall), + EmptyStatement.INSTANCE + )); + } else { + block.getAst().add(0, new ExpressionStatement(enterBlockCall)); + } + block.getAst().add( new ExpressionStatement(exitBlockCall)); + } + + private MethodCallExpression createBlockListenerCall(Block block, BlockParseInfo blockType, MethodNode blockListenerMethod) { + return createDirectMethodCall( + new ClassExpression(nodeCache.SpockRuntime), + blockListenerMethod, + new ArgumentListExpression( + createDirectMethodCall(VariableExpression.THIS_EXPRESSION, + nodeCache.SpecInternals_GetSpecificationContext, + ArgumentListExpression.EMPTY_ARGUMENTS), + new ConstructorCallExpression(nodeCache.BlockInfo, + new ArgumentListExpression( + new PropertyExpression( + new ClassExpression(nodeCache.BlockKind), + blockType.name() + ), + new ListExpression( + block.getDescriptions().stream().map(ConstantExpression::new).collect(Collectors.toList()) + ) + )) + )); + } + @Override public void visitAnyBlock(Block block) { this.block = block; diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything.groovy index 73f24b5d53..6c2432e75e 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything.groovy @@ -17,4 +17,4 @@ public class apackage.ASpec extends spock.lang.Specification { org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything__Groovy_4_0_2__.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything__Groovy_4_0_2__.groovy index efddcfb896..866d3c94aa 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything__Groovy_4_0_2__.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceFeatureBody_can_render_everything__Groovy_4_0_2__.groovy @@ -17,4 +17,4 @@ public class apackage.ASpec extends spock.lang.Specification implements groovy.l org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceSpecBody_renders_only_methods__fields__properties__object_initializers_and_their_annotation_by_default.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceSpecBody_renders_only_methods__fields__properties__object_initializers_and_their_annotation_by_default.groovy index 8dd68e26fc..050fe98a76 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceSpecBody_renders_only_methods__fields__properties__object_initializers_and_their_annotation_by_default.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/AstSpec__astToSourceSpecBody_renders_only_methods__fields__properties__object_initializers_and_their_annotation_by_default.groovy @@ -22,4 +22,4 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } /*--------- end::snapshot[] ---------*/ -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference.groovy index 7afc507db7..121d96dc1f 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference.groovy @@ -14,10 +14,7 @@ public void $spock_feature_0_0() { java.lang.Object foobar java.lang.Throwable $spock_feature_throwable try { - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) foobar = this.foobar() - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) try { org.spockframework.runtime.SpockRuntime.verifyMethodCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'println(foobar)', 6, 3, null, this, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), 'println'), new java.lang.Object[]{$spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), foobar)}, $spock_valueRecorder.realizeNas(4, false), false, 3) } @@ -25,7 +22,6 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'println(foobar)', 6, 3, null, $spock_condition_throwable)} finally { } - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) } catch (java.lang.Throwable $spock_tmp_throwable) { $spock_feature_throwable = $spock_tmp_throwable @@ -33,11 +29,7 @@ public void $spock_feature_0_0() { } finally { try { - if ( $spock_feature_throwable == null) { - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.CLEANUP, [])) - } foobar.size() - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.CLEANUP, [])) } catch (java.lang.Throwable $spock_tmp_throwable) { if ( $spock_feature_throwable != null) { @@ -55,4 +47,4 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } /*--------- end::snapshot[] ---------*/ -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy index 915f2108bf..593883a373 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/CleanupBlocksAstSpec__cleanup_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy @@ -14,10 +14,7 @@ public void $spock_feature_0_0() { def (java.lang.Object foobar, java.lang.Object b) = [null, null] java.lang.Throwable $spock_feature_throwable try { - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) (foobar, b) = this.foobar() - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) try { org.spockframework.runtime.SpockRuntime.verifyMethodCondition($spock_errorCollector, $spock_valueRecorder.reset(), 'println(foobar)', 6, 3, null, this, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(0), 'println'), new java.lang.Object[]{$spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(1), foobar)}, $spock_valueRecorder.realizeNas(4, false), false, 3) } @@ -25,7 +22,6 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, 'println(foobar)', 6, 3, null, $spock_condition_throwable)} finally { } - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) } catch (java.lang.Throwable $spock_tmp_throwable) { $spock_feature_throwable = $spock_tmp_throwable @@ -33,11 +29,7 @@ public void $spock_feature_0_0() { } finally { try { - if ( $spock_feature_throwable == null) { - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.CLEANUP, [])) - } foobar.size() - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.CLEANUP, [])) } catch (java.lang.Throwable $spock_tmp_throwable) { if ( $spock_feature_throwable != null) { @@ -55,4 +47,4 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } /*--------- end::snapshot[] ---------*/ -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference.groovy index 0b01b5fffc..0ddd3a2533 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference.groovy @@ -10,17 +10,17 @@ public java.lang.Object foobar() { public void $spock_feature_0_0() { try { java.lang.Object foobar + org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) this.getSpecificationContext().setThrownException(null) try { - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) foobar = this.foobar() - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) } catch (java.lang.Throwable $spock_ex) { this.getSpecificationContext().setThrownException($spock_ex) } finally { } + org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) this.thrownImpl(null, null, java.lang.IllegalStateException) org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) @@ -30,4 +30,4 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } /*--------- end::snapshot[] ---------*/ -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy index 64c8c2410b..ad891b0ceb 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/condition/ExceptionConditionsAstSpec__thrown_rewrite_keeps_correct_method_reference_for_multi_assignments.groovy @@ -10,17 +10,17 @@ public java.lang.Object foobar() { public void $spock_feature_0_0() { try { def (java.lang.Object foobar, java.lang.Object b) = [null, null] + org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) this.getSpecificationContext().setThrownException(null) try { - org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) (foobar, b) = this.foobar() - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) } catch (java.lang.Throwable $spock_ex) { this.getSpecificationContext().setThrownException($spock_ex) } finally { } + org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) this.thrownImpl(null, null, java.lang.IllegalStateException) org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) @@ -30,4 +30,4 @@ public void $spock_feature_0_0() { org.spockframework.runtime.SpockRuntime.clearCurrentBlock(this.getSpecificationContext())} } /*--------- end::snapshot[] ---------*/ -} +} \ No newline at end of file diff --git a/spock-specs/src/test/resources/org/spockframework/smoke/ast/mock/MocksAstSpec__simple_interaction.groovy b/spock-specs/src/test/resources/org/spockframework/smoke/ast/mock/MocksAstSpec__simple_interaction.groovy index 24304a1a95..9ae45aef5a 100644 --- a/spock-specs/src/test/resources/org/spockframework/smoke/ast/mock/MocksAstSpec__simple_interaction.groovy +++ b/spock-specs/src/test/resources/org/spockframework/smoke/ast/mock/MocksAstSpec__simple_interaction.groovy @@ -9,14 +9,14 @@ public void $spock_feature_0_0() { try { org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.SETUP, [])) java.util.List list = this.MockImpl('list', java.util.List) - org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.SETUP, [])) this.getSpecificationContext().getMockController().enterScope() this.getSpecificationContext().getMockController().addInteraction(new org.spockframework.mock.runtime.InteractionBuilder(8, 5, '1 * list.add(1)').setFixedCount(1).addEqualTarget(list).addEqualMethodName('add').setArgListKind(true, false).addEqualArg(1).build()) + org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.SETUP, [])) org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) list.add(1) org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.WHEN, [])) - this.getSpecificationContext().getMockController().leaveScope() org.spockframework.runtime.SpockRuntime.callEnterBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) + this.getSpecificationContext().getMockController().leaveScope() org.spockframework.runtime.SpockRuntime.callExitBlock(this.getSpecificationContext(), new org.spockframework.runtime.model.BlockInfo(org.spockframework.runtime.model.BlockKind.THEN, [])) this.getSpecificationContext().getMockController().leaveScope() }