diff --git a/llvm/lib/Support/Mustache.cpp b/llvm/lib/Support/Mustache.cpp index 6c2ed6c84c6cf..40b39b803c40f 100644 --- a/llvm/lib/Support/Mustache.cpp +++ b/llvm/lib/Support/Mustache.cpp @@ -166,6 +166,10 @@ class ASTNode { void renderSectionLambdas(const llvm::json::Value &Contexts, llvm::raw_ostream &OS, SectionLambda &L); + void indentTextNode(std::string &Body, size_t Indentation, bool FinalNode); + + void indentNodes(ASTNode *Node, bool IsPartial); + void renderPartial(const llvm::json::Value &Contexts, llvm::raw_ostream &OS, ASTNode *Partial); @@ -681,10 +685,61 @@ void ASTNode::renderChild(const json::Value &Contexts, llvm::raw_ostream &OS) { Child->render(Contexts, OS); } +void ASTNode::indentTextNode(std::string &Body, size_t Indentation, + bool FinalNode) { + std::string Spaces(Indentation, ' '); + size_t Pos = 0; + size_t LastChar = std::string::npos; + + if (FinalNode) + LastChar = Body.find_last_not_of(" \t\r\f\v"); + + while ((Pos = Body.find('\n', Pos)) != std::string::npos) { + if (FinalNode && (Pos == LastChar)) + break; + + Body.insert(Pos + 1, Spaces); + Pos += 1 + Indentation; + LastChar += Indentation; + } +} + +void ASTNode::indentNodes(ASTNode *Node, bool IsPartial) { + size_t Size = Node->Children.size(); + + for (size_t i = 0; i < Size; ++i) { + ASTNode *Child = Node->Children[i].get(); + switch (Child->Ty) { + case ASTNode::Text: { + // Only track the final node for partials. + bool IsFinalNode = ((i == Size - 1) && IsPartial); + indentTextNode(Child->Body, Indentation, IsFinalNode); + break; + } + case ASTNode::Section: { + indentNodes(Child, false); + break; + } + case ASTNode::Partial: { + indentNodes(Child, true); + break; + } + case ASTNode::Root: + case ASTNode::Variable: + case ASTNode::UnescapeVariable: + case ASTNode::InvertSection: + break; + default: + llvm::outs() << "Invalid ASTNode type\n"; + break; + } + } +} + void ASTNode::renderPartial(const json::Value &Contexts, llvm::raw_ostream &OS, ASTNode *Partial) { - AddIndentationStringStream IS(OS, Indentation); - Partial->render(Contexts, IS); + indentNodes(Partial, true); + Partial->render(Contexts, OS); } void ASTNode::renderLambdas(const json::Value &Contexts, llvm::raw_ostream &OS, diff --git a/llvm/utils/llvm-test-mustache-spec/llvm-test-mustache-spec.cpp b/llvm/utils/llvm-test-mustache-spec/llvm-test-mustache-spec.cpp index 1f566e13f070a..a3d0f661ec36e 100644 --- a/llvm/utils/llvm-test-mustache-spec/llvm-test-mustache-spec.cpp +++ b/llvm/utils/llvm-test-mustache-spec/llvm-test-mustache-spec.cpp @@ -141,7 +141,6 @@ static const StringMap> XFailTestNames = {{ "Triple Mustache - Standalone", "Triple Mustache With Padding", }}, - {"partials.json", {"Standalone Indentation"}}, {"sections.json", {"Implicit Iterator - Triple mustache"}}, }};