Skip to content

Commit 71b00d1

Browse files
ilovepiPeterChou1
andcommitted
[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 <[email protected]>
1 parent ba7721e commit 71b00d1

File tree

3 files changed

+137
-3
lines changed

3 files changed

+137
-3
lines changed

clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class MustacheHTMLGenerator : public Generator {
4141
const ClangDocContext &CDCtx) override;
4242
};
4343

44+
4445
class MustacheTemplateFile : public Template {
4546
public:
4647
static Expected<std::unique_ptr<MustacheTemplateFile>>
@@ -68,20 +69,121 @@ class MustacheTemplateFile : public Template {
6869
}
6970

7071
MustacheTemplateFile(StringRef TemplateStr) : Template(TemplateStr) {}
72+
private:
7173
};
7274

75+
static std::unique_ptr<MustacheTemplateFile> NamespaceTemplate = nullptr;
76+
77+
static std::unique_ptr<MustacheTemplateFile> RecordTemplate = nullptr;
78+
79+
static Error setupTemplateFiles(const clang::doc::ClangDocContext &CDCtx) {
80+
return Error::success();
81+
}
82+
7383
Error MustacheHTMLGenerator::generateDocs(
7484
StringRef RootDir, StringMap<std::unique_ptr<doc::Info>> Infos,
7585
const clang::doc::ClangDocContext &CDCtx) {
86+
if (auto Err = setupTemplateFiles(CDCtx))
87+
return Err;
88+
// Track which directories we already tried to create.
89+
StringSet<> CreatedDirs;
90+
// Collect all output by file name and create the necessary directories.
91+
StringMap<std::vector<doc::Info *>> FileToInfos;
92+
for (const auto &Group : Infos) {
93+
doc::Info *Info = Group.getValue().get();
94+
95+
SmallString<128> Path;
96+
sys::path::native(RootDir, Path);
97+
sys::path::append(Path, Info->getRelativeFilePath(""));
98+
if (!CreatedDirs.contains(Path)) {
99+
if (std::error_code Err = sys::fs::create_directories(Path);
100+
Err != std::error_code())
101+
return createStringError(Err, "failed to create directory '%s'.",
102+
Path.c_str());
103+
CreatedDirs.insert(Path);
104+
}
105+
106+
sys::path::append(Path, Info->getFileBaseName() + ".html");
107+
FileToInfos[Path].push_back(Info);
108+
}
109+
110+
for (const auto &Group : FileToInfos) {
111+
std::error_code FileErr;
112+
raw_fd_ostream InfoOS(Group.getKey(), FileErr, sys::fs::OF_None);
113+
if (FileErr)
114+
return createStringError(FileErr, "Error opening file '%s'",
115+
Group.getKey().data());
116+
117+
for (const auto &Info : Group.getValue()) {
118+
if (Error Err = generateDocForInfo(Info, InfoOS, CDCtx))
119+
return Err;
120+
}
121+
}
76122
return Error::success();
77123
}
78124

125+
static json::Value extractValue(const NamespaceInfo &I,
126+
const ClangDocContext &CDCtx) {
127+
Object NamespaceValue = Object();
128+
return NamespaceValue;
129+
}
130+
131+
static json::Value extractValue(const RecordInfo &I,
132+
const ClangDocContext &CDCtx) {
133+
Object RecordValue = Object();
134+
return RecordValue;
135+
}
136+
137+
static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
138+
Info *I) {
139+
return createStringError(inconvertibleErrorCode(),
140+
"setupTemplateValue is unimplemented");
141+
}
142+
79143
Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
80144
const ClangDocContext &CDCtx) {
145+
switch (I->IT) {
146+
case InfoType::IT_namespace: {
147+
json::Value V =
148+
extractValue(*static_cast<clang::doc::NamespaceInfo *>(I), CDCtx);
149+
if (auto Err = setupTemplateValue(CDCtx, V, I))
150+
return Err;
151+
NamespaceTemplate->render(V, OS);
152+
break;
153+
}
154+
case InfoType::IT_record: {
155+
json::Value V =
156+
extractValue(*static_cast<clang::doc::RecordInfo *>(I), CDCtx);
157+
if (auto Err = setupTemplateValue(CDCtx, V, I))
158+
return Err;
159+
// Serialize the JSON value to the output stream in a readable format.
160+
RecordTemplate->render(V, OS);
161+
break;
162+
}
163+
case InfoType::IT_enum:
164+
OS << "IT_enum\n";
165+
break;
166+
case InfoType::IT_function:
167+
OS << "IT_Function\n";
168+
break;
169+
case InfoType::IT_typedef:
170+
OS << "IT_typedef\n";
171+
break;
172+
case InfoType::IT_default:
173+
return createStringError(inconvertibleErrorCode(), "unexpected InfoType");
174+
}
81175
return Error::success();
82176
}
83177

