https://github.com/ilovepi updated https://github.com/llvm/llvm-project/pull/138061
>From 1925647e9577d827a87d1c7ac4326836928f90e0 Mon Sep 17 00:00:00 2001 From: Paul Kirth <paulki...@google.com> Date: Wed, 30 Apr 2025 08:09:41 -0700 Subject: [PATCH] [clang-doc] Add HTMLMustacheGenerator methods Split from #133161. This patch fills in the implementation for a number of the MustacheHTMLGenerator methods. Many of these APIs are just stubbed out, and will have their implementation filled in by later patches. Co-authored-by: Peter Chou <peter.c...@mail.utoronto.ca> --- .../clang-doc/HTMLMustacheGenerator.cpp | 98 +++++++++++++++++++ .../unittests/clang-doc/CMakeLists.txt | 1 + .../clang-doc/HTMLMustacheGeneratorTest.cpp | 37 ++++++- 3 files changed, 133 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp index 6ba0325685599..879987b5292ed 100644 --- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp @@ -70,18 +70,116 @@ class MustacheTemplateFile : public Template { MustacheTemplateFile(StringRef TemplateStr) : Template(TemplateStr) {} }; +static std::unique_ptr<MustacheTemplateFile> NamespaceTemplate = nullptr; + +static std::unique_ptr<MustacheTemplateFile> RecordTemplate = nullptr; + +static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) { + return Error::success(); +} + Error MustacheHTMLGenerator::generateDocs( StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos, const clang::doc::ClangDocContext &CDCtx) { + if (auto Err = setupTemplateFiles(CDCtx)) + return Err; + // Track which directories we already tried to create. + StringSet<> CreatedDirs; + // Collect all output by file name and create the necessary directories. + StringMap<std::vector<doc::Info *>> FileToInfos; + for (const auto &Group : Infos) { + doc::Info *Info = Group.getValue().get(); + + SmallString<128> Path; + sys::path::native(RootDir, Path); + sys::path::append(Path, Info->getRelativeFilePath("")); + if (!CreatedDirs.contains(Path)) { + if (std::error_code EC = sys::fs::create_directories(Path)) + return createStringError(EC, "failed to create directory '%s'.", + Path.c_str()); + CreatedDirs.insert(Path); + } + + sys::path::append(Path, Info->getFileBaseName() + ".html"); + FileToInfos[Path].push_back(Info); + } + + for (const auto &Group : FileToInfos) { + std::error_code FileErr; + raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_None); + if (FileErr) + return createFileOpenError(Group.getKey(), FileErr); + + for (const auto &Info : Group.getValue()) { + if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx)) + return Err; + } + } return Error::success(); } +static json::Value extractValue(const NamespaceInfo &I, + const ClangDocContext &CDCtx) { + Object NamespaceValue = Object(); + return NamespaceValue; +} + +static json::Value extractValue(const RecordInfo &I, + const ClangDocContext &CDCtx) { + Object RecordValue = Object(); + return RecordValue; +} + +static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V, + Info *I) { + return createStringError(inconvertibleErrorCode(), + "setupTemplateValue is unimplemented"); +} + Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS, const ClangDocContext &CDCtx) { + switch (I->IT) { + case InfoType::IT_namespace: { + json::Value V = + extractValue(*static_cast<clang::doc::NamespaceInfo *>(I), CDCtx); + if (auto Err = setupTemplateValue(CDCtx, V, I)) + return Err; + NamespaceTemplate->render(V, OS); + break; + } + case InfoType::IT_record: { + json::Value V = + extractValue(*static_cast<clang::doc::RecordInfo *>(I), CDCtx); + if (auto Err = setupTemplateValue(CDCtx, V, I)) + return Err; + // Serialize the JSON value to the output stream in a readable format. + RecordTemplate->render(V, OS); + break; + } + case InfoType::IT_enum: + OS << "IT_enum\n"; + break; + case InfoType::IT_function: + OS << "IT_Function\n"; + break; + case InfoType::IT_typedef: + OS << "IT_typedef\n"; + break; + case InfoType::IT_default: + return createStringError(inconvertibleErrorCode(), "unexpected InfoType"); + } return Error::success(); } Error MustacheHTMLGenerator::createResources(ClangDocContext &CDCtx) { + for (const auto &FilePath : CDCtx.UserStylesheets) { + if (Error Err = copyFile(FilePath, CDCtx.OutDirectory)) + return Err; + } + for (const auto &FilePath : CDCtx.JsScripts) { + if (Error Err = copyFile(FilePath, CDCtx.OutDirectory)) + return Err; + } return Error::success(); } diff --git a/clang-tools-extra/unittests/clang-doc/CMakeLists.txt b/clang-tools-extra/unittests/clang-doc/CMakeLists.txt index 81c18e6014072..fd14d85c63485 100644 --- a/clang-tools-extra/unittests/clang-doc/CMakeLists.txt +++ b/clang-tools-extra/unittests/clang-doc/CMakeLists.txt @@ -34,6 +34,7 @@ clang_target_link_libraries(ClangDocTests clangTooling clangToolingCore ) + target_link_libraries(ClangDocTests PRIVATE clangDoc diff --git a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp index cd82fc5ae7fa0..773dbef8e652d 100644 --- a/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp @@ -10,7 +10,9 @@ #include "Generators.h" #include "Representation.h" #include "clang/Basic/Version.h" +#include "llvm/Support/Path.h" #include "llvm/Testing/Support/Error.h" +#include "llvm/Testing/Support/SupportHelpers.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -40,13 +42,43 @@ getClangDocContext(std::vector<std::string> UserStylesheets = {}, return CDCtx; } +static void verifyFileContents(const Twine &Path, StringRef Contents) { + auto Buffer = MemoryBuffer::getFile(Path); + ASSERT_TRUE((bool)Buffer); + StringRef Data = Buffer.get()->getBuffer(); + ASSERT_EQ(Data, Contents); +} + TEST(HTMLMustacheGeneratorTest, createResources) { auto G = getHTMLMustacheGenerator(); ASSERT_THAT(G, NotNull()) << "Could not find HTMLMustacheGenerator"; ClangDocContext CDCtx = getClangDocContext(); + EXPECT_THAT_ERROR(G->createResources(CDCtx), Failed()) + << "Empty UserStylesheets or JsScripts should fail!"; + + unittest::TempDir RootTestDirectory("createResourcesTest", /*Unique=*/true); + CDCtx.OutDirectory = RootTestDirectory.path(); + + unittest::TempFile CSS("clang-doc-mustache", "css", "CSS"); + unittest::TempFile JS("mustache", "js", "JavaScript"); + + CDCtx.UserStylesheets[0] = CSS.path(); + CDCtx.JsScripts[0] = JS.path(); EXPECT_THAT_ERROR(G->createResources(CDCtx), Succeeded()) - << "Failed to create resources."; + << "Failed to create resources with valid UserStylesheets and JsScripts"; + { + SmallString<256> PathBuff; + llvm::sys::path::append(PathBuff, RootTestDirectory.path(), + "clang-doc-mustache.css"); + verifyFileContents(PathBuff, "CSS"); + } + + { + SmallString<256> PathBuff; + llvm::sys::path::append(PathBuff, RootTestDirectory.path(), "mustache.js"); + verifyFileContents(PathBuff, "JavaScript"); + } } TEST(HTMLMustacheGeneratorTest, generateDocs) { @@ -79,8 +111,7 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) { I.Children.Functions.back().Name = "OneFunction"; I.Children.Enums.emplace_back(); - EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Succeeded()) - << "Failed to generate docs."; + EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed()); std::string Expected = R"raw()raw"; EXPECT_THAT(Actual.str(), Eq(Expected)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits