Skip to content

[clang-doc] Add HTMLMustacheGenerator.cpp #138060

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

Merged
merged 1 commit into from
May 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_clang_library(clangDoc STATIC
Representation.cpp
Serialize.cpp
YAMLGenerator.cpp
HTMLMustacheGenerator.cpp

DEPENDS
omp_gen
Expand All @@ -24,7 +25,7 @@ add_clang_library(clangDoc STATIC

clang_target_link_libraries(clangDoc
PRIVATE
clangDocSupport
clangDocSupport
clangAnalysis
clangAST
clangASTMatchers
Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-doc/Generators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ static int LLVM_ATTRIBUTE_UNUSED MDGeneratorAnchorDest =
MDGeneratorAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED HTMLGeneratorAnchorDest =
HTMLGeneratorAnchorSource;

static int LLVM_ATTRIBUTE_UNUSED MHTMLGeneratorAnchorDest =
MHTMLGeneratorAnchorSource;
} // namespace doc
} // namespace clang
1 change: 1 addition & 0 deletions clang-tools-extra/clang-doc/Generators.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ std::string getTagType(TagTypeKind AS);
extern volatile int YAMLGeneratorAnchorSource;
extern volatile int MDGeneratorAnchorSource;
extern volatile int HTMLGeneratorAnchorSource;
extern volatile int MHTMLGeneratorAnchorSource;

} // namespace doc
} // namespace clang
Expand Down
98 changes: 98 additions & 0 deletions clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
///===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the implementation of the MustacheHTMLGenerator class,
/// which is Clang-Doc generator for HTML using Mustache templates.
///
//===----------------------------------------------------------------------===//

#include "Generators.h"
#include "Representation.h"
#include "support/File.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mustache.h"

using namespace llvm;
using namespace llvm::json;
using namespace llvm::mustache;

namespace clang {
namespace doc {

static Error createFileOpenError(StringRef FileName, std::error_code EC) {
return createFileError("cannot open file " + FileName, EC);
}

class MustacheHTMLGenerator : public Generator {
public:
static const char *Format;
Error generateDocs(StringRef RootDir,
StringMap<std::unique_ptr<doc::Info>> Infos,
const ClangDocContext &CDCtx) override;
Error createResources(ClangDocContext &CDCtx) override;
Error generateDocForInfo(Info *I, raw_ostream &OS,
const ClangDocContext &CDCtx) override;
};

class MustacheTemplateFile : public Template {
public:
static Expected<std::unique_ptr<MustacheTemplateFile>>
createMustacheFile(StringRef FileName) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError =
MemoryBuffer::getFile(FileName);
if (auto EC = BufferOrError.getError())
return createFileOpenError(FileName, EC);

std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get());
StringRef FileContent = Buffer->getBuffer();
return std::make_unique<MustacheTemplateFile>(FileContent);
}

Error registerPartialFile(StringRef Name, StringRef FileName) {
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError =
MemoryBuffer::getFile(FileName);
if (auto EC = BufferOrError.getError())
return createFileOpenError(FileName, EC);

std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get());
StringRef FileContent = Buffer->getBuffer();
registerPartial(Name.str(), FileContent.str());
return Error::success();
}

MustacheTemplateFile(StringRef TemplateStr) : Template(TemplateStr) {}
};

Error MustacheHTMLGenerator::generateDocs(
StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos,
const clang::doc::ClangDocContext &CDCtx) {
return Error::success();
}

Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
const ClangDocContext &CDCtx) {
return Error::success();
}

Error MustacheHTMLGenerator::createResources(ClangDocContext &CDCtx) {
return Error::success();
}

const char *MustacheHTMLGenerator::Format = "mustache";

static GeneratorRegistry::Add<MustacheHTMLGenerator>
MHTML(MustacheHTMLGenerator::Format, "Generator for mustache HTML output.");

// This anchor is used to force the linker to link in the generated object
// file and thus register the generator.
volatile int MHTMLGeneratorAnchorSource = 0;

} // namespace doc
} // namespace clang
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-doc/Representation.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,9 @@ struct ClangDocContext {
std::vector<std::string> JsScripts;
// Base directory for remote repositories.
StringRef Base;
// Maps mustache template types to specific mustache template files.
// Ex. comment-template -> /path/to/comment-template.mustache
llvm::StringMap<std::string> MustacheTemplates;
Index Idx;
};

Expand Down
2 changes: 2 additions & 0 deletions clang-tools-extra/unittests/clang-doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_extra_unittest(ClangDocTests
ClangDocTest.cpp
GeneratorTest.cpp
HTMLGeneratorTest.cpp
HTMLMustacheGeneratorTest.cpp
MDGeneratorTest.cpp
MergeTest.cpp
SerializeTest.cpp
Expand All @@ -36,4 +37,5 @@ clang_target_link_libraries(ClangDocTests
target_link_libraries(ClangDocTests
PRIVATE
clangDoc
LLVMTestingSupport
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//===-- clang-doc/HTMLMustacheGeneratorTest.cpp ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "ClangDocTest.h"
#include "Generators.h"
#include "Representation.h"
#include "clang/Basic/Version.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace testing;
using namespace clang::doc;

static const std::string ClangDocVersion =
clang::getClangToolFullVersion("clang-doc");

static std::unique_ptr<Generator> getHTMLMustacheGenerator() {
auto G = findGeneratorByName("mustache");
if (!G)
return nullptr;
return std::move(G.get());
}

static ClangDocContext
getClangDocContext(std::vector<std::string> UserStylesheets = {},
StringRef RepositoryUrl = "",
StringRef RepositoryLinePrefix = "", StringRef Base = "") {
ClangDocContext CDCtx{
{}, "test-project", {}, {}, {}, RepositoryUrl, RepositoryLinePrefix,
Base, UserStylesheets};
CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(), "");
CDCtx.JsScripts.emplace_back("");
return CDCtx;
}

TEST(HTMLMustacheGeneratorTest, createResources) {
auto G = getHTMLMustacheGenerator();
ASSERT_THAT(G, NotNull()) << "Could not find HTMLMustacheGenerator";
ClangDocContext CDCtx = getClangDocContext();

EXPECT_THAT_ERROR(G->createResources(CDCtx), Succeeded())
<< "Failed to create resources.";
}

TEST(HTMLMustacheGeneratorTest, generateDocs) {
auto G = getHTMLMustacheGenerator();
assert(G && "Could not find HTMLMustacheGenerator");
ClangDocContext CDCtx = getClangDocContext();

StringRef RootDir = "";
EXPECT_THAT_ERROR(G->generateDocs(RootDir, {}, CDCtx), Succeeded())
<< "Failed to generate docs.";
}

TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) {
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";
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();

EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Succeeded())
<< "Failed to generate docs.";

std::string Expected = R"raw()raw";
EXPECT_THAT(Actual.str(), Eq(Expected));
}
Loading