Skip to content
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

[llvm] add support for mustache templating language #111427

Closed
wants to merge 34 commits into from

Conversation

PeterChou1
Copy link
Contributor

Depends on: #105893

Adds a tool to validate the mustache support library the tool consumes the spec from https://github.com/mustache/spec and validates if any test fails

@PeterChou1 PeterChou1 marked this pull request as ready for review October 7, 2024 19:52
Copy link

github-actions bot commented Oct 7, 2024

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff 62ae01201fc7185aca61d040c4f2df5303bae0ad 70e21e890c0d6ecc5eda7fbfc8c04bd60461ff1e --extensions h,cpp -- llvm/include/llvm/Support/Mustache.h llvm/lib/Support/Mustache.cpp llvm/tools/mustache/mustache.cpp llvm/unittests/Support/MustacheTest.cpp
View the diff from clang-format here.
diff --git a/llvm/include/llvm/Support/Mustache.h b/llvm/include/llvm/Support/Mustache.h
index 4d216ac59c..21e233eb12 100644
--- a/llvm/include/llvm/Support/Mustache.h
+++ b/llvm/include/llvm/Support/Mustache.h
@@ -63,8 +63,8 @@
 #include "Error.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Allocator.h"
-#include "llvm/Support/StringSaver.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/Support/StringSaver.h"
 #include <vector>
 
 namespace llvm {
@@ -129,19 +129,19 @@ public:
     InvertSection,
   };
 
-  ASTNode() : T(Type::Root), LocalContext(nullptr){};
+  ASTNode() : T(Type::Root), LocalContext(nullptr) {};
 
   ASTNode(StringRef Body, ASTNode *Parent)
       : T(Type::Text), Body(Body), Parent(Parent), LocalContext(nullptr),
-        Indentation(0){};
+        Indentation(0) {};
 
   // Constructor for Section/InvertSection/Variable/UnescapeVariable
   ASTNode(Type T, Accessor Accessor, ASTNode *Parent)
       : T(T), Parent(Parent), Children({}), Accessor(Accessor),
-        LocalContext(nullptr), Indentation(0){};
+        LocalContext(nullptr), Indentation(0) {};
 
   void addChild(ASTNode *Child) { Children.emplace_back(Child); };
-  
+
   void setBody(StringRef NewBody) { Body = NewBody; };
 
   void setRawBody(StringRef NewBody) { RawBody = NewBody; };
@@ -149,30 +149,26 @@ public:
   void setIndentation(size_t NewIndentation) { Indentation = NewIndentation; };
 
   void render(llvm::json::Value Data, SmallString<0> &Output);
-  
+
   void setUpNode(llvm::BumpPtrAllocator &Allocator,
-                 StringMap<ASTNode *> &Partials,
-                 StringMap<Lambda> &Lambdas,
+                 StringMap<ASTNode *> &Partials, StringMap<Lambda> &Lambdas,
                  StringMap<SectionLambda> &SectionLambdas,
                  DenseMap<char, StringRef> &Escapes);
+
 private:
