Author: Paul Kirth
Date: 2025-05-23T15:59:42-07:00
New Revision: 26fe803b9fcc555ce7f719b542a05690805d5140

URL: 
https://github.com/llvm/llvm-project/commit/26fe803b9fcc555ce7f719b542a05690805d5140
DIFF: 
https://github.com/llvm/llvm-project/commit/26fe803b9fcc555ce7f719b542a05690805d5140.diff

LOG: [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator 
(#138064)

This patch implements the business logic for setupTemplateValue, which
was split from #133161. The implementation configures the relative path
relationships between the various HTML components, and prepares them
prior to their use in the generator.

Co-authored-by: Peter Chou <peter.c...@mail.utoronto.ca>

Added: 
    

Modified: 
    clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
    clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp 
b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index 18ee3b8d0fc43..65dc2e93582e8 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -397,7 +397,7 @@ static json::Value extractValue(const RecordInfo &I,
 
   maybeInsertLocation(I.DefLoc, CDCtx, RecordValue);
 
-  StringRef BasePath = I.getRelativeFilePath("");
+  SmallString<64> BasePath = I.getRelativeFilePath("");
   extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx);
   json::Value PublicMembers = Array();
   json::Array &PubMemberRef = *PublicMembers.getAsArray();
@@ -431,8 +431,28 @@ static json::Value extractValue(const RecordInfo &I,
 
 static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
                                 Info *I) {
-  return createStringError(inconvertibleErrorCode(),
-                           "setupTemplateValue is unimplemented");
+  V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName});
+  json::Value StylesheetArr = Array();
+  auto InfoPath = I->getRelativeFilePath("");
+  SmallString<128> RelativePath = computeRelativePath("", InfoPath);
+  sys::path::native(RelativePath, sys::path::Style::posix);
+  for (const auto &FilePath : CDCtx.UserStylesheets) {
+    SmallString<128> StylesheetPath = RelativePath;
+    sys::path::append(StylesheetPath, sys::path::Style::posix,
+                      sys::path::filename(FilePath));
+    StylesheetArr.getAsArray()->emplace_back(StylesheetPath);
+  }
+  V.getAsObject()->insert({"Stylesheets", StylesheetArr});
+
+  json::Value ScriptArr = Array();
+  for (auto Script : CDCtx.JsScripts) {
+    SmallString<128> JsPath = RelativePath;
+    sys::path::append(JsPath, sys::path::Style::posix,
+                      sys::path::filename(Script));
+    ScriptArr.getAsArray()->emplace_back(JsPath);
+  }
+  V.getAsObject()->insert({"Scripts", ScriptArr});
+  return Error::success();
 }
 
 Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
@@ -443,6 +463,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, 
raw_ostream &OS,
         extractValue(*static_cast<clang::doc::NamespaceInfo *>(I), CDCtx);
     if (auto Err = setupTemplateValue(CDCtx, V, I))
       return Err;
+    assert(NamespaceTemplate && "NamespaceTemplate is nullptr.");
     NamespaceTemplate->render(V, OS);
     break;
   }

diff  --git 
a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp 
b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp
index 4c8cf4fa7e460..95acd363a958e 100644
--- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp
+++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp
@@ -20,10 +20,14 @@
 
 using namespace llvm;
 using namespace testing;
+using namespace clang;
 using namespace clang::doc;
 
-static const std::string ClangDocVersion =
-    clang::getClangToolFullVersion("clang-doc");
+// FIXME: Don't enable unit tests that can read files. Remove once we can use
+// lit to test these properties.
+#define ENABLE_LOCAL_TEST 0
+
+static const std::string ClangDocVersion = 
getClangToolFullVersion("clang-doc");
 
 static std::unique_ptr<Generator> getHTMLMustacheGenerator() {
   auto G = findGeneratorByName("mustache");
@@ -91,37 +95,190 @@ TEST(HTMLMustacheGeneratorTest, generateDocs) {
   unittest::TempDir RootTestDirectory("generateDocsTest", /*Unique=*/true);
   CDCtx.OutDirectory = RootTestDirectory.path();
 
+#if ENABLE_LOCAL_TEST
   // FIXME: We can't read files during unit tests. Migrate to lit once
   // tool support lands.
-  // getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
+  getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
 
+  EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
+                    Succeeded())
+      << "Failed to generate docs.";
+#else
   EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
                     Failed())
       << "Failed to generate docs.";
