docs: public static void setContainerBlockInputs(RuleBuildContext context,
                                                  List<JavaBlockDescr> descrs,
                                                  JavaContainerBlockDescr parentBlock,
                                                  String originalCode,
                                                  BoundIdentifiers bindings,
                                                  Map<String, Class<?>> parentVars,
                                                  int offset) {
          StringBuilder consequence = new StringBuilder();
          int lastAdded = 0;
  
          // strip blocks, so we can analyse this block with MVEL
          for (JavaBlockDescr block : parentBlock.getJavaBlockDescrs()) {
              if (block.getEnd() == 0) {
                  // do nothing, it was incorrectly parsed, but this error should be picked up else where
                  continue;
              }
  
              if (block.getType() == JavaBlockDescr.BlockType.TRY) {
                  // adding previous chunk up to the start of this block
                  consequence.append(originalCode.substring(lastAdded,
                          block.getStart() - 1 - offset));
                  JavaTryBlockDescr tryDescr = (JavaTryBlockDescr) block;
                  if (tryDescr.getFinal() != null) {
                      lastAdded = tryDescr.getFinal().getEnd() - offset;
                  } else {
                      lastAdded = tryDescr.getCatches().get(tryDescr.getCatches().size() - 1).getEnd() - offset;
                  }
  
                  stripTryDescr(originalCode,
                          consequence,
                          (JavaTryBlockDescr) block,
                          offset);
              } else if (block.getType() == JavaBlockDescr.BlockType.THROW) {
                  // adding previous chunk up to the start of this block
                  consequence.append(originalCode.substring(lastAdded,
                          block.getStart() - 1 - offset));
  
                  JavaThrowBlockDescr throwBlock = (JavaThrowBlockDescr) block;
                  addWhiteSpaces(originalCode, consequence, throwBlock.getStart() - offset, throwBlock.getTextStart() - offset);
                  consequence.append(originalCode.substring(throwBlock.getTextStart() - offset - 1, throwBlock.getEnd() - 1 - offset)).append(";");
                  lastAdded = throwBlock.getEnd() - offset;
              } else if (block.getType() == JavaBlockDescr.BlockType.IF) {
                  // adding previous chunk up to the start of this block
                  consequence.append(originalCode.substring(lastAdded,
                          block.getStart() - 1 - offset));
                  JavaIfBlockDescr ifDescr = (JavaIfBlockDescr) block;
                  lastAdded = ifDescr.getEnd() - offset;
                  stripBlockDescr(originalCode,
                                  consequence,
                                  ifDescr,
                                  offset);
              } else if (block.getType() == JavaBlockDescr.BlockType.ELSE) {
                  // adding previous chunk up to the start of this block
                  consequence.append(originalCode.substring(lastAdded,
                          block.getStart() - 1 - offset));
                  JavaElseBlockDescr elseDescr = (JavaElseBlockDescr) block;
                  lastAdded = elseDescr.getEnd() - offset;
                  stripBlockDescr(originalCode,
                                  consequence,
                                  elseDescr,
                                  offset);
              } else if (block.getType() == JavaBlockDescr.BlockType.WHILE) {
                  // adding previous chunk up to the start of this block
                  consequence.append(originalCode.substring(lastAdded,
                          block.getStart() - 1 - offset));
                  JavaWhileBlockDescr whileDescr = (JavaWhileBlockDescr) block;
                  lastAdded = whileDescr.getEnd() - offset;
                  stripBlockDescr(originalCode,
                                  consequence,
                                  whileDescr,
                                  offset);
              } else if (block.getType() == JavaBlockDescr.BlockType.FOR) {
                  // adding previous chunk up to the start of this block
                  consequence.append(originalCode.substring(lastAdded,
                          block.getStart() - 1 - offset));
                  JavaForBlockDescr forDescr = (JavaForBlockDescr) block;
                  lastAdded = forDescr.getEnd() - offset;
                  stripBlockDescr(originalCode,
                                  consequence,
                                  forDescr,
                                  offset);
              }
          }
          consequence.append(originalCode.substring(lastAdded));
  
          // We need to do this as MVEL doesn't recognise "modify"
          MacroProcessor macroProcessor = new MacroProcessor();
          Map<String, Macro> macros = new HashMap<String, Macro>(MVELConsequenceBuilder.macros);
          macros.put("modify",
                  new Macro() {
                      public String doMacro() {
                          return "with  ";
                      }
                  });
          macroProcessor.setMacros(macros);
          String mvelCode = macroProcessor.parse(consequence.toString());
  
  
          Map<String, Class<?>> inputs = getInputs(context, mvelCode, bindings, parentVars);
          inputs.putAll(parentVars);
          parentBlock.setInputs(inputs);
  
          // now go depth, set inputs for each nested container
          // set inputs for current container blocks to be rewritten
          for (JavaBlockDescr block : parentBlock.getJavaBlockDescrs()) {
              if (block.getType() == JavaBlockDescr.BlockType.TRY) {
                  JavaTryBlockDescr tryBlock = (JavaTryBlockDescr) block;
                  setContainerBlockInputs(context,
                          descrs,
                          tryBlock,
                          originalCode.substring(tryBlock.getTextStart() - offset, tryBlock.getEnd() - 1 - offset),
                          bindings,
                          inputs,
                          tryBlock.getTextStart());
                  for (JavaCatchBlockDescr catchBlock : tryBlock.getCatches()) {
                      setContainerBlockInputs(context,
                              descrs,
                              catchBlock,
                              catchBlock.getClause() + "=null;" + originalCode.substring(catchBlock.getTextStart() - offset, catchBlock.getEnd() - 1 - offset),
                              bindings,
                              inputs,
                              tryBlock.getTextStart());
                  }
  
                  if (tryBlock.getFinal() != null) {
                      JavaFinalBlockDescr finalBlock = tryBlock.getFinal();
                      setContainerBlockInputs(context,
                              descrs,
                              finalBlock,
                              originalCode.substring(finalBlock.getTextStart() - offset, finalBlock.getEnd() - 1 - offset),
                              bindings,
                              inputs,
                              tryBlock.getTextStart());
                  }
              } else if (block.getType() == JavaBlockDescr.BlockType.IF) {
                  JavaIfBlockDescr ifBlock = (JavaIfBlockDescr) block;
                  int adjustBlock = (originalCode.charAt(ifBlock.getTextStart() - offset - 1) == '{') ? 0 : 1;
                  setContainerBlockInputs(context,
                          descrs,
                          ifBlock,
                          originalCode.substring(ifBlock.getTextStart() - offset + adjustBlock, ifBlock.getEnd() - 1 - offset - adjustBlock),
                          bindings,
                          inputs,
                          ifBlock.getTextStart());
              } else if (block.getType() == JavaBlockDescr.BlockType.ELSE) {
                  JavaElseBlockDescr elseBlock = (JavaElseBlockDescr) block;
                  int adjustBlock = (originalCode.charAt(elseBlock.getTextStart() - offset - 1) == '{') ? 0 : 1;
                  setContainerBlockInputs(context,
                          descrs,
                          elseBlock,
                          originalCode.substring(elseBlock.getTextStart() - offset + adjustBlock, elseBlock.getEnd() - 1 - offset - adjustBlock),
                          bindings,
                          inputs,
                          elseBlock.getTextStart());
              } else if (block.getType() == JavaBlockDescr.BlockType.WHILE) {
                  JavaWhileBlockDescr whileBlock = (JavaWhileBlockDescr) block;
                  int adjustBlock = (originalCode.charAt(whileBlock.getTextStart() - offset - 1) == '{') ? 0 : 1;
                  setContainerBlockInputs(context,
                          descrs,
                          whileBlock,
                          originalCode.substring(whileBlock.getTextStart() - offset + adjustBlock, whileBlock.getEnd() - 1 - offset - adjustBlock),
                          bindings,
                          inputs,
                          whileBlock.getTextStart());
              } else if (block.getType() == JavaBlockDescr.BlockType.FOR) {
                  JavaForBlockDescr forBlock = (JavaForBlockDescr) block;
                  int adjustBlock = (originalCode.charAt(forBlock.getTextStart() - offset - 1) == '{') ? 0 : 1;
                  setContainerBlockInputs(context,
                          descrs,
                          forBlock,
                          originalCode.substring(forBlock.getStartParen() - offset, forBlock.getInitEnd() - offset) +
                                  originalCode.substring(forBlock.getTextStart() - offset + adjustBlock, forBlock.getEnd() - 1 - offset - adjustBlock),
                          bindings,
                          inputs,
                          forBlock.getTextStart() - (forBlock.getInitEnd() - forBlock.getStartParen()));
              } else {
                  block.setInputs(inputs); // each block to be rewritten now knows it's own variables
                  descrs.add(block);
              }
          }
      }