77// ===----------------------------------------------------------------------===//
88#include " llvm/Support/Mustache.h"
99#include " llvm/ADT/SmallVector.h"
10- #include " llvm/Support/Error.h"
1110#include " llvm/Support/raw_ostream.h"
1211#include < sstream>
1312
@@ -23,6 +22,13 @@ static bool isFalsey(const json::Value &V) {
2322 (V.getAsArray () && V.getAsArray ()->empty ());
2423}
2524
25+ static bool isContextFalsey (const json::Value *V) {
26+ // A missing context (represented by a nullptr) is defined as falsey.
27+ if (!V)
28+ return true ;
29+ return isFalsey (*V);
30+ }
31+
2632static Accessor splitMustacheString (StringRef Str) {
2733 // We split the mustache string into an accessor.
2834 // For example:
@@ -560,68 +566,71 @@ void toMustacheString(const json::Value &Data, raw_ostream &OS) {
560566 }
561567}
562568
563- void ASTNode::render (const json::Value &Data, raw_ostream &OS) {
564- ParentContext = &Data;
569+ void ASTNode::render (const json::Value &CurrentCtx, raw_ostream &OS) {
570+ // Set the parent context to the incoming context so that we
571+ // can walk up the context tree correctly in findContext().
572+ ParentContext = &CurrentCtx;
565573 const json::Value *ContextPtr = Ty == Root ? ParentContext : findContext ();
566- const json::Value &Context = ContextPtr ? *ContextPtr : nullptr ;
567574
568575 switch (Ty) {
569576 case Root:
570- renderChild (Data , OS);
577+ renderChild (CurrentCtx , OS);
571578 return ;
572579 case Text:
573580 OS << Body;
574581 return ;
575582 case Partial: {
576583 auto Partial = Partials.find (AccessorValue[0 ]);
577584 if (Partial != Partials.end ())
578- renderPartial (Data , OS, Partial->getValue ().get ());
585+ renderPartial (CurrentCtx , OS, Partial->getValue ().get ());
579586 return ;
580587 }
581588 case Variable: {
582589 auto Lambda = Lambdas.find (AccessorValue[0 ]);
583- if (Lambda != Lambdas.end ())
584- renderLambdas (Data , OS, Lambda->getValue ());
585- else {
590+ if (Lambda != Lambdas.end ()) {
591+ renderLambdas (CurrentCtx , OS, Lambda->getValue ());
592+ } else if (ContextPtr) {
586593 EscapeStringStream ES (OS, Escapes);
587- toMustacheString (Context , ES);
594+ toMustacheString (*ContextPtr , ES);
588595 }
589596 return ;
590597 }
591598 case UnescapeVariable: {
592599 auto Lambda = Lambdas.find (AccessorValue[0 ]);
593- if (Lambda != Lambdas.end ())
594- renderLambdas (Data, OS, Lambda->getValue ());
595- else
596- toMustacheString (Context, OS);
600+ if (Lambda != Lambdas.end ()) {
601+ renderLambdas (CurrentCtx, OS, Lambda->getValue ());
602+ } else if (ContextPtr) {
603+ toMustacheString (*ContextPtr, OS);
604+ }
597605 return ;
598606 }
599607 case Section: {
600- // Sections are not rendered if the context is falsey.
601608 auto SectionLambda = SectionLambdas.find (AccessorValue[0 ]);
602609 bool IsLambda = SectionLambda != SectionLambdas.end ();
603- if (isFalsey (Context) && !IsLambda)
604- return ;
605610
606611 if (IsLambda) {
607- renderSectionLambdas (Data , OS, SectionLambda->getValue ());
612+ renderSectionLambdas (CurrentCtx , OS, SectionLambda->getValue ());
608613 return ;
609614 }
610615
611- if (Context.getAsArray ()) {
612- const json::Array *Arr = Context.getAsArray ();
616+ if (isContextFalsey (ContextPtr))
617+ return ;
618+
619+ if (const json::Array *Arr = ContextPtr->getAsArray ()) {
613620 for (const json::Value &V : *Arr)
614621 renderChild (V, OS);
615622 return ;
616623 }
617- renderChild (Context , OS);
624+ renderChild (*ContextPtr , OS);
618625 return ;
619626 }
620627 case InvertSection: {
621628 bool IsLambda = SectionLambdas.contains (AccessorValue[0 ]);
622- if (!isFalsey (Context) || IsLambda)
623- return ;
624- renderChild (Context, OS);
629+ if (isContextFalsey (ContextPtr) && !IsLambda) {
630+ // The context for the children remains unchanged from the parent's, so
631+ // we pass this node's original incoming context.
632+ renderChild (CurrentCtx, OS);
633+ }
625634 return ;
626635 }
627636 }
0 commit comments