[clang-tools-extra] 26fe803 - [clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator (#138064)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 23 15:59:45 PDT 2025
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.chou at 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
}
More information about the cfe-commits
mailing list