Program: 29350
Project: 29350
Buggy source:
/** 
 * Renders a   {@link SoyValueProvider} incrementally via {@link SoyValueProvider#renderAndResolve}<p>The strategy is to: <ul> <li>Stash the SoyValueProvider in a field   {@code $currentRenderee}, so that if we detach halfway through rendering we don't lose the value. Note, we could use the scope/variable system of   {@link TemplateVariableManager} to manage this value, but we know there willonly ever be 1 live at a time, so we can just manage the single special field ourselves. <li>Apply all the streaming autoescapers to the current appendable. Also, stash it in the {@code $currentAppendable} field for the same reasons as above.<li>Invoke  {@link SoyValueProvider#renderAndResolve} with the standard detach logic.<li>Clear the two fields once rendering is complete. </ul> <p>TODO(lukes): if the expression is a param, then this is kind of silly since it looks like <pre> {@code SoyValueProvider localParam = this.param; this.currentRenderee = localParam; SoyValueProvider localRenderee = this.currentRenderee; localRenderee.renderAndResolve();}</pre> <p>In this case we could elide the currentRenderee altogether if we knew the soyValueProvider expression was just a field read... And this is the _common_case for .renderAndResolve calls. to actually do this we could add a mechanism similar to the SaveStrategy enum for expressions, kind of like   {@link Expression#isCheap()} which isn't that useful in practice.
 * @param soyValueProvider The value to render incrementally
 * @param directives The streaming print directives applied to the expression
 * @param reattachPoint The point where execution should resume if the soyValueProvider detacheswhile being evaluated.
 * @return a statement for the full render.
 */
private Statement renderIncrementally(Expression soyValueProvider,List<PrintDirectiveNode> directives,Label reattachPoint){
  FieldRef currentRendereeField=variables.getCurrentRenderee();
  Statement initRenderee=currentRendereeField.putInstanceField(thisVar,soyValueProvider).labelStart(reattachPoint);
  Statement clearRenderee=currentRendereeField.putInstanceField(thisVar,constantNull(SOY_VALUE_PROVIDER_TYPE));
  Statement initAppendable=Statement.NULL_STATEMENT;
  Statement clearAppendable=Statement.NULL_STATEMENT;
  Expression appendable=appendableExpression;
  if (!directives.isEmpty()) {
    Label printDirectiveArgumentReattachPoint=new Label();
    AppendableAndOptions wrappedAppendable=applyStreamingPrintDirectives(directives,appendable,exprCompiler.asBasicCompiler(printDirectiveArgumentReattachPoint),parameterLookup.getRenderContext());
    FieldRef currentAppendableField=variables.getCurrentAppendable();
    initAppendable=currentAppendableField.putInstanceField(thisVar,wrappedAppendable.appendable()).labelStart(printDirectiveArgumentReattachPoint);
    appendable=currentAppendableField.accessor(thisVar);
    clearAppendable=currentAppendableField.putInstanceField(thisVar,constantNull(LOGGING_ADVISING_APPENDABLE_TYPE));
    if (wrappedAppendable.closeable()) {
      clearAppendable=Statement.concat(currentAppendableField.accessor(thisVar).checkedCast(BytecodeUtils.CLOSEABLE_TYPE).invokeVoid(MethodRef.CLOSEABLE_CLOSE),clearAppendable);
    }
  }
  Expression callRenderAndResolve=currentRendereeField.accessor(thisVar).invoke(MethodRef.SOY_VALUE_PROVIDER_RENDER_AND_RESOLVE,appendable,constant(false));
  Statement doCall=detachState.detachForRender(callRenderAndResolve);
  return Statement.concat(initRenderee,initAppendable,doCall,clearAppendable,clearRenderee);
}

Fixed version (ground truth):
/** 
 * Renders a   {@link SoyValueProvider} incrementally via {@link SoyValueProvider#renderAndResolve}<p>The strategy is to: <ul> <li>Stash the SoyValueProvider in a field   {@code $currentRenderee}, so that if we detach halfway through rendering we don't lose the value. Note, we could use the scope/variable system of   {@link TemplateVariableManager} to manage this value, but we know there willonly ever be 1 live at a time, so we can just manage the single special field ourselves. <li>Apply all the streaming autoescapers to the current appendable. Also, stash it in the {@code $currentAppendable} field for the same reasons as above.<li>Invoke  {@link SoyValueProvider#renderAndResolve} with the standard detach logic.<li>Clear the two fields once rendering is complete. </ul> <p>TODO(lukes): if the expression is a param, then this is kind of silly since it looks like <pre> {@code SoyValueProvider localParam = this.param; this.currentRenderee = localParam; SoyValueProvider localRenderee = this.currentRenderee; localRenderee.renderAndResolve();}</pre> <p>In this case we could elide the currentRenderee altogether if we knew the soyValueProvider expression was just a field read... And this is the _common_case for .renderAndResolve calls. to actually do this we could add a mechanism similar to the SaveStrategy enum for expressions, kind of like   {@link Expression#isCheap()} which isn't that useful in practice.
 * @param soyValueProvider The value to render incrementally
 * @param directives The streaming print directives applied to the expression
 * @param reattachPoint The point where execution should resume if the soyValueProvider detacheswhile being evaluated.
 * @return a statement for the full render.
 */
private Statement renderIncrementally(Expression soyValueProvider,List<PrintDirectiveNode> directives,Label reattachPoint){
  FieldRef currentRendereeField=variables.getCurrentRenderee();
  Statement initRenderee=currentRendereeField.putInstanceField(thisVar,soyValueProvider).labelStart(reattachPoint);
  Statement clearRenderee=currentRendereeField.putInstanceField(thisVar,constantNull(SOY_VALUE_PROVIDER_TYPE));
  Statement initAppendable=Statement.NULL_STATEMENT;
  Statement clearAppendable=Statement.NULL_STATEMENT;
  Expression appendable=appendableExpression;
  if (!directives.isEmpty()) {
    Label printDirectiveArgumentReattachPoint=new Label();
    AppendableAndOptions wrappedAppendable=applyStreamingPrintDirectives(directives,appendable,exprCompiler.asBasicCompiler(printDirectiveArgumentReattachPoint),parameterLookup.getRenderContext(),variables);
    FieldRef currentAppendableField=variables.getCurrentAppendable();
    initAppendable=currentAppendableField.putInstanceField(thisVar,wrappedAppendable.appendable()).labelStart(printDirectiveArgumentReattachPoint);
    appendable=currentAppendableField.accessor(thisVar);
    clearAppendable=currentAppendableField.putInstanceField(thisVar,constantNull(LOGGING_ADVISING_APPENDABLE_TYPE));
    if (wrappedAppendable.closeable()) {
      clearAppendable=Statement.concat(currentAppendableField.accessor(thisVar).checkedCast(BytecodeUtils.CLOSEABLE_TYPE).invokeVoid(MethodRef.CLOSEABLE_CLOSE),clearAppendable);
    }
  }
  Expression callRenderAndResolve=currentRendereeField.accessor(thisVar).invoke(MethodRef.SOY_VALUE_PROVIDER_RENDER_AND_RESOLVE,appendable,constant(false));
  Statement doCall=detachState.detachForRender(callRenderAndResolve);
  return Statement.concat(initRenderee,initAppendable,doCall,clearAppendable,clearRenderee);
}