Skip to content

Commit 26fe803

Browse files
ilovepiPeterChou1
andauthored
[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 <[email protected]>
1 parent a8be7a7 commit 26fe803

File tree

2 files changed

+199
-21
lines changed

2 files changed

+199
-21
lines changed

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ static json::Value extractValue(const RecordInfo &I,
397397

398398
maybeInsertLocation(I.DefLoc, CDCtx, RecordValue);
399399

400-
StringRef BasePath = I.getRelativeFilePath("");
400+
SmallString<64> BasePath = I.getRelativeFilePath("");
401401
extractScopeChildren(I.Children, RecordValue, BasePath, CDCtx);
402402
json::Value PublicMembers = Array();
403403
json::Array &PubMemberRef = *PublicMembers.getAsArray();
@@ -431,8 +431,28 @@ static json::Value extractValue(const RecordInfo &I,
431431

432432
static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
433433
Info *I) {
434-
return createStringError(inconvertibleErrorCode(),
435-
"setupTemplateValue is unimplemented");
434+
V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName});
435+
json::Value StylesheetArr = Array();
436+
auto InfoPath = I->getRelativeFilePath("");
437+
SmallString<128> RelativePath = computeRelativePath("", InfoPath);
438+
sys::path::native(RelativePath, sys::path::Style::posix);
439+
for (const auto &FilePath : CDCtx.UserStylesheets) {
440+
SmallString<128> StylesheetPath = RelativePath;
441+
sys::path::append(StylesheetPath, sys::path::Style::posix,
442+
sys::path::filename(FilePath));
443+
StylesheetArr.getAsArray()->emplace_back(StylesheetPath);
444+
}
445+
V.getAsObject()->insert({"Stylesheets", StylesheetArr});
446+
447+
json::Value ScriptArr = Array();
448+
for (auto Script : CDCtx.JsScripts) {
449+
SmallString<128> JsPath = RelativePath;
450+
sys::path::append(JsPath, sys::path::Style::posix,
451+
sys::path::filename(Script));
452+
ScriptArr.getAsArray()->emplace_back(JsPath);
453+
}
454+
V.getAsObject()->insert({"Scripts", ScriptArr});
455+
return Error::success();
436456
}
437457

438458
Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
@@ -443,6 +463,7 @@ Error MustacheHTMLGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
443463
extractValue(*static_cast<clang::doc::NamespaceInfo *>(I), CDCtx);
444464
if (auto Err = setupTemplateValue(CDCtx, V, I))
445465
return Err;
466+
assert(NamespaceTemplate && "NamespaceTemplate is nullptr.");
446467
NamespaceTemplate->render(V, OS);
447468
break;
448469
}

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

Lines changed: 175 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@
2020

2121
using namespace llvm;
2222
using namespace testing;
23+
using namespace clang;
2324
using namespace clang::doc;
2425

25-
static const std::string ClangDocVersion =
26-
clang::getClangToolFullVersion("clang-doc");
26+
// FIXME: Don't enable unit tests that can read files. Remove once we can use
27+
// lit to test these properties.
28+
#define ENABLE_LOCAL_TEST 0
29+
30+
static const std::string ClangDocVersion = getClangToolFullVersion("clang-doc");
2731

2832
static std::unique_ptr<Generator> getHTMLMustacheGenerator() {
2933
auto G = findGeneratorByName("mustache");
@@ -91,37 +95,190 @@ TEST(HTMLMustacheGeneratorTest, generateDocs) {
9195
unittest::TempDir RootTestDirectory("generateDocsTest", /*Unique=*/true);
9296
CDCtx.OutDirectory = RootTestDirectory.path();
9397

98+
#if ENABLE_LOCAL_TEST
9499
// FIXME: We can't read files during unit tests. Migrate to lit once
95100
// tool support lands.
96-
// getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
101+
getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
97102

103+
EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
104+
Succeeded())
105+
<< "Failed to generate docs.";
106+
#else
98107
EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
99108
Failed())
100109
<< "Failed to generate docs.";
110+
#endif
101111
}
102112

