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;