private void addBlockListeners(Block block) {
    BlockParseInfo blockType = block.getParseInfo();
    if (!blockType.isSupportingBlockListeners()) return;

    // SpockRuntime.callBlockEntered(getSpecificationContext(), blockMetadataIndex)
    MethodCallExpression blockEnteredCall = createBlockListenerCall(block, nodeCache.SpockRuntime_CallBlockEntered);
    // SpockRuntime.callBlockExited(getSpecificationContext(), blockMetadataIndex)
    MethodCallExpression blockExitedCall = createBlockListenerCall(block, nodeCache.SpockRuntime_CallBlockExited);

    block.getAst().add(0, new ExpressionStatement(blockEnteredCall));
    if (blockType == BlockParseInfo.CLEANUP) {
      // In case of a cleanup block we need store a reference of the previously `currentBlock` in case that an exception occurred
      // and restore it at the end of the cleanup block, so that the correct `BlockInfo` is available for the `IErrorContext`.
      // The restoration happens in the `finally` statement created by `createCleanupTryCatch`.
      VariableExpression failedBlock = new VariableExpression(SpockNames.FAILED_BLOCK, nodeCache.BlockInfo);
      block.getAst().add(0, ifThrowableIsNotNull(storeFailedBlock(failedBlock)));
    }
    block.getAst().add(new ExpressionStatement(blockExitedCall));
  }
A Spec visitor responsible for most of the rewriting of a Spec's AST.

@author Peter Niederwieser
spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java