103-
TEST(HTMLMustacheGeneratorTest, generateDocsForInfo) {
113+
TEST(HTMLGeneratorTest, emitFunctionHTML) {
114+
#if ENABLE_LOCAL_TEST
104115
auto G = getHTMLMustacheGenerator();
105116
assert(G && "Could not find HTMLMustacheGenerator");
106117
ClangDocContext CDCtx = getClangDocContext();
107118
std::string Buffer;
108119
llvm::raw_string_ostream Actual(Buffer);
109-
NamespaceInfo I;
110-
I.Name = "Namespace";
120+
121+
unittest::TempDir RootTestDirectory("emitRecordHTML",
122+
/*Unique=*/true);
123+
CDCtx.OutDirectory = RootTestDirectory.path();
124+
125+
getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
126+
127+
// FIXME: This is a terrible hack, since we can't initialize the templates
128+
// directly. We'll need to update the interfaces so that we can call
129+
// SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
130+
EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
131+
Succeeded())
132+
<< "Failed to generate docs.";
133+
134+
CDCtx.RepositoryUrl = "http://www.repository.com";
135+
136+
FunctionInfo I;
137+
I.Name = "f";
111138
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
112139

113-
I.Children.Namespaces.emplace_back(EmptySID, "ChildNamespace",
114-
InfoType::IT_namespace,
115-
"Namespace::ChildNamespace", "Namespace");
116-
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
117-
"Namespace::ChildStruct", "Namespace");
118-
I.Children.Functions.emplace_back();
119-
I.Children.Functions.back().Access = clang::AccessSpecifier::AS_none;
120-
I.Children.Functions.back().Name = "OneFunction";
121-
I.Children.Enums.emplace_back();
140+
I.DefLoc = Location(10, 10, "dir/test.cpp", true);
141+
I.Loc.emplace_back(12, 12, "test.cpp");
142+
143+
I.Access = AccessSpecifier::AS_none;
144+
145+
SmallString<16> PathTo;
146+
llvm::sys::path::native("path/to", PathTo);
147+
I.ReturnType = doc::TypeInfo(
148+
Reference(EmptySID, "float", InfoType::IT_default, "float", PathTo));
149+
I.Params.emplace_back(doc::TypeInfo("int", PathTo), "P");
150+
I.IsMethod = true;
151+
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
152+
153+
auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
154+
assert(!Err);
155+
std::string Expected = R"raw(IT_Function
156+
)raw";
157+
158+
// FIXME: Functions are not handled yet.
159+
EXPECT_EQ(Expected, Actual.str());
160+
#endif
161+
}
162+
163+
TEST(HTMLMustacheGeneratorTest, emitEnumHTML) {
164+
#if ENABLE_LOCAL_TEST
165+
auto G = getHTMLMustacheGenerator();
166+
assert(G && "Could not find HTMLMustacheGenerator");
167+
ClangDocContext CDCtx = getClangDocContext();
168+
std::string Buffer;
169+
llvm::raw_string_ostream Actual(Buffer);
170+
171+
unittest::TempDir RootTestDirectory("emitEnumHTML",
172+
/*Unique=*/true);
173+
CDCtx.OutDirectory = RootTestDirectory.path();
174+
175+
getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
176+
177+
// FIXME: This is a terrible hack, since we can't initialize the templates
178+
// directly. We'll need to update the interfaces so that we can call
179+
// SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
180+
EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
181+
Succeeded())
182+
<< "Failed to generate docs.";
183+
184+
CDCtx.RepositoryUrl = "http://www.repository.com";
185+
186+
EnumInfo I;
187+
I.Name = "e";
188+
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
189+
190+
I.DefLoc = Location(10, 10, "test.cpp", true);
191+
I.Loc.emplace_back(12, 12, "test.cpp");
192+
193+
I.Members.emplace_back("X");
194+
I.Scoped = true;
195+
196+
auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
197+
assert(!Err);
198+
199+
std::string Expected = R"raw(IT_enum
200+
)raw";
201+
202+
// FIXME: Enums are not handled yet.
203+
EXPECT_EQ(Expected, Actual.str());
204+
#endif
205+
}
206+
207+
TEST(HTMLMustacheGeneratorTest, emitCommentHTML) {
208+
#if ENABLE_LOCAL_TEST
209+
auto G = getHTMLMustacheGenerator();
210+
assert(G && "Could not find HTMLMustacheGenerator");
211+
ClangDocContext CDCtx = getClangDocContext();
212+
std::string Buffer;
213+
llvm::raw_string_ostream Actual(Buffer);
214+
215+
unittest::TempDir RootTestDirectory("emitCommentHTML",
216+
/*Unique=*/true);
217+
CDCtx.OutDirectory = RootTestDirectory.path();
218+
219+
getMustacheHtmlFiles(CLANG_DOC_TEST_ASSET_DIR, CDCtx);
220+
221+
// FIXME: This is a terrible hack, since we can't initialize the templates
222+
// directly. We'll need to update the interfaces so that we can call
223+
// SetupTemplateFiles() from outsize of HTMLMustacheGenerator.cpp
224+
EXPECT_THAT_ERROR(G->generateDocs(RootTestDirectory.path(), {}, CDCtx),
225+
Succeeded())
226+
<< "Failed to generate docs.";
227+
228+
CDCtx.RepositoryUrl = "http://www.repository.com";
229+
230+
FunctionInfo I;
231+
I.Name = "f";
232+
I.DefLoc = Location(10, 10, "test.cpp", true);
233+
I.ReturnType = doc::TypeInfo("void");
234+
I.Params.emplace_back(doc::TypeInfo("int"), "I");
235+
I.Params.emplace_back(doc::TypeInfo("int"), "J");
236+
I.Access = AccessSpecifier::AS_none;
237+
238+
CommentInfo Top;
239+
Top.Kind = "FullComment";
240+
241+
Top.Children.emplace_back(std::make_unique<CommentInfo>());
242+
CommentInfo *BlankLine = Top.Children.back().get();
243+
BlankLine->Kind = "ParagraphComment";
244+
BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
245+
BlankLine->Children.back()->Kind = "TextComment";
246+
247+
Top.Children.emplace_back(std::make_unique<CommentInfo>());
248+
CommentInfo *Brief = Top.Children.back().get();
249+
Brief->Kind = "ParagraphComment";
250+
Brief->Children.emplace_back(std::make_unique<CommentInfo>());
251+
Brief->Children.back()->Kind = "TextComment";
252+
Brief->Children.back()->Name = "ParagraphComment";
253+
Brief->Children.back()->Text = " Brief description.";
254+
255+
Top.Children.emplace_back(std::make_unique<CommentInfo>());
256+
CommentInfo *Extended = Top.Children.back().get();
257+
Extended->Kind = "ParagraphComment";
258+
Extended->Children.emplace_back(std::make_unique<CommentInfo>());
259+
Extended->Children.back()->Kind = "TextComment";
260+
Extended->Children.back()->Text = " Extended description that";
261+
Extended->Children.emplace_back(std::make_unique<CommentInfo>());
262+
Extended->Children.back()->Kind = "TextComment";
263+
Extended->Children.back()->Text = " continues onto the next line.";
264+
265+
Top.Children.emplace_back(std::make_unique<CommentInfo>());
266+
CommentInfo *Entities = Top.Children.back().get();
267+
Entities->Kind = "ParagraphComment";
268+
Entities->Children.emplace_back(std::make_unique<CommentInfo>());
269+
Entities->Children.back()->Kind = "TextComment";
270+
Entities->Children.back()->Name = "ParagraphComment";
271+
Entities->Children.back()->Text =
272+
" Comment with html entities: &, <, >, \", \'.";
273+
274+
I.Description.emplace_back(std::move(Top));
122275

123-
EXPECT_THAT_ERROR(G->generateDocForInfo(&I, Actual, CDCtx), Failed());
276+
auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
277+
assert(!Err);
278+
std::string Expected = R"raw(IT_Function
279+
)raw";
124280

125-
std::string Expected = R"raw()raw";
126-
EXPECT_THAT(Actual.str(), Eq(Expected));
281+
// FIXME: Functions are not handled yet.
282+
EXPECT_EQ(Expected, Actual.str());
283+
#endif
127284
}

0 commit comments

Comments
 (0)