+#endif
 }
 
-TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) {
+TEST(HTMLGeneratorTest, emitFunctionHTML) {
+#if ENABLE_LOCAL_TEST
   auto G = getHTMLMustacheGenerator();
   assert(G && "Could not find HTMLMustacheGenerator");
   ClangDocContext CDCtx = getClangDocContext();
   std::string Buffer;
   llvm::raw_string_ostream Actual(Buffer);
-  NamespaceInfo I;
-  I.Name = "Namespace";
+
+  unittest::TempDir RootTestDirectory("emitRecordHTML",
+                                      /*Unique=*/true);
+  CDCtx.OutDirectory = RootTestDirectory.path();
+
+  getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
+
+  // FIXME: This is a terrible hack, since we can't initialize the templates
+  // directly. We'll need to update the interfaces so that we can call
+  // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
+  EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
+                    Succeeded())
+      << "Failed to generate docs.";
+
+  CDCtx.RepositoryUrl = "http://www.repository.com";;
+
+  FunctionInfo I;
+  I.Name = "f";
   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
 
-  I.Children.Namespaces.emplace_back(EmptySID, "ChildNamespace",
-                                     InfoType::IT_namespace,
-                                     "Namespace::ChildNamespace", "Namespace");
-  I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
-                                  "Namespace::ChildStruct", "Namespace");
-  I.Children.Functions.emplace_back();
-  I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none;
-  I.Children.Functions.back().Name = "OneFunction";
-  I.Children.Enums.emplace_back();
+  I.DefLoc = Location(10, 10, "dir/test.cpp", true);
+  I.Loc.emplace_back(12, 12, "test.cpp");
+
+  I.Access = AccessSpecifier::AS_none;
+
+  SmallString<16> PathTo;
+  llvm::sys::path::native("path/to", PathTo);
+  I.ReturnType = doc::TypeInfo(
+      Reference(EmptySID, "float", InfoType::IT_default, "float", PathTo));
+  I.Params.emplace_back(doc::TypeInfo("int", PathTo), "P");
+  I.IsMethod = true;
+  I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
+
+  auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
+  assert(!Err);
+  std::string Expected = R"raw(IT_Function
+)raw";
+
+  // FIXME: Functions are not handled yet.
+  EXPECT_EQ(Expected, Actual.str());
+#endif
+}
+
+TEST(HTMLMustacheGeneratorTest, emitEnumHTML) {
+#if ENABLE_LOCAL_TEST
+  auto G = getHTMLMustacheGenerator();
+  assert(G && "Could not find HTMLMustacheGenerator");
+  ClangDocContext CDCtx = getClangDocContext();
+  std::string Buffer;
+  llvm::raw_string_ostream Actual(Buffer);
+
+  unittest::TempDir RootTestDirectory("emitEnumHTML",
+                                      /*Unique=*/true);
+  CDCtx.OutDirectory = RootTestDirectory.path();
+
+  getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
+
+  // FIXME: This is a terrible hack, since we can't initialize the templates
+  // directly. We'll need to update the interfaces so that we can call
+  // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
+  EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
+                    Succeeded())
+      << "Failed to generate docs.";
+
+  CDCtx.RepositoryUrl = "http://www.repository.com";;
+
+  EnumInfo I;
+  I.Name = "e";
+  I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+
+  I.DefLoc = Location(10, 10, "test.cpp", true);
+  I.Loc.emplace_back(12, 12, "test.cpp");
+
+  I.Members.emplace_back("X");
+  I.Scoped = true;
+
+  auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
+  assert(!Err);
+
+  std::string Expected = R"raw(IT_enum
+)raw";
+
+  // FIXME: Enums are not handled yet.
+  EXPECT_EQ(Expected, Actual.str());
+#endif
+}
+
+TEST(HTMLMustacheGeneratorTest, emitCommentHTML) {
+#if ENABLE_LOCAL_TEST
+  auto G = getHTMLMustacheGenerator();
+  assert(G && "Could not find HTMLMustacheGenerator");
+  ClangDocContext CDCtx = getClangDocContext();
+  std::string Buffer;
+  llvm::raw_string_ostream Actual(Buffer);
+
+  unittest::TempDir RootTestDirectory("emitCommentHTML",
+                                      /*Unique=*/true);
+  CDCtx.OutDirectory = RootTestDirectory.path();
+
+  getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
+
+  // FIXME: This is a terrible hack, since we can't initialize the templates
+  // directly. We'll need to update the interfaces so that we can call
+  // SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
+  EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
+                    Succeeded())
+      << "Failed to generate docs.";
+
+  CDCtx.RepositoryUrl = "http://www.repository.com";;
+
+  FunctionInfo I;
+  I.Name = "f";
+  I.DefLoc = Location(10, 10, "test.cpp", true);
+  I.ReturnType = doc::TypeInfo("void");
+  I.Params.emplace_back(doc::TypeInfo("int"), "I");
+  I.Params.emplace_back(doc::TypeInfo("int"), "J");
+  I.Access = AccessSpecifier::AS_none;
+
+  CommentInfo Top;
+  Top.Kind = "FullComment";
+
+  Top.Children.emplace_back(std::make_unique<CommentInfo>());
+  CommentInfo *BlankLine = Top.Children.back().get();
+  BlankLine->Kind = "ParagraphComment";
+  BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
+  BlankLine->Children.back()->Kind = "TextComment";
+
+  Top.Children.emplace_back(std::make_unique<CommentInfo>());
+  CommentInfo *Brief = Top.Children.back().get();
+  Brief->Kind = "ParagraphComment";
+  Brief->Children.emplace_back(std::make_unique<CommentInfo>());
+  Brief->Children.back()->Kind = "TextComment";
+  Brief->Children.back()->Name = "ParagraphComment";
+  Brief->Children.back()->Text = " Brief description.";
+
+  Top.Children.emplace_back(std::make_unique<CommentInfo>());
+  CommentInfo *Extended = Top.Children.back().get();
+  Extended->Kind = "ParagraphComment";
+  Extended->Children.emplace_back(std::make_unique<CommentInfo>());
+  Extended->Children.back()->Kind = "TextComment";
+  Extended->Children.back()->Text = " Extended description that";
+  Extended->Children.emplace_back(std::make_unique<CommentInfo>());
+  Extended->Children.back()->Kind = "TextComment";
+  Extended->Children.back()->Text = " continues onto the next line.";
+
+  Top.Children.emplace_back(std::make_unique<CommentInfo>());
+  CommentInfo *Entities = Top.Children.back().get();
+  Entities->Kind = "ParagraphComment";
+  Entities->Children.emplace_back(std::make_unique<CommentInfo>());
+  Entities->Children.back()->Kind = "TextComment";
+  Entities->Children.back()->Name = "ParagraphComment";
+  Entities->Children.back()->Text =
+      " Comment with html entities: &, <, >, \", \'.";
+
+  I.Description.emplace_back(std::move(Top));
 
-  EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed());
+  auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
+  assert(!Err);
+  std::string Expected = R"raw(IT_Function
+)raw";
 
-  std::string Expected = R"raw()raw";
-  EXPECT_THAT(Actual.str(), Eq(Expected));
+  // FIXME: Functions are not handled yet.
+  EXPECT_EQ(Expected, Actual.str());
+#endif
 }


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to