Skip to content

Commit 7c91d2f

Browse files
evelez7vinay-deshmukh
authored andcommitted
[clang-doc] revert to a nested directory structure (llvm#166978)
Restore previous behavior of creating a nested directory structure in JSON and HTML output. Now, namespaces are all named index.json and will serve as the main page of their directory, e.g. clang/index.json is the "homepage" for the namespace clang. Some new functionality is added to replicate the directory structure from JSON to the HTML output, since the HTML output doesn't handle any Infos to create the directory structure.
1 parent de7c492 commit 7c91d2f

18 files changed

+64
-56
lines changed

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

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ namespace clang {
2929
namespace doc {
3030
static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
3131
StringRef Path, raw_fd_ostream &OS,
32-
const ClangDocContext &CDCtx);
32+
const ClangDocContext &CDCtx,
33+
StringRef HTMLRootPath);
3334

3435
static Error createFileOpenError(StringRef FileName, std::error_code EC) {
3536
return createFileError("cannot open file " + FileName, EC);
@@ -159,16 +160,24 @@ Error MustacheHTMLGenerator::generateDocs(
159160
{
160161
llvm::TimeTraceScope TS("Iterate JSON files");
161162
std::error_code EC;
162-
sys::fs::directory_iterator JSONIter(JSONPath, EC);
163+
sys::fs::recursive_directory_iterator JSONIter(JSONPath, EC);
163164
std::vector<json::Value> JSONFiles;
164165
JSONFiles.reserve(Infos.size());
165166
if (EC)
166167
return createStringError("Failed to create directory iterator.");
167168

168-
SmallString<128> HTMLDirPath(RootDir.str() + "/html/");
169+
SmallString<128> HTMLDirPath(RootDir.str() + "/html");
169170
if (auto EC = sys::fs::create_directories(HTMLDirPath))
170171
return createFileError(HTMLDirPath, EC);
171-
while (JSONIter != sys::fs::directory_iterator()) {
172+
while (JSONIter != sys::fs::recursive_directory_iterator()) {
173+
// create the same directory structure in the HTML dir
174+
if (JSONIter->type() == sys::fs::file_type::directory_file) {
175+
SmallString<128> HTMLClonedPath(JSONIter->path());
176+
sys::path::replace_path_prefix(HTMLClonedPath, JSONPath, HTMLDirPath);
177+
if (auto EC = sys::fs::create_directories(HTMLClonedPath))
178+
return createFileError(HTMLClonedPath, EC);
179+
}
180+
172181
if (EC)
173182
return createFileError("Failed to iterate: " + JSONIter->path(), EC);
174183

@@ -190,15 +199,16 @@ Error MustacheHTMLGenerator::generateDocs(
190199
return Parsed.takeError();
191200

192201
std::error_code FileErr;
193-
SmallString<128> HTMLFilePath(HTMLDirPath);
194-
sys::path::append(HTMLFilePath, sys::path::filename(Path));
202+
SmallString<128> HTMLFilePath(JSONIter->path());
203+
sys::path::replace_path_prefix(HTMLFilePath, JSONPath, HTMLDirPath);
195204
sys::path::replace_extension(HTMLFilePath, "html");
196205
raw_fd_ostream InfoOS(HTMLFilePath, FileErr, sys::fs::OF_None);
197206
if (FileErr)
198207
return createFileOpenError(Path, FileErr);
199208

200-
if (Error Err = generateDocForJSON(*Parsed, sys::path::stem(HTMLFilePath),
201-
HTMLFilePath, InfoOS, CDCtx))
209+
if (Error Err =
210+
generateDocForJSON(*Parsed, sys::path::stem(HTMLFilePath),
211+
HTMLFilePath, InfoOS, CDCtx, HTMLDirPath))
202212
return Err;
203213
JSONIter.increment(EC);
204214
}
@@ -207,16 +217,16 @@ Error MustacheHTMLGenerator::generateDocs(
207217
return Error::success();
208218
}
209219

210-
static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
220+
static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
221+
SmallString<128> RelativeHTMLPath) {
211222
V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName});
212223
json::Value StylesheetArr = Array();
213-
SmallString<128> RelativePath("./");
214-
sys::path::native(RelativePath, sys::path::Style::posix);
224+
sys::path::native(RelativeHTMLPath, sys::path::Style::posix);
215225

216226
auto *SSA = StylesheetArr.getAsArray();
217227
SSA->reserve(CDCtx.UserStylesheets.size());
218228
for (const auto &FilePath : CDCtx.UserStylesheets) {
219-
SmallString<128> StylesheetPath = RelativePath;
229+
SmallString<128> StylesheetPath = RelativeHTMLPath;
220230
sys::path::append(StylesheetPath, sys::path::Style::posix,
221231
sys::path::filename(FilePath));
222232
SSA->emplace_back(StylesheetPath);
@@ -227,7 +237,7 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
227237
auto *SCA = ScriptArr.getAsArray();
228238
SCA->reserve(CDCtx.JsScripts.size());
229239
for (auto Script : CDCtx.JsScripts) {
230-
SmallString<128> JsPath = RelativePath;
240+
SmallString<128> JsPath = RelativeHTMLPath;
231241
sys::path::append(JsPath, sys::path::Style::posix,
232242
sys::path::filename(Script));
233243
SCA->emplace_back(JsPath);
@@ -238,7 +248,8 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
238248

239249
static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
240250
StringRef Path, raw_fd_ostream &OS,
241-
const ClangDocContext &CDCtx) {
251+
const ClangDocContext &CDCtx,
252+
StringRef HTMLRootPath) {
242253
auto StrValue = (*JSON.getAsObject())["InfoType"];
243254
if (StrValue.kind() != json::Value::Kind::String)
244255
return createStringError("JSON file '%s' does not contain key: 'InfoType'.",
@@ -249,13 +260,17 @@ static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
249260
"JSON file '%s' does not contain 'InfoType' field as a string.",
250261
Filename.str().c_str());
251262

263+
SmallString<128> PathVec(Path);
264+
// Remove filename, or else the relative path will have an extra "../"
265+
sys::path::remove_filename(PathVec);
266+
auto RelativeHTMLPath = computeRelativePath(HTMLRootPath, PathVec);
252267
if (ObjTypeStr.value() == "namespace") {
253-
if (auto Err = setupTemplateValue(CDCtx, JSON))
268+
if (auto Err = setupTemplateValue(CDCtx, JSON, RelativeHTMLPath))
254269
return Err;
255270
assert(NamespaceTemplate && "NamespaceTemplate is nullptr.");
256271
NamespaceTemplate->render(JSON, OS);
257272
} else if (ObjTypeStr.value() == "record") {
258-
if (auto Err = setupTemplateValue(CDCtx, JSON))
273+
if (auto Err = setupTemplateValue(CDCtx, JSON, RelativeHTMLPath))
259274
return Err;
260275
assert(RecordTemplate && "RecordTemplate is nullptr.");
261276
RecordTemplate->render(JSON, OS);

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

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -581,22 +581,14 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) {
581581
if (I->IT == InfoType::IT_record) {
582582
auto *RecordSymbolInfo = static_cast<SymbolInfo *>(I);
583583
FileName = RecordSymbolInfo->MangledName;
584-
} else if (I->USR == GlobalNamespaceID)
584+
} else if (I->IT == InfoType::IT_namespace) {
585585
FileName = "index";
586-
else if (I->IT == InfoType::IT_namespace) {
587-
for (const auto &NS : I->Namespace) {
588-
FileName += NS.Name;
589-
FileName += "_";
590-
}
591-
FileName += I->Name;
592586
} else
593587
FileName = I->Name;
594588
sys::path::append(Path, FileName + ".json");
595589
return FileName;
596590
}
597591

598-
// FIXME: Revert back to creating nested directories for namespaces instead of
599-
// putting everything in a flat directory structure.
600592
Error JSONGenerator::generateDocs(
601593
StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos,
602594
const ClangDocContext &CDCtx) {
@@ -609,6 +601,7 @@ Error JSONGenerator::generateDocs(
609601
auto RootDirStr = RootDir.str() + "/json";
610602
StringRef JSONDir = StringRef(RootDirStr);
611603
sys::path::native(JSONDir, Path);
604+
sys::path::append(Path, Info->getRelativeFilePath(""));
612605
if (!CreatedDirs.contains(Path)) {
613606
if (std::error_code Err = sys::fs::create_directories(Path);
614607
Err != std::error_code())

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
// RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json
33

44
// RUN: clang-doc --format=mustache --output=%t/docs --executor=all-TUs %t/build/compile_commands.json
5-
// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV5Shape.html -check-prefix=HTML-SHAPE
6-
// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV10Calculator.html -check-prefix=HTML-CALC
7-
// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV9Rectangle.html -check-prefix=HTML-RECTANGLE
8-
// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV6Circle.html -check-prefix=HTML-CIRCLE
5+
// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV5Shape.html -check-prefix=HTML-SHAPE
6+
// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV10Calculator.html -check-prefix=HTML-CALC
7+
// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV9Rectangle.html -check-prefix=HTML-RECTANGLE
8+
// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV6Circle.html -check-prefix=HTML-CIRCLE
99

1010
HTML-SHAPE: <html lang="en-US">
1111
HTML-SHAPE: <head>
1212
HTML-SHAPE: <meta charset="utf-8"/>
1313
HTML-SHAPE: <title>Shape</title>
14-
HTML-SHAPE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
15-
HTML-SHAPE: <script src="./mustache-index.js"></script>
14+
HTML-SHAPE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
15+
HTML-SHAPE: <script src="../mustache-index.js"></script>
1616
HTML-SHAPE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
1717
HTML-SHAPE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
1818
HTML-SHAPE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -151,8 +151,8 @@ HTML-CALC: <html lang="en-US">
151151
HTML-CALC: <head>
152152
HTML-CALC: <meta charset="utf-8"/>
153153
HTML-CALC: <title>Calculator</title>
154-
HTML-CALC: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
155-
HTML-CALC: <script src="./mustache-index.js"></script>
154+
HTML-CALC: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
155+
HTML-CALC: <script src="../mustache-index.js"></script>
156156
HTML-CALC: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
157157
HTML-CALC: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
158158
HTML-CALC: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -440,8 +440,8 @@ HTML-RECTANGLE: <html lang="en-US">
440440
HTML-RECTANGLE: <head>
441441
HTML-RECTANGLE: <meta charset="utf-8"/>
442442
HTML-RECTANGLE: <title>Rectangle</title>
443-
HTML-RECTANGLE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
444-
HTML-RECTANGLE: <script src="./mustache-index.js"></script>
443+
HTML-RECTANGLE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
444+
HTML-RECTANGLE: <script src="../mustache-index.js"></script>
445445
HTML-RECTANGLE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
446446
HTML-RECTANGLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
447447
HTML-RECTANGLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
@@ -597,8 +597,8 @@ HTML-CIRCLE: <html lang="en-US">
597597
HTML-CIRCLE: <head>
598598
HTML-CIRCLE: <meta charset="utf-8"/>
599599
HTML-CIRCLE: <title>Circle</title>
600-
HTML-CIRCLE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
601-
HTML-CIRCLE: <script src="./mustache-index.js"></script>
600+
HTML-CIRCLE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
601+
HTML-CIRCLE: <script src="../mustache-index.js"></script>
602602
HTML-CIRCLE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
603603
HTML-CIRCLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
604604
HTML-CIRCLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>

clang-tools-extra/test/clang-doc/json/class-requires.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
44

55
template<typename T>
66
concept Addable = requires(T a, T b) {

clang-tools-extra/test/clang-doc/json/class-specialization.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json --check-prefix=BASE
4-
// RUN: FileCheck %s < %t/json/_ZTV7MyClassIiE.json --check-prefix=SPECIALIZATION
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json --check-prefix=BASE
4+
// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClassIiE.json --check-prefix=SPECIALIZATION
55

66
template<typename T> struct MyClass {};
77

clang-tools-extra/test/clang-doc/json/class-template.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
44

55
template<typename T> struct MyClass {
66
T MemberTemplate;

clang-tools-extra/test/clang-doc/json/class.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
44

55
struct Foo;
66

clang-tools-extra/test/clang-doc/json/compound-constraints.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/index.json
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
44

55
template<typename T> concept Incrementable = requires (T a) {
66
a++;

clang-tools-extra/test/clang-doc/json/concept.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/index.json
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
44

55
// Requires that T suports post and pre-incrementing.
66
template<typename T>

clang-tools-extra/test/clang-doc/json/function-requires.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: rm -rf %t && mkdir -p %t
22
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
3-
// RUN: FileCheck %s < %t/json/index.json
3+
// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
44

55
template<typename T>
66
concept Incrementable = requires(T x) {

0 commit comments

Comments
 (0)