84178
Error MustacheHTMLGenerator::createResources(ClangDocContext &CDCtx) {
179+
for (const auto &FilePath : CDCtx.UserStylesheets) {
180+
if (Error Err = copyFile(FilePath, CDCtx.OutDirectory))
181+
return Err;
182+
}
183+
for (const auto &FilePath : CDCtx.JsScripts) {
184+
if (Error Err = copyFile(FilePath, CDCtx.OutDirectory))
185+
return Err;
186+
}
85187
return Error::success();
86188
}
87189

clang-tools-extra/unittests/clang-doc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ clang_target_link_libraries(ClangDocTests
3434
clangTooling
3535
clangToolingCore
3636
)
37+
3738
target_link_libraries(ClangDocTests
3839
PRIVATE
3940
clangDoc

clang-tools-extra/unittests/clang-doc/HTMLMustacheGeneratorTest.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
#include "Generators.h"
1111
#include "Representation.h"
1212
#include "clang/Basic/Version.h"
13+
#include "llvm/Support/Path.h"
1314
#include "llvm/Testing/Support/Error.h"
15+
#include "llvm/Testing/Support/SupportHelpers.h"
1416
#include "gmock/gmock.h"
1517
#include "gtest/gtest.h"
1618

@@ -40,13 +42,43 @@ getClangDocContext(std::vector<std::string> UserStylesheets = {},
4042
return CDCtx;
4143
}
4244

45+
static void verifyFileContents(const Twine &Path, StringRef Contents) {
46+
auto Buffer = MemoryBuffer::getFile(Path);
47+
ASSERT_TRUE((bool)Buffer);
48+
StringRef Data = Buffer.get()->getBuffer();
49+
ASSERT_EQ(Data, Contents);
50+
}
51+
4352
TEST(HTMLMustacheGeneratorTest, createResources) {
4453
auto G = getHTMLMustacheGenerator();
4554
ASSERT_THAT(G, NotNull()) << "Could not find HTMLMustacheGenerator";
4655
ClangDocContext CDCtx = getClangDocContext();
56+
EXPECT_THAT_ERROR(G->createResources(CDCtx), Failed())
57+
<< "Empty UserStylesheets or JsScripts should fail!";
58+
59+
unittest::TempDir RootTestDirectory("createResourcesTest", /*Unique=*/true);
60+
CDCtx.OutDirectory = RootTestDirectory.path();
61+
62+
unittest::TempFile CSS("clang-doc-mustache", "css", "CSS");
63+
unittest::TempFile JS("mustache", "js", "JavaScript");
64+
65+
CDCtx.UserStylesheets[0] = CSS.path();
66+
CDCtx.JsScripts[0] = JS.path();
4767

4868
EXPECT_THAT_ERROR(G->createResources(CDCtx), Succeeded())
49-
<< "Failed to create resources.";
69+
<< "Failed to create resources with valid UserStylesheets and JsScripts";
70+
{
71+
SmallString<256> PathBuff;
72+
llvm::sys::path::append(PathBuff, RootTestDirectory.path(),
73+
"clang-doc-mustache.css");
74+
verifyFileContents(PathBuff, "CSS");
75+
}
76+
77+
{
78+
SmallString<256> PathBuff;
79+
llvm::sys::path::append(PathBuff, RootTestDirectory.path(), "mustache.js");
80+
verifyFileContents(PathBuff, "JavaScript");
81+
}
5082
}
5183

5284
TEST(HTMLMustacheGeneratorTest, generateDocs) {
@@ -79,8 +111,7 @@ TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) {
79111
I.Children.Functions.back().Name = "OneFunction";
80112
I.Children.Enums.emplace_back();
81113

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

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

0 commit comments

Comments
 (0)