-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[llvm][mustache] Introduce MustacheContext to simplify mustache APIs #159191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This was referenced Sep 16, 2025
This was referenced Sep 16, 2025
@llvm/pr-subscribers-llvm-support Author: Paul Kirth (ilovepi) ChangesFull diff: https://github.com/llvm/llvm-project/pull/159191.diff 2 Files Affected:
diff --git a/llvm/include/llvm/Support/Mustache.h b/llvm/include/llvm/Support/Mustache.h
index 781ec557950ec..ee9f40638fd12 100644
--- a/llvm/include/llvm/Support/Mustache.h
+++ b/llvm/include/llvm/Support/Mustache.h
@@ -85,6 +85,14 @@ using SectionLambda = std::function<llvm::json::Value(std::string)>;
class ASTNode;
using AstPtr = std::unique_ptr<ASTNode>;
+using EscapeMap = DenseMap<char, std::string>;
+
+struct MustacheContext {
+ StringMap<AstPtr> Partials;
+ StringMap<Lambda> Lambdas;
+ StringMap<SectionLambda> SectionLambdas;
+ EscapeMap Escapes;
+};
// A Template represents the container for the AST and the partials
// and Lambdas that are registered with it.
@@ -118,10 +126,7 @@ class Template {
LLVM_ABI void overrideEscapeCharacters(DenseMap<char, std::string> Escapes);
private:
- StringMap<AstPtr> Partials;
- StringMap<Lambda> Lambdas;
- StringMap<SectionLambda> SectionLambdas;
- DenseMap<char, std::string> Escapes;
+ MustacheContext Ctx;
AstPtr Tree;
};
} // namespace llvm::mustache
diff --git a/llvm/lib/Support/Mustache.cpp b/llvm/lib/Support/Mustache.cpp
index f948344883452..9dbc87a457e97 100644
--- a/llvm/lib/Support/Mustache.cpp
+++ b/llvm/lib/Support/Mustache.cpp
@@ -139,26 +139,17 @@ class ASTNode {
InvertSection,
};
- ASTNode(llvm::StringMap<AstPtr> &Partials, llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas, EscapeMap &Escapes)
- : Partials(Partials), Lambdas(Lambdas), SectionLambdas(SectionLambdas),
- Escapes(Escapes), Ty(Type::Root), Parent(nullptr),
- ParentContext(nullptr) {}
+ ASTNode(MustacheContext &Ctx)
+ : Ctx(Ctx), Ty(Type::Root), Parent(nullptr), ParentContext(nullptr) {}
- ASTNode(std::string Body, ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas, EscapeMap &Escapes)
- : Partials(Partials), Lambdas(Lambdas), SectionLambdas(SectionLambdas),
- Escapes(Escapes), Ty(Type::Text), Body(std::move(Body)), Parent(Parent),
+ ASTNode(MustacheContext &Ctx, std::string Body, ASTNode *Parent)
+ : Ctx(Ctx), Ty(Type::Text), Body(std::move(Body)), Parent(Parent),
ParentContext(nullptr) {}
// Constructor for Section/InvertSection/Variable/UnescapeVariable Nodes
- ASTNode(Type Ty, Accessor Accessor, ASTNode *Parent,
- llvm::StringMap<AstPtr> &Partials, llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas, EscapeMap &Escapes)
- : Partials(Partials), Lambdas(Lambdas), SectionLambdas(SectionLambdas),
- Escapes(Escapes), Ty(Ty), Parent(Parent),
- AccessorValue(std::move(Accessor)), ParentContext(nullptr) {}
+ ASTNode(MustacheContext &Ctx, Type Ty, Accessor Accessor, ASTNode *Parent)
+ : Ctx(Ctx), Ty(Ty), Parent(Parent), AccessorValue(std::move(Accessor)),
+ ParentContext(nullptr) {}
void addChild(AstPtr Child) { Children.emplace_back(std::move(Child)); };
@@ -190,10 +181,7 @@ class ASTNode {
void renderSection(const json::Value &CurrentCtx, raw_ostream &OS);
void renderInvertSection(const json::Value &CurrentCtx, raw_ostream &OS);
- StringMap<AstPtr> &Partials;
- StringMap<Lambda> &Lambdas;
- StringMap<SectionLambda> &SectionLambdas;
- EscapeMap &Escapes;
+ MustacheContext &Ctx;
Type Ty;
size_t Indentation = 0;
std::string RawBody;
@@ -206,29 +194,18 @@ class ASTNode {
};
// A wrapper for arena allocator for ASTNodes
-static AstPtr createRootNode(llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes) {
- return std::make_unique<ASTNode>(Partials, Lambdas, SectionLambdas, Escapes);
+static AstPtr createRootNode(MustacheContext &Ctx) {
+ return std::make_unique<ASTNode>(Ctx);
}
-static AstPtr createNode(ASTNode::Type T, Accessor A, ASTNode *Parent,
- llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes) {
- return std::make_unique<ASTNode>(T, std::move(A), Parent, Partials, Lambdas,
- SectionLambdas, Escapes);
+static AstPtr createNode(MustacheContext &Ctx, ASTNode::Type T, Accessor A,
+ ASTNode *Parent) {
+ return std::make_unique<ASTNode>(Ctx, T, std::move(A), Parent);
}
-static AstPtr createTextNode(std::string Body, ASTNode *Parent,
- llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes) {
- return std::make_unique<ASTNode>(std::move(Body), Parent, Partials, Lambdas,
- SectionLambdas, Escapes);
+static AstPtr createTextNode(MustacheContext &Ctx, std::string Body,
+ ASTNode *Parent) {
+ return std::make_unique<ASTNode>(Ctx, std::move(Body), Parent);
}
// Function to check if there is meaningful text behind.
@@ -545,39 +522,26 @@ class AddIndentationStringStream : public raw_ostream {
class Parser {
public:
- Parser(StringRef TemplateStr) : TemplateStr(TemplateStr) {}
+ Parser(StringRef TemplateStr, MustacheContext &Ctx)
+ : Ctx(Ctx), TemplateStr(TemplateStr) {}
- AstPtr parse(llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes);
+ AstPtr parse();
private:
- void parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes);
-
- void parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
- llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes);
+ void parseMustache(ASTNode *Parent);
+ void parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A);
+ MustacheContext &Ctx;
SmallVector<Token> Tokens;
size_t CurrentPtr;
StringRef TemplateStr;
};
-void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
- llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes) {
- AstPtr CurrentNode =
- createNode(Ty, A, Parent, Partials, Lambdas, SectionLambdas, Escapes);
+void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty,
+ const Accessor &A) {
+ AstPtr CurrentNode = createNode(Ctx, Ty, A, Parent);
size_t Start = CurrentPtr;
- parseMustache(CurrentNode.get(), Partials, Lambdas, SectionLambdas, Escapes);
+ parseMustache(CurrentNode.get());
const size_t End = CurrentPtr - 1;
std::string RawBody;
for (std::size_t I = Start; I < End; I++)
@@ -586,21 +550,15 @@ void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty, const Accessor &A,
Parent->addChild(std::move(CurrentNode));
}
-AstPtr Parser::parse(llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes) {
+AstPtr Parser::parse() {
Tokens = tokenize(TemplateStr);
CurrentPtr = 0;
- AstPtr RootNode = createRootNode(Partials, Lambdas, SectionLambdas, Escapes);
- parseMustache(RootNode.get(), Partials, Lambdas, SectionLambdas, Escapes);
+ AstPtr RootNode = createRootNode(Ctx);
+ parseMustache(RootNode.get());
return RootNode;
}
-void Parser::parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
- llvm::StringMap<Lambda> &Lambdas,
- llvm::StringMap<SectionLambda> &SectionLambdas,
- EscapeMap &Escapes) {
+void Parser::parseMustache(ASTNode *Parent) {
while (CurrentPtr < Tokens.size()) {
Token CurrentToken = Tokens[CurrentPtr];
@@ -610,38 +568,34 @@ void Parser::parseMustache(ASTNode *Parent, llvm::StringMap<AstPtr> &Partials,
switch (CurrentToken.getType()) {
case Token::Type::Text: {
- CurrentNode = createTextNode(std::move(CurrentToken.TokenBody), Parent,
- Partials, Lambdas, SectionLambdas, Escapes);
+ CurrentNode =
+ createTextNode(Ctx, std::move(CurrentToken.TokenBody), Parent);
Parent->addChild(std::move(CurrentNode));
break;
}
case Token::Type::Variable: {
- CurrentNode = createNode(ASTNode::Variable, std::move(A), Parent,
- Partials, Lambdas, SectionLambdas, Escapes);
+ CurrentNode = createNode(Ctx, ASTNode::Variable, std::move(A), Parent);
Parent->addChild(std::move(CurrentNode));
break;
}
case Token::Type::UnescapeVariable: {
- CurrentNode = createNode(ASTNode::UnescapeVariable, std::move(A), Parent,
- Partials, Lambdas, SectionLambdas, Escapes);
+ CurrentNode =
+ createNode(Ctx, ASTNode::UnescapeVariable, std::move(A), Parent);
Parent->addChild(std::move(CurrentNode));
break;
}
case Token::Type::Partial: {
- CurrentNode = createNode(ASTNode::Partial, std::move(A), Parent, Partials,
- Lambdas, SectionLambdas, Escapes);
+ CurrentNode = createNode(Ctx, ASTNode::Partial, std::move(A), Parent);
CurrentNode->setIndentation(CurrentToken.getIndentation());
Parent->addChild(std::move(CurrentNode));
break;
}
case Token::Type::SectionOpen: {
- parseSection(Parent, ASTNode::Section, A, Partials, Lambdas,
- SectionLambdas, Escapes);
+ parseSection(Parent, ASTNode::Section, A);
break;
}
case Token::Type::InvertSectionOpen: {
- parseSection(Parent, ASTNode::InvertSection, A, Partials, Lambdas,
- SectionLambdas, Escapes);
+ parseSection(Parent, ASTNode::InvertSection, A);
break;
}
case Token::Type::Comment:
@@ -691,25 +645,25 @@ void ASTNode::renderRoot(const json::Value &CurrentCtx, raw_ostream &OS) {
void ASTNode::renderText(raw_ostream &OS) { OS << Body; }
void ASTNode::renderPartial(const json::Value &CurrentCtx, raw_ostream &OS) {
- auto Partial = Partials.find(AccessorValue[0]);
- if (Partial != Partials.end())
+ auto Partial = Ctx.Partials.find(AccessorValue[0]);
+ if (Partial != Ctx.Partials.end())
renderPartial(CurrentCtx, OS, Partial->getValue().get());
}
void ASTNode::renderVariable(const json::Value &CurrentCtx, raw_ostream &OS) {
- auto Lambda = Lambdas.find(AccessorValue[0]);
- if (Lambda != Lambdas.end()) {
+ auto Lambda = Ctx.Lambdas.find(AccessorValue[0]);
+ if (Lambda != Ctx.Lambdas.end()) {
renderLambdas(CurrentCtx, OS, Lambda->getValue());
} else if (const json::Value *ContextPtr = findContext()) {
- EscapeStringStream ES(OS, Escapes);
+ EscapeStringStream ES(OS, Ctx.Escapes);
toMustacheString(*ContextPtr, ES);
}
}
void ASTNode::renderUnescapeVariable(const json::Value &CurrentCtx,
raw_ostream &OS) {
- auto Lambda = Lambdas.find(AccessorValue[0]);
- if (Lambda != Lambdas.end()) {
+ auto Lambda = Ctx.Lambdas.find(AccessorValue[0]);
+ if (Lambda != Ctx.Lambdas.end()) {
renderLambdas(CurrentCtx, OS, Lambda->getValue());
} else if (const json::Value *ContextPtr = findContext()) {
toMustacheString(*ContextPtr, OS);
@@ -717,8 +671,8 @@ void ASTNode::renderUnescapeVariable(const json::Value &CurrentCtx,
}
void ASTNode::renderSection(const json::Value &CurrentCtx, raw_ostream &OS) {
- auto SectionLambda = SectionLambdas.find(AccessorValue[0]);
- if (SectionLambda != SectionLambdas.end()) {
+ auto SectionLambda = Ctx.SectionLambdas.find(AccessorValue[0]);
+ if (SectionLambda != Ctx.SectionLambdas.end()) {
renderSectionLambdas(CurrentCtx, OS, SectionLambda->getValue());
return;
}
@@ -737,7 +691,7 @@ void ASTNode::renderSection(const json::Value &CurrentCtx, raw_ostream &OS) {
void ASTNode::renderInvertSection(const json::Value &CurrentCtx,
raw_ostream &OS) {
- bool IsLambda = SectionLambdas.contains(AccessorValue[0]);
+ bool IsLambda = Ctx.SectionLambdas.contains(AccessorValue[0]);
const json::Value *ContextPtr = findContext();
if (isContextFalsey(ContextPtr) && !IsLambda) {
renderChild(CurrentCtx, OS);
@@ -833,10 +787,10 @@ void ASTNode::renderLambdas(const json::Value &Contexts, llvm::raw_ostream &OS,
std::string LambdaStr;
raw_string_ostream Output(LambdaStr);
toMustacheString(LambdaResult, Output);
- Parser P = Parser(LambdaStr);
- AstPtr LambdaNode = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
+ Parser P(LambdaStr, Ctx);
+ AstPtr LambdaNode = P.parse();
- EscapeStringStream ES(OS, Escapes);
+ EscapeStringStream ES(OS, Ctx.Escapes);
if (Ty == Variable) {
LambdaNode->render(Contexts, ES);
return;
@@ -852,8 +806,8 @@ void ASTNode::renderSectionLambdas(const json::Value &Contexts,
std::string LambdaStr;
raw_string_ostream Output(LambdaStr);
toMustacheString(Return, Output);
- Parser P = Parser(LambdaStr);
- AstPtr LambdaNode = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
+ Parser P(LambdaStr, Ctx);
+ AstPtr LambdaNode = P.parse();
LambdaNode->render(Contexts, OS);
}
@@ -862,22 +816,26 @@ void Template::render(const json::Value &Data, llvm::raw_ostream &OS) {
}
void Template::registerPartial(std::string Name, std::string Partial) {
- Parser P = Parser(Partial);
- AstPtr PartialTree = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
- Partials.insert(std::make_pair(Name, std::move(PartialTree)));
+ Parser P(Partial, Ctx);
+ AstPtr PartialTree = P.parse();
+ Ctx.Partials.insert(std::make_pair(Name, std::move(PartialTree)));
}
-void Template::registerLambda(std::string Name, Lambda L) { Lambdas[Name] = L; }
+void Template::registerLambda(std::string Name, Lambda L) {
+ Ctx.Lambdas[Name] = L;
+}
void Template::registerLambda(std::string Name, SectionLambda L) {
- SectionLambdas[Name] = L;
+ Ctx.SectionLambdas[Name] = L;
}
-void Template::overrideEscapeCharacters(EscapeMap E) { Escapes = std::move(E); }
+void Template::overrideEscapeCharacters(EscapeMap E) {
+ Ctx.Escapes = std::move(E);
+}
Template::Template(StringRef TemplateStr) {
- Parser P = Parser(TemplateStr);
- Tree = P.parse(Partials, Lambdas, SectionLambdas, Escapes);
+ Parser P(TemplateStr, Ctx);
+ Tree = P.parse();
// The default behavior is to escape html entities.
const EscapeMap HtmlEntities = {{'&', "&"},
{'<', "<"},
@@ -888,18 +846,13 @@ Template::Template(StringRef TemplateStr) {
}
Template::Template(Template &&Other) noexcept
- : Partials(std::move(Other.Partials)), Lambdas(std::move(Other.Lambdas)),
- SectionLambdas(std::move(Other.SectionLambdas)),
- Escapes(std::move(Other.Escapes)), Tree(std::move(Other.Tree)) {}
+ : Ctx(std::move(Other.Ctx)), Tree(std::move(Other.Tree)) {}
Template::~Template() = default;
Template &Template::operator=(Template &&Other) noexcept {
if (this != &Other) {
- Partials = std::move(Other.Partials);
- Lambdas = std::move(Other.Lambdas);
- SectionLambdas = std::move(Other.SectionLambdas);
- Escapes = std::move(Other.Escapes);
+ Ctx = std::move(Other.Ctx);
Tree = std::move(Other.Tree);
Other.Tree = nullptr;
}
|
cbc8872
to
f441a1c
Compare
608c9bf
to
e79233d
Compare
a31a1ef
to
de12e19
Compare
452b7c4
to
ea687e4
Compare
de12e19
to
1b4ad5d
Compare
evelez7
approved these changes
Sep 29, 2025
1b4ad5d
to
d0ee769
Compare
2ddc19d
to
bfd4244
Compare
d0ee769
to
446d204
Compare
Just return an optional pair of StringRefs instead.
7be7b16
to
cb3731b
Compare
446d204
to
9e5c507
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/116/builds/19044 Here is the relevant piece of the build log for the reference
|
mahesh-attarde
pushed a commit
to mahesh-attarde/llvm-project
that referenced
this pull request
Oct 3, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.