-  
-  void renderLambdas(llvm::json::Value& Contexts, 
-                     SmallString<0> &Output,
-                     Lambda& L);
-  
-  void renderSectionLambdas(llvm::json::Value& Contexts, 
-                          SmallString<0> &Output,
-                          SectionLambda& L);
-  
-  void renderPartial(llvm::json::Value& Contexts, 
-                     SmallString<0> &Output,
+  void renderLambdas(llvm::json::Value &Contexts, SmallString<0> &Output,
+                     Lambda &L);
+
+  void renderSectionLambdas(llvm::json::Value &Contexts, SmallString<0> &Output,
+                            SectionLambda &L);
+
+  void renderPartial(llvm::json::Value &Contexts, SmallString<0> &Output,
                      ASTNode *Partial);
 
-  void renderChild(llvm::json::Value& Context, SmallString<0> &Output);
-  
+  void renderChild(llvm::json::Value &Context, SmallString<0> &Output);
+
   llvm::json::Value findContext();
-  
+
   llvm::BumpPtrAllocator *Allocator;
   StringMap<ASTNode *> *Partials;
   StringMap<Lambda> *Lambdas;
diff --git a/llvm/lib/Support/Mustache.cpp b/llvm/lib/Support/Mustache.cpp
index daa2446f92..76532161fd 100644
--- a/llvm/lib/Support/Mustache.cpp
+++ b/llvm/lib/Support/Mustache.cpp
@@ -15,8 +15,8 @@ using namespace llvm::json;
 using namespace llvm::mustache;
 
 SmallString<0> escapeString(StringRef Input,
-                  DenseMap<char, StringRef> &Escape) {
-  
+                            DenseMap<char, StringRef> &Escape) {
+
   SmallString<0> Output;
   for (char C : Input) {
     if (Escape.find(C) != Escape.end())
@@ -42,8 +42,7 @@ Accessor split(StringRef Str, char Delimiter) {
   return Tokens;
 }
 
-void addIndentation(llvm::SmallString<0> &PartialStr,
-                    size_t IndentationSize) {
+void addIndentation(llvm::SmallString<0> &PartialStr, size_t IndentationSize) {
   std::string Indent(IndentationSize, ' ');
   llvm::SmallString<0> Result;
   for (size_t I = 0; I < PartialStr.size(); ++I) {
@@ -175,28 +174,28 @@ SmallVector<Token, 0> tokenize(StringRef Template) {
 
     if (!RequiresCleanUp)
       continue;
-    
-    // We adjust the token body if there's no text behind or ahead a token is 
+
+    // We adjust the token body if there's no text behind or ahead a token is
     // considered surrounded by no text if the right of the previous token
     // is a newline followed by spaces or if the left of the next token
     // is spaces followed by a newline
     // eg.
     //  "Line 1\n {{#section}} \n Line 2 \n {{/section}} \n Line 3"
-    
+
     bool NoTextBehind = noTextBehind(Idx, Tokens);
     bool NoTextAhead = noTextAhead(Idx, Tokens);
-    
+
     // Adjust next token body if there is no text ahead
-    // eg. 
+    // eg.
     //  The template string
     //  "{{! Comment }} \nLine 2"
-    // would be considered as no text ahead and should be render as 
+    // would be considered as no text ahead and should be render as
     //  " Line 2"
     if ((NoTextBehind && NoTextAhead) || (NoTextAhead && Idx == 0)) {
       Token &NextToken = Tokens[Idx + 1];
       StringRef NextTokenBody = NextToken.getTokenBody();
       // cut off the leading newline which could be \n or \r\n
-      if (NextTokenBody.starts_with("\r\n")) 
+      if (NextTokenBody.starts_with("\r\n"))
         NextToken.setTokenBody(NextTokenBody.substr(2));
       else if (NextTokenBody.starts_with("\n"))
         NextToken.setTokenBody(NextTokenBody.substr(1));
@@ -205,9 +204,9 @@ SmallVector<Token, 0> tokenize(StringRef Template) {
     // eg.
     //  The template string
     //  " \t{{#section}}A{{/section}}"
-    // would be considered as no text ahead and should be render as 
+    // would be considered as no text ahead and should be render as
     //  "A"
-    // The exception for this is partial tag which requires us to 
+    // The exception for this is partial tag which requires us to
     // keep track of the indentation once it's rendered
     if (((NoTextBehind && NoTextAhead) || (NoTextBehind && Idx == LastIdx))) {
       Token &PrevToken = Tokens[Idx - 1];
@@ -230,7 +229,6 @@ public:
   ASTNode *parse();
 
 private:
-  
   void parseMustache(ASTNode *Parent);
 
   BumpPtrAllocator &Allocator;
@@ -352,7 +350,7 @@ Template::Template(StringRef TemplateStr) {
   registerEscape(HtmlEntities);
 }
 
-void toJsonString(Value &Data, SmallString<0>& Output) {
+void toJsonString(Value &Data, SmallString<0> &Output) {
   if (Data.getAsNull())
     return;
   if (auto *Arr = Data.getAsArray())
@@ -377,7 +375,6 @@ bool isFalsey(Value &V) {
          (V.getAsObject() && V.getAsObject()->empty());
 }
 
-
 void ASTNode::render(Value Data, SmallString<0> &Output) {
   LocalContext = Data;
   Value Context = T == Root ? Data : findContext();
@@ -418,12 +415,12 @@ void ASTNode::render(Value Data, SmallString<0> &Output) {
     bool IsLambda = SectionLambda != SectionLambdas->end();
     if (isFalsey(Context) && !IsLambda)
       return;
-    
+
     if (IsLambda) {
-        renderSectionLambdas(Data, Output, SectionLambda->getValue());
-        return;
+      renderSectionLambdas(Data, Output, SectionLambda->getValue());
+      return;
     }
-    
+
     if (Context.getAsArray()) {
       SmallString<0> Result;
       json::Array *Arr = Context.getAsArray();
@@ -432,16 +429,15 @@ void ASTNode::render(Value Data, SmallString<0> &Output) {
       Output = Result;
       return;
     }
-    
+
     renderChild(Context, Output);
   }
   case InvertSection: {
-    bool IsLambda = SectionLambdas->find(Accessor[0]) != 
-                    SectionLambdas->end();
-    
+    bool IsLambda = SectionLambdas->find(Accessor[0]) != SectionLambdas->end();
+
     if (!isFalsey(Context) || IsLambda)
       return;
-    
+
     renderChild(Context, Output);
   }
   }
@@ -451,8 +447,8 @@ void ASTNode::render(Value Data, SmallString<0> &Output) {
 Value ASTNode::findContext() {
   // The mustache spec allows for dot notation to access nested values
   // a single dot refers to the current context.
-  // We attempt to find the JSON context in the current node, if it is not 
-  // found, then we traverse the parent nodes to find the context until we 
+  // We attempt to find the JSON context in the current node, if it is not
+  // found, then we traverse the parent nodes to find the context until we
   // reach the root node or the context is found
   if (Accessor.empty())
     return nullptr;
@@ -493,25 +489,19 @@ void ASTNode::renderChild(Value &Context, SmallString<0> &Output) {
   }
 }
 
-void ASTNode::renderPartial(Value &Context, 
-                            SmallString<0> &Output,
+void ASTNode::renderPartial(Value &Context, SmallString<0> &Output,
                             ASTNode *Partial) {
   Partial->render(Context, Output);
   addIndentation(Output, Indentation);
 }
 
-void ASTNode::renderLambdas(Value &Context, 
-                            SmallString<0> &Output,
-                            Lambda& L) {
+void ASTNode::renderLambdas(Value &Context, SmallString<0> &Output, Lambda &L) {
   Value LambdaResult = L();
   SmallString<0> LambdaStr;
   toJsonString(LambdaResult, LambdaStr);
   Parser P = Parser(LambdaStr, *Allocator);
   ASTNode *LambdaNode = P.parse();
-  LambdaNode->setUpNode(*Allocator, 
-                        *Partials, 
-                        *Lambdas, 
-                        *SectionLambdas,
+  LambdaNode->setUpNode(*Allocator, *Partials, *Lambdas, *SectionLambdas,
                         *Escapes);
   LambdaNode->render(Context, Output);
   if (T == Variable)
@@ -519,9 +509,7 @@ void ASTNode::renderLambdas(Value &Context,
   return;
 }
 
-
-void ASTNode::renderSectionLambdas(Value &Contexts, 
-                                   SmallString<0> &Output,
+void ASTNode::renderSectionLambdas(Value &Contexts, SmallString<0> &Output,
                                    SectionLambda &L) {
   Value Return = L(RawBody);
   if (isFalsey(Return))
@@ -530,21 +518,16 @@ void ASTNode::renderSectionLambdas(Value &Contexts,
   toJsonString(Return, LambdaStr);
   Parser P = Parser(LambdaStr, *Allocator);
   ASTNode *LambdaNode = P.parse();
-  LambdaNode->setUpNode(*Allocator, 
-                        *Partials, 
-                        *Lambdas, 
-                        *SectionLambdas,
+  LambdaNode->setUpNode(*Allocator, *Partials, *Lambdas, *SectionLambdas,
                         *Escapes);
   LambdaNode->render(Contexts, Output);
   return;
 }
 
-void ASTNode::setUpNode(BumpPtrAllocator &Alloc,
-                        StringMap<ASTNode *> &Par,
-                        StringMap<Lambda> &L,
-                        StringMap<SectionLambda> &SC,
+void ASTNode::setUpNode(BumpPtrAllocator &Alloc, StringMap<ASTNode *> &Par,
+                        StringMap<Lambda> &L, StringMap<SectionLambda> &SC,
                         DenseMap<char, StringRef> &E) {
-  
+
   // Passed down datastructures needed for rendering to
   // the children nodes
   Allocator = &Alloc;
@@ -554,5 +537,4 @@ void ASTNode::setUpNode(BumpPtrAllocator &Alloc,
   Escapes = &E;
   for (ASTNode *Child : Children)
     Child->setUpNode(Alloc, Par, L, SC, E);
-  
 }

@PeterChou1 PeterChou1 closed this Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant