Skip to content

Commit 72da18f

Browse files
ilovepiPeterChou1
andcommitted
[clang-doc] Implement setupTemplateValue for HTMLMustacheGenerator
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. The tests here are disabled by default until we can use lit tests via tool support, since we cannot read files in the unit tests. Co-authored-by: Peter Chou <[email protected]>
1 parent a8be7a7 commit 72da18f

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)