diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index b4b9322b0500a..3650f66ec39bd 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -29,7 +29,8 @@ namespace clang {
namespace doc {
static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
StringRef Path, raw_fd_ostream &OS,
- const ClangDocContext &CDCtx);
+ const ClangDocContext &CDCtx,
+ StringRef HTMLRootPath);
static Error createFileOpenError(StringRef FileName, std::error_code EC) {
return createFileError("cannot open file " + FileName, EC);
@@ -159,16 +160,24 @@ Error MustacheHTMLGenerator::generateDocs(
{
llvm::TimeTraceScope TS("Iterate JSON files");
std::error_code EC;
- sys::fs::directory_iterator JSONIter(JSONPath, EC);
+ sys::fs::recursive_directory_iterator JSONIter(JSONPath, EC);
std::vector JSONFiles;
JSONFiles.reserve(Infos.size());
if (EC)
return createStringError("Failed to create directory iterator.");
- SmallString<128> HTMLDirPath(RootDir.str() + "/html/");
+ SmallString<128> HTMLDirPath(RootDir.str() + "/html");
if (auto EC = sys::fs::create_directories(HTMLDirPath))
return createFileError(HTMLDirPath, EC);
- while (JSONIter != sys::fs::directory_iterator()) {
+ while (JSONIter != sys::fs::recursive_directory_iterator()) {
+ // create the same directory structure in the HTML dir
+ if (JSONIter->type() == sys::fs::file_type::directory_file) {
+ SmallString<128> HTMLClonedPath(JSONIter->path());
+ sys::path::replace_path_prefix(HTMLClonedPath, JSONPath, HTMLDirPath);
+ if (auto EC = sys::fs::create_directories(HTMLClonedPath))
+ return createFileError(HTMLClonedPath, EC);
+ }
+
if (EC)
return createFileError("Failed to iterate: " + JSONIter->path(), EC);
@@ -190,15 +199,16 @@ Error MustacheHTMLGenerator::generateDocs(
return Parsed.takeError();
std::error_code FileErr;
- SmallString<128> HTMLFilePath(HTMLDirPath);
- sys::path::append(HTMLFilePath, sys::path::filename(Path));
+ SmallString<128> HTMLFilePath(JSONIter->path());
+ sys::path::replace_path_prefix(HTMLFilePath, JSONPath, HTMLDirPath);
sys::path::replace_extension(HTMLFilePath, "html");
raw_fd_ostream InfoOS(HTMLFilePath, FileErr, sys::fs::OF_None);
if (FileErr)
return createFileOpenError(Path, FileErr);
- if (Error Err = generateDocForJSON(*Parsed, sys::path::stem(HTMLFilePath),
- HTMLFilePath, InfoOS, CDCtx))
+ if (Error Err =
+ generateDocForJSON(*Parsed, sys::path::stem(HTMLFilePath),
+ HTMLFilePath, InfoOS, CDCtx, HTMLDirPath))
return Err;
JSONIter.increment(EC);
}
@@ -207,16 +217,16 @@ Error MustacheHTMLGenerator::generateDocs(
return Error::success();
}
-static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
+static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V,
+ SmallString<128> RelativeHTMLPath) {
V.getAsObject()->insert({"ProjectName", CDCtx.ProjectName});
json::Value StylesheetArr = Array();
- SmallString<128> RelativePath("./");
- sys::path::native(RelativePath, sys::path::Style::posix);
+ sys::path::native(RelativeHTMLPath, sys::path::Style::posix);
auto *SSA = StylesheetArr.getAsArray();
SSA->reserve(CDCtx.UserStylesheets.size());
for (const auto &FilePath : CDCtx.UserStylesheets) {
- SmallString<128> StylesheetPath = RelativePath;
+ SmallString<128> StylesheetPath = RelativeHTMLPath;
sys::path::append(StylesheetPath, sys::path::Style::posix,
sys::path::filename(FilePath));
SSA->emplace_back(StylesheetPath);
@@ -227,7 +237,7 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
auto *SCA = ScriptArr.getAsArray();
SCA->reserve(CDCtx.JsScripts.size());
for (auto Script : CDCtx.JsScripts) {
- SmallString<128> JsPath = RelativePath;
+ SmallString<128> JsPath = RelativeHTMLPath;
sys::path::append(JsPath, sys::path::Style::posix,
sys::path::filename(Script));
SCA->emplace_back(JsPath);
@@ -238,7 +248,8 @@ static Error setupTemplateValue(const ClangDocContext &CDCtx, json::Value &V) {
static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
StringRef Path, raw_fd_ostream &OS,
- const ClangDocContext &CDCtx) {
+ const ClangDocContext &CDCtx,
+ StringRef HTMLRootPath) {
auto StrValue = (*JSON.getAsObject())["InfoType"];
if (StrValue.kind() != json::Value::Kind::String)
return createStringError("JSON file '%s' does not contain key: 'InfoType'.",
@@ -249,13 +260,17 @@ static Error generateDocForJSON(json::Value &JSON, StringRef Filename,
"JSON file '%s' does not contain 'InfoType' field as a string.",
Filename.str().c_str());
+ SmallString<128> PathVec(Path);
+ // Remove filename, or else the relative path will have an extra "../"
+ sys::path::remove_filename(PathVec);
+ auto RelativeHTMLPath = computeRelativePath(HTMLRootPath, PathVec);
if (ObjTypeStr.value() == "namespace") {
- if (auto Err = setupTemplateValue(CDCtx, JSON))
+ if (auto Err = setupTemplateValue(CDCtx, JSON, RelativeHTMLPath))
return Err;
assert(NamespaceTemplate && "NamespaceTemplate is nullptr.");
NamespaceTemplate->render(JSON, OS);
} else if (ObjTypeStr.value() == "record") {
- if (auto Err = setupTemplateValue(CDCtx, JSON))
+ if (auto Err = setupTemplateValue(CDCtx, JSON, RelativeHTMLPath))
return Err;
assert(RecordTemplate && "RecordTemplate is nullptr.");
RecordTemplate->render(JSON, OS);
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index 93ec90e9048ea..9a770d7939a4b 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -581,22 +581,14 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) {
if (I->IT == InfoType::IT_record) {
auto *RecordSymbolInfo = static_cast(I);
FileName = RecordSymbolInfo->MangledName;
- } else if (I->USR == GlobalNamespaceID)
+ } else if (I->IT == InfoType::IT_namespace) {
FileName = "index";
- else if (I->IT == InfoType::IT_namespace) {
- for (const auto &NS : I->Namespace) {
- FileName += NS.Name;
- FileName += "_";
- }
- FileName += I->Name;
} else
FileName = I->Name;
sys::path::append(Path, FileName + ".json");
return FileName;
}
-// FIXME: Revert back to creating nested directories for namespaces instead of
-// putting everything in a flat directory structure.
Error JSONGenerator::generateDocs(
StringRef RootDir, llvm::StringMap> Infos,
const ClangDocContext &CDCtx) {
@@ -609,6 +601,7 @@ Error JSONGenerator::generateDocs(
auto RootDirStr = RootDir.str() + "/json";
StringRef JSONDir = StringRef(RootDirStr);
sys::path::native(JSONDir, Path);
+ sys::path::append(Path, Info->getRelativeFilePath(""));
if (!CreatedDirs.contains(Path)) {
if (std::error_code Err = sys::fs::create_directories(Path);
Err != std::error_code())
diff --git a/clang-tools-extra/test/clang-doc/basic-project.mustache.test b/clang-tools-extra/test/clang-doc/basic-project.mustache.test
index 55099517101f2..5a40a6b7c9799 100644
--- a/clang-tools-extra/test/clang-doc/basic-project.mustache.test
+++ b/clang-tools-extra/test/clang-doc/basic-project.mustache.test
@@ -2,17 +2,17 @@
// RUN: sed 's|$test_dir|%/S|g' %S/Inputs/basic-project/database_template.json > %t/build/compile_commands.json
// RUN: clang-doc --format=mustache --output=%t/docs --executor=all-TUs %t/build/compile_commands.json
-// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV5Shape.html -check-prefix=HTML-SHAPE
-// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV10Calculator.html -check-prefix=HTML-CALC
-// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV9Rectangle.html -check-prefix=HTML-RECTANGLE
-// RUN: FileCheck %s -input-file=%t/docs/html/_ZTV6Circle.html -check-prefix=HTML-CIRCLE
+// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV5Shape.html -check-prefix=HTML-SHAPE
+// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV10Calculator.html -check-prefix=HTML-CALC
+// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV9Rectangle.html -check-prefix=HTML-RECTANGLE
+// RUN: FileCheck %s -input-file=%t/docs/html/GlobalNamespace/_ZTV6Circle.html -check-prefix=HTML-CIRCLE
HTML-SHAPE:
HTML-SHAPE:
HTML-SHAPE:
HTML-SHAPE: Shape
-HTML-SHAPE:
-HTML-SHAPE:
+HTML-SHAPE:
+HTML-SHAPE:
HTML-SHAPE:
HTML-SHAPE:
HTML-SHAPE:
@@ -151,8 +151,8 @@ HTML-CALC:
HTML-CALC:
HTML-CALC:
HTML-CALC: Calculator
-HTML-CALC:
-HTML-CALC:
+HTML-CALC:
+HTML-CALC:
HTML-CALC:
HTML-CALC:
HTML-CALC:
@@ -440,8 +440,8 @@ HTML-RECTANGLE:
HTML-RECTANGLE:
HTML-RECTANGLE:
HTML-RECTANGLE: Rectangle
-HTML-RECTANGLE:
-HTML-RECTANGLE:
+HTML-RECTANGLE:
+HTML-RECTANGLE:
HTML-RECTANGLE:
HTML-RECTANGLE:
HTML-RECTANGLE:
@@ -597,8 +597,8 @@ HTML-CIRCLE:
HTML-CIRCLE:
HTML-CIRCLE:
HTML-CIRCLE: Circle
-HTML-CIRCLE:
-HTML-CIRCLE:
+HTML-CIRCLE:
+HTML-CIRCLE:
HTML-CIRCLE:
HTML-CIRCLE:
HTML-CIRCLE:
diff --git a/clang-tools-extra/test/clang-doc/json/class-requires.cpp b/clang-tools-extra/test/clang-doc/json/class-requires.cpp
index 513961723990e..4e5ec3a5729cd 100644
--- a/clang-tools-extra/test/clang-doc/json/class-requires.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-requires.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
template
concept Addable = requires(T a, T b) {
diff --git a/clang-tools-extra/test/clang-doc/json/class-specialization.cpp b/clang-tools-extra/test/clang-doc/json/class-specialization.cpp
index d3ad6957e7851..60f3b44eb69b0 100644
--- a/clang-tools-extra/test/clang-doc/json/class-specialization.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-specialization.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json --check-prefix=BASE
-// RUN: FileCheck %s < %t/json/_ZTV7MyClassIiE.json --check-prefix=SPECIALIZATION
+// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json --check-prefix=BASE
+// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClassIiE.json --check-prefix=SPECIALIZATION
template struct MyClass {};
diff --git a/clang-tools-extra/test/clang-doc/json/class-template.cpp b/clang-tools-extra/test/clang-doc/json/class-template.cpp
index 5ef78f54854dd..de52064466140 100644
--- a/clang-tools-extra/test/clang-doc/json/class-template.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-template.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
template struct MyClass {
T MemberTemplate;
diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp
index adb1ed7511c3b..91160585bef1a 100644
--- a/clang-tools-extra/test/clang-doc/json/class.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
struct Foo;
diff --git a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
index 1a73a0ddb722f..5b15a88d562de 100644
--- a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
+++ b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/index.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
template concept Incrementable = requires (T a) {
a++;
diff --git a/clang-tools-extra/test/clang-doc/json/concept.cpp b/clang-tools-extra/test/clang-doc/json/concept.cpp
index e96ec14d7dde4..5d8c47eff0a16 100644
--- a/clang-tools-extra/test/clang-doc/json/concept.cpp
+++ b/clang-tools-extra/test/clang-doc/json/concept.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/index.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
// Requires that T suports post and pre-incrementing.
template
diff --git a/clang-tools-extra/test/clang-doc/json/function-requires.cpp b/clang-tools-extra/test/clang-doc/json/function-requires.cpp
index 94271467cba63..8ba6adc66a54b 100644
--- a/clang-tools-extra/test/clang-doc/json/function-requires.cpp
+++ b/clang-tools-extra/test/clang-doc/json/function-requires.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --extra-arg -std=c++20 --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/index.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
template
concept Incrementable = requires(T x) {
diff --git a/clang-tools-extra/test/clang-doc/json/function-specifiers.cpp b/clang-tools-extra/test/clang-doc/json/function-specifiers.cpp
index faaccb7d4f63f..6630d9e873dcf 100644
--- a/clang-tools-extra/test/clang-doc/json/function-specifiers.cpp
+++ b/clang-tools-extra/test/clang-doc/json/function-specifiers.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/index.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
static void myFunction() {}
diff --git a/clang-tools-extra/test/clang-doc/json/method-template.cpp b/clang-tools-extra/test/clang-doc/json/method-template.cpp
index 87977f891a223..f4885d956ad9b 100644
--- a/clang-tools-extra/test/clang-doc/json/method-template.cpp
+++ b/clang-tools-extra/test/clang-doc/json/method-template.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/_ZTV7MyClass.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/_ZTV7MyClass.json
struct MyClass {
template T methodTemplate(T param) {
diff --git a/clang-tools-extra/test/clang-doc/json/multiple-namespaces.cpp b/clang-tools-extra/test/clang-doc/json/multiple-namespaces.cpp
index 04fcfc1dc0a85..69269989e03d4 100644
--- a/clang-tools-extra/test/clang-doc/json/multiple-namespaces.cpp
+++ b/clang-tools-extra/test/clang-doc/json/multiple-namespaces.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/foo_tools.json --check-prefix=CHECK-FOO
-// RUN: FileCheck %s < %t/json/bar_tools.json --check-prefix=CHECK-BAR
+// RUN: FileCheck %s < %t/json/foo/tools/index.json --check-prefix=CHECK-FOO
+// RUN: FileCheck %s < %t/json/bar/tools/index.json --check-prefix=CHECK-BAR
namespace foo {
namespace tools {
diff --git a/clang-tools-extra/test/clang-doc/json/namespace.cpp b/clang-tools-extra/test/clang-doc/json/namespace.cpp
index dcf83236bae28..dd7a9af9c82a0 100644
--- a/clang-tools-extra/test/clang-doc/json/namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/json/namespace.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/index.json
+// RUN: FileCheck %s < %t/json/GlobalNamespace/index.json
class MyClass {};
diff --git a/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp b/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
index cf19e1e34a818..5baca7f39b783 100644
--- a/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
-// RUN: FileCheck %s < %t/json/nested.json --check-prefix=NESTED
-// RUN: FileCheck %s < %t/json/nested_inner.json --check-prefix=INNER
+// RUN: FileCheck %s < %t/json/nested/index.json --check-prefix=NESTED
+// RUN: FileCheck %s < %t/json/nested/inner/index.json --check-prefix=INNER
namespace nested {
int Global;
diff --git a/clang-tools-extra/test/clang-doc/long-name.cpp b/clang-tools-extra/test/clang-doc/long-name.cpp
index e29c468ecc4da..77e50b1553ad5 100644
--- a/clang-tools-extra/test/clang-doc/long-name.cpp
+++ b/clang-tools-extra/test/clang-doc/long-name.cpp
@@ -2,8 +2,8 @@
// UNSUPPORTED: system-windows
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --output=%t --format=mustache --executor=standalone %s
-// RUN: ls %t/json | FileCheck %s -check-prefix=CHECK-JSON
-// RUN: ls %t/html | FileCheck %s -check-prefix=CHECK-HTML
+// RUN: ls %t/json/GlobalNamespace | FileCheck %s -check-prefix=CHECK-JSON
+// RUN: ls %t/html/GlobalNamespace | FileCheck %s -check-prefix=CHECK-HTML
struct ThisStructHasANameThatResultsInAMangledNameThatIsExactly250CharactersLongThatIsSupposedToTestTheFilenameLengthLimitsWithinClangDocInOrdertoSeeifclangdocwillcrashornotdependingonthelengthofthestructIfTheLengthIsTooLongThenClangDocWillCrashAnd12 {};
diff --git a/clang-tools-extra/test/clang-doc/mustache-index.cpp b/clang-tools-extra/test/clang-doc/mustache-index.cpp
index 5317b639bc500..7b98c6b7c9880 100644
--- a/clang-tools-extra/test/clang-doc/mustache-index.cpp
+++ b/clang-tools-extra/test/clang-doc/mustache-index.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --format=mustache --output=%t --executor=standalone %s
-// RUN: FileCheck %s < %t/html/index.html
+// RUN: FileCheck %s < %t/html/GlobalNamespace/index.html
enum Color {
RED,
diff --git a/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp b/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp
index 880562d0deebd..ee8b844d1f7f1 100644
--- a/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp
+++ b/clang-tools-extra/test/clang-doc/mustache-separate-namespace.cpp
@@ -1,6 +1,6 @@
// RUN: rm -rf %t && mkdir -p %t
// RUN: clang-doc --format=mustache --output=%t --executor=standalone %s
-// RUN: FileCheck %s < %t/html/MyNamespace.html
+// RUN: FileCheck %s < %t/html/MyNamespace/index.html
namespace MyNamespace {
class Foo;