Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions llvm/lib/Support/Mustache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Comment on lines +732 to +735
Copy link
Contributor

@ilovepi ilovepi Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default:
llvm::outs() << "Invalid ASTNode type\n";
break;
}
}
llvm_unreachable("Invalid ASTNode type");

I believe we should get an error if we fail to handle one of the cases due to -Wswitch-enum, so default isn't needed. Since all cases are fully covered, I'd prefer we mark it unreachable, so it breaks loudly. If you're not getting the compile time warning or error diagnostic in your build for the uncovered switch, please let me know so we can fix that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do get a warning about a fully covered switch with this, so we should remove it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, actually, since you're looping over a bunch of things, the unreachable may not work unless you switch break to continue.

}
}

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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ static const StringMap<StringSet<>> XFailTestNames = {{
"Triple Mustache - Standalone",
"Triple Mustache With Padding",
}},
{"partials.json", {"Standalone Indentation"}},
{"sections.json", {"Implicit Iterator - Triple mustache"}},
}};

Expand Down