Skip to content

Commit f14ad74

Browse files
authored
Reapply [clang-doc] Add --asset option to clang-doc (#96358)
Reapply #94717 Adds a new option --asset which allows users to specified the asset folder for the html output of clang-doc. This patch adds a better test for --asset option + fixes bug where clang-doc assumes that user supplied js file is assume to be index.js
1 parent 868b90d commit f14ad74

File tree

9 files changed

+133
-37
lines changed

9 files changed

+133
-37
lines changed

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,18 @@ genStylesheetsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) {
289289
static std::vector<std::unique_ptr<TagNode>>
290290
genJsScriptsHTML(StringRef InfoPath, const ClangDocContext &CDCtx) {
291291
std::vector<std::unique_ptr<TagNode>> Out;
292+
293+
// index_json.js is part of every generated HTML file
294+
SmallString<128> IndexJSONPath = computeRelativePath("", InfoPath);
295+
auto IndexJSONNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT);
296+
llvm::sys::path::append(IndexJSONPath, "index_json.js");
297+
llvm::sys::path::native(IndexJSONPath, llvm::sys::path::Style::posix);
298+
IndexJSONNode->Attributes.emplace_back("src", std::string(IndexJSONPath));
299+
Out.emplace_back(std::move(IndexJSONNode));
300+
292301
for (const auto &FilePath : CDCtx.JsScripts) {
293-
auto ScriptNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT);
294302
SmallString<128> ScriptPath = computeRelativePath("", InfoPath);
303+
auto ScriptNode = std::make_unique<TagNode>(HTMLTag::TAG_SCRIPT);
295304
llvm::sys::path::append(ScriptPath, llvm::sys::path::filename(FilePath));
296305
// Paths in HTML must be in posix-style
297306
llvm::sys::path::native(ScriptPath, llvm::sys::path::Style::posix);
@@ -1069,7 +1078,7 @@ llvm::Error HTMLGenerator::createResources(ClangDocContext &CDCtx) {
10691078
if (Err)
10701079
return Err;
10711080
}
1072-
for (const auto &FilePath : CDCtx.FilesToCopy) {
1081+
for (const auto &FilePath : CDCtx.JsScripts) {
10731082
Err = CopyFile(FilePath, CDCtx.OutDirectory);
10741083
if (Err)
10751084
return Err;

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,11 +368,9 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
368368
StringRef ProjectName, bool PublicOnly,
369369
StringRef OutDirectory, StringRef SourceRoot,
370370
StringRef RepositoryUrl,
371-
std::vector<std::string> UserStylesheets,
372-
std::vector<std::string> JsScripts)
371+
std::vector<std::string> UserStylesheets)
373372
: ECtx(ECtx), ProjectName(ProjectName), PublicOnly(PublicOnly),
374-
OutDirectory(OutDirectory), UserStylesheets(UserStylesheets),
375-
JsScripts(JsScripts) {
373+
OutDirectory(OutDirectory), UserStylesheets(UserStylesheets) {
376374
llvm::SmallString<128> SourceRootDir(SourceRoot);
377375
if (SourceRoot.empty())
378376
// If no SourceRoot was provided the current path is used as the default

clang-tools-extra/clang-doc/Representation.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,7 @@ struct ClangDocContext {
482482
ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
483483
bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
484484
StringRef RepositoryUrl,
485-
std::vector<std::string> UserStylesheets,
486-
std::vector<std::string> JsScripts);
485+
std::vector<std::string> UserStylesheets);
487486
tooling::ExecutionContext *ECtx;
488487
std::string ProjectName; // Name of project clang-doc is documenting.
489488
bool PublicOnly; // Indicates if only public declarations are documented.
@@ -498,8 +497,6 @@ struct ClangDocContext {
498497
std::vector<std::string> UserStylesheets;
499498
// JavaScript files that will be imported in allHTML file.
500499
std::vector<std::string> JsScripts;
501-
// Other files that should be copied to OutDirectory, besides UserStylesheets.
502-
std::vector<std::string> FilesToCopy;
503500
Index Idx;
504501
};
505502

clang-tools-extra/clang-doc/tool/ClangDocMain.cpp

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ static llvm::cl::list<std::string> UserStylesheets(
8181
llvm::cl::desc("CSS stylesheets to extend the default styles."),
8282
llvm::cl::cat(ClangDocCategory));
8383

84+
static llvm::cl::opt<std::string> UserAssetPath(
85+
"asset",
86+
llvm::cl::desc("User supplied asset path to "
87+
"override the default css and js files for html output"),
88+
llvm::cl::cat(ClangDocCategory));
89+
8490
static llvm::cl::opt<std::string> SourceRoot("source-root", llvm::cl::desc(R"(
8591
Directory where processed files are stored.
8692
Links to definition locations will only be
@@ -127,16 +133,84 @@ std::string getFormatString() {
127133
// GetMainExecutable (since some platforms don't support taking the
128134
// address of main, and some platforms can't implement GetMainExecutable
129135
// without being given the address of a function in the main executable).
130-
std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
136+
std::string getExecutablePath(const char *Argv0, void *MainAddr) {
131137
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
132138
}
133139

140+
llvm::Error getAssetFiles(clang::doc::ClangDocContext &CDCtx) {
141+
using DirIt = llvm::sys::fs::directory_iterator;
142+
std::error_code FileErr;
143+
llvm::SmallString<128> FilePath(UserAssetPath);
144+
for (DirIt DirStart = DirIt(UserAssetPath, FileErr),
145+
DirEnd;
146+
!FileErr && DirStart != DirEnd; DirStart.increment(FileErr)) {
147+
FilePath = DirStart->path();
148+
if (llvm::sys::fs::is_regular_file(FilePath)) {
149+
if (llvm::sys::path::extension(FilePath) == ".css")
150+
CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
151+
std::string(FilePath));
152+
else if (llvm::sys::path::extension(FilePath) == ".js")
153+
CDCtx.JsScripts.emplace_back(FilePath.str());
154+
}
155+
}
156+
if (FileErr)
157+
return llvm::createFileError(FilePath, FileErr);
158+
return llvm::Error::success();
159+
}
160+
161+
llvm::Error getDefaultAssetFiles(const char *Argv0,
162+
clang::doc::ClangDocContext &CDCtx) {
163+
void *MainAddr = (void *)(intptr_t)getExecutablePath;
164+
std::string ClangDocPath = getExecutablePath(Argv0, MainAddr);
165+
llvm::SmallString<128> NativeClangDocPath;
166+
llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
167+
168+
llvm::SmallString<128> AssetsPath;
169+
AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
170+
llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc");
171+
llvm::SmallString<128> DefaultStylesheet;
172+
llvm::sys::path::native(AssetsPath, DefaultStylesheet);
173+
llvm::sys::path::append(DefaultStylesheet,
174+
"clang-doc-default-stylesheet.css");
175+
llvm::SmallString<128> IndexJS;
176+
llvm::sys::path::native(AssetsPath, IndexJS);
177+
llvm::sys::path::append(IndexJS, "index.js");
178+
179+
if (!llvm::sys::fs::is_regular_file(IndexJS))
180+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
181+
"default index.js file missing at " +
182+
IndexJS + "\n");
183+
184+
if (!llvm::sys::fs::is_regular_file(DefaultStylesheet))
185+
return llvm::createStringError(
186+
llvm::inconvertibleErrorCode(),
187+
"default clang-doc-default-stylesheet.css file missing at " +
188+
DefaultStylesheet + "\n");
189+
190+
CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
191+
std::string(DefaultStylesheet));
192+
CDCtx.JsScripts.emplace_back(IndexJS.str());
193+
194+
return llvm::Error::success();
195+
}
196+
197+
llvm::Error getHtmlAssetFiles(const char *Argv0,
198+
clang::doc::ClangDocContext &CDCtx) {
199+
if (!UserAssetPath.empty() &&
200+
!llvm::sys::fs::is_directory(std::string(UserAssetPath)))
201+
llvm::outs() << "Asset path supply is not a directory: " << UserAssetPath
202+
<< " falling back to default\n";
203+
if (llvm::sys::fs::is_directory(std::string(UserAssetPath)))
204+
return getAssetFiles(CDCtx);
205+
return getDefaultAssetFiles(Argv0, CDCtx);
206+
}
207+
134208
int main(int argc, const char **argv) {
135209
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
136210
std::error_code OK;
137211

138212
const char *Overview =
139-
R"(Generates documentation from source code and comments.
213+
R"(Generates documentation from source code and comments.
140214
141215
Example usage for files without flags (default):
142216
@@ -178,27 +252,14 @@ Example usage for a project using a compile commands database:
178252
OutDirectory,
179253
SourceRoot,
180254
RepositoryUrl,
181-
{UserStylesheets.begin(), UserStylesheets.end()},
182-
{"index.js", "index_json.js"}};
255+
{UserStylesheets.begin(), UserStylesheets.end()}
256+
};
183257

184258
if (Format == "html") {
185-
void *MainAddr = (void *)(intptr_t)GetExecutablePath;
186-
std::string ClangDocPath = GetExecutablePath(argv[0], MainAddr);
187-
llvm::SmallString<128> NativeClangDocPath;
188-
llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
189-
llvm::SmallString<128> AssetsPath;
190-
AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
191-
llvm::sys::path::append(AssetsPath, "..", "share", "clang-doc");
192-
llvm::SmallString<128> DefaultStylesheet;
193-
llvm::sys::path::native(AssetsPath, DefaultStylesheet);
194-
llvm::sys::path::append(DefaultStylesheet,
195-
"clang-doc-default-stylesheet.css");
196-
llvm::SmallString<128> IndexJS;
197-
llvm::sys::path::native(AssetsPath, IndexJS);
198-
llvm::sys::path::append(IndexJS, "index.js");
199-
CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
200-
std::string(DefaultStylesheet));
201-
CDCtx.FilesToCopy.emplace_back(IndexJS.str());
259+
if (auto Err = getHtmlAssetFiles(argv[0], CDCtx)) {
260+
llvm::errs() << toString(std::move(Err)) << "\n";
261+
return 1;
262+
}
202263
}
203264

204265
// Mapping phase
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
body {
2+
padding: 0;
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("Hello, world!");
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
// RUN: clang-doc --format=html --output=%t --asset=%S/Inputs/test-assets --executor=standalone %s
3+
// RUN: FileCheck %s -input-file=%t/index.html -check-prefix=INDEX
4+
// RUN: FileCheck %s -input-file=%t/test.css -check-prefix=CSS
5+
// RUN: FileCheck %s -input-file=%t/test.js -check-prefix=JS
6+
7+
// INDEX: <!DOCTYPE html>
8+
// INDEX-NEXT: <meta charset="utf-8"/>
9+
// INDEX-NEXT: <title>Index</title>
10+
// INDEX-NEXT: <link rel="stylesheet" href="test.css"/>
11+
// INDEX-NEXT: <script src="index_json.js"></script>
12+
// INDEX-NEXT: <script src="test.js"></script>
13+
// INDEX-NEXT: <header id="project-title"></header>
14+
// INDEX-NEXT: <main>
15+
// INDEX-NEXT: <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left" style="flex: 0 100%;"></div>
16+
// INDEX-NEXT: </main>
17+
18+
// CSS: body {
19+
// CSS-NEXT: padding: 0;
20+
// CSS-NEXT: }
21+
22+
// JS: console.log("Hello, world!");

clang-tools-extra/test/clang-doc/basic-project.test

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
// HTML-SHAPE-NEXT: <meta charset="utf-8"/>
5858
// HTML-SHAPE-NEXT: <title>class Shape</title>
5959
// HTML-SHAPE-NEXT: <link rel="stylesheet" href="../clang-doc-default-stylesheet.css"/>
60-
// HTML-SHAPE-NEXT: <script src="../index.js"></script>
61-
// HTML-SHAPE-NEXT: <script src="../index_json.js"></script>
60+
// HTML-SHAPE-NEXT: <script src="{{.*}}index_json.js"></script>
61+
// HTML-SHAPE-NEXT: <script src="{{.*}}index.js"></script>
6262
// HTML-SHAPE-NEXT: <header id="project-title"></header>
6363
// HTML-SHAPE-NEXT: <main>
6464
// HTML-SHAPE-NEXT: <div id="sidebar-left" path="GlobalNamespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
@@ -122,8 +122,8 @@
122122
// HTML-CALC-NEXT: <meta charset="utf-8"/>
123123
// HTML-CALC-NEXT: <title>class Calculator</title>
124124
// HTML-CALC-NEXT: <link rel="stylesheet" href="{{.*}}clang-doc-default-stylesheet.css"/>
125-
// HTML-CALC-NEXT: <script src="{{.*}}index.js"></script>
126125
// HTML-CALC-NEXT: <script src="{{.*}}index_json.js"></script>
126+
// HTML-CALC-NEXT: <script src="{{.*}}index.js"></script>
127127
// HTML-CALC-NEXT: <header id="project-title"></header>
128128
// HTML-CALC-NEXT: <main>
129129
// HTML-CALC-NEXT: <div id="sidebar-left" path="GlobalNamespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
@@ -200,8 +200,8 @@
200200
// HTML-RECTANGLE-NEXT: <meta charset="utf-8"/>
201201
// HTML-RECTANGLE-NEXT: <title>class Rectangle</title>
202202
// HTML-RECTANGLE-NEXT: <link rel="stylesheet" href="{{.*}}clang-doc-default-stylesheet.css"/>
203-
// HTML-RECTANGLE-NEXT: <script src="{{.*}}index.js"></script>
204203
// HTML-RECTANGLE-NEXT: <script src="{{.*}}index_json.js"></script>
204+
// HTML-RECTANGLE-NEXT: <script src="{{.*}}index.js"></script>
205205
// HTML-RECTANGLE-NEXT: <header id="project-title"></header>
206206
// HTML-RECTANGLE-NEXT: <main>
207207
// HTML-RECTANGLE-NEXT: <div id="sidebar-left" path="GlobalNamespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
@@ -281,8 +281,8 @@
281281
// HTML-CIRCLE-NEXT: <meta charset="utf-8"/>
282282
// HTML-CIRCLE-NEXT: <title>class Circle</title>
283283
// HTML-CIRCLE-NEXT: <link rel="stylesheet" href="{{.*}}clang-doc-default-stylesheet.css"/>
284-
// HTML-CIRCLE-NEXT: <script src="{{.*}}index.js"></script>
285284
// HTML-CIRCLE-NEXT: <script src="{{.*}}index_json.js"></script>
285+
// HTML-CIRCLE-NEXT: <script src="{{.*}}index.js"></script>
286286
// HTML-CIRCLE-NEXT: <header id="project-title"></header>
287287
// HTML-CIRCLE-NEXT: <main>
288288
// HTML-CIRCLE-NEXT: <div id="sidebar-left" path="GlobalNamespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ ClangDocContext
3030
getClangDocContext(std::vector<std::string> UserStylesheets = {},
3131
StringRef RepositoryUrl = "") {
3232
ClangDocContext CDCtx{
33-
{}, "test-project", {}, {}, {}, RepositoryUrl, UserStylesheets, {}};
33+
{}, "test-project", {}, {}, {}, RepositoryUrl, UserStylesheets};
3434
CDCtx.UserStylesheets.insert(
3535
CDCtx.UserStylesheets.begin(),
3636
"../share/clang/clang-doc-default-stylesheet.css");
@@ -66,6 +66,7 @@ TEST(HTMLGeneratorTest, emitNamespaceHTML) {
6666
<title>namespace Namespace</title>
6767
<link rel="stylesheet" href="../clang-doc-default-stylesheet.css"/>
6868
<link rel="stylesheet" href="../user-provided-stylesheet.css"/>
69+
<script src="../index_json.js"></script>
6970
<script src="../index.js"></script>
7071
<header id="project-title">test-project</header>
7172
<main>
@@ -176,6 +177,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML) {
176177
<meta charset="utf-8"/>
177178
<title>class r</title>
178179
<link rel="stylesheet" href="../../../clang-doc-default-stylesheet.css"/>
180+
<script src="../../../index_json.js"></script>
179181
<script src="../../../index.js"></script>
180182
<header id="project-title">test-project</header>
181183
<main>
@@ -290,6 +292,7 @@ TEST(HTMLGeneratorTest, emitFunctionHTML) {
290292
<meta charset="utf-8"/>
291293
<title></title>
292294
<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
295+
<script src="index_json.js"></script>
293296
<script src="index.js"></script>
294297
<header id="project-title">test-project</header>
295298
<main>
@@ -337,6 +340,7 @@ TEST(HTMLGeneratorTest, emitEnumHTML) {
337340
<meta charset="utf-8"/>
338341
<title></title>
339342
<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
343+
<script src="index_json.js"></script>
340344
<script src="index.js"></script>
341345
<header id="project-title">test-project</header>
342346
<main>
@@ -422,6 +426,7 @@ TEST(HTMLGeneratorTest, emitCommentHTML) {
422426
<meta charset="utf-8"/>
423427
<title></title>
424428
<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
429+
<script src="index_json.js"></script>
425430
<script src="index.js"></script>
426431
<header id="project-title">test-project</header>
427432
<main>

0 commit comments

Comments
 (0)