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