Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 31 additions & 16 deletions clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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<json::Value> 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);

Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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'.",
Expand All @@ -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);
Expand Down
11 changes: 2 additions & 9 deletions clang-tools-extra/clang-doc/JSONGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,22 +581,14 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) {
if (I->IT == InfoType::IT_record) {
auto *RecordSymbolInfo = static_cast<SymbolInfo *>(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<std::unique_ptr<doc::Info>> Infos,
const ClangDocContext &CDCtx) {
Expand All @@ -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())
Expand Down
24 changes: 12 additions & 12 deletions clang-tools-extra/test/clang-doc/basic-project.mustache.test
Original file line number Diff line number Diff line change
Expand Up @@ -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 lang="en-US">
HTML-SHAPE: <head>
HTML-SHAPE: <meta charset="utf-8"/>
HTML-SHAPE: <title>Shape</title>
HTML-SHAPE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
HTML-SHAPE: <script src="./mustache-index.js"></script>
HTML-SHAPE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
HTML-SHAPE: <script src="../mustache-index.js"></script>
HTML-SHAPE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-SHAPE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-SHAPE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
Expand Down Expand Up @@ -151,8 +151,8 @@ HTML-CALC: <html lang="en-US">
HTML-CALC: <head>
HTML-CALC: <meta charset="utf-8"/>
HTML-CALC: <title>Calculator</title>
HTML-CALC: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
HTML-CALC: <script src="./mustache-index.js"></script>
HTML-CALC: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
HTML-CALC: <script src="../mustache-index.js"></script>
HTML-CALC: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-CALC: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-CALC: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
Expand Down Expand Up @@ -440,8 +440,8 @@ HTML-RECTANGLE: <html lang="en-US">
HTML-RECTANGLE: <head>
HTML-RECTANGLE: <meta charset="utf-8"/>
HTML-RECTANGLE: <title>Rectangle</title>
HTML-RECTANGLE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
HTML-RECTANGLE: <script src="./mustache-index.js"></script>
HTML-RECTANGLE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
HTML-RECTANGLE: <script src="../mustache-index.js"></script>
HTML-RECTANGLE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-RECTANGLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-RECTANGLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
Expand Down Expand Up @@ -597,8 +597,8 @@ HTML-CIRCLE: <html lang="en-US">
HTML-CIRCLE: <head>
HTML-CIRCLE: <meta charset="utf-8"/>
HTML-CIRCLE: <title>Circle</title>
HTML-CIRCLE: <link rel="stylesheet" type="text/css" href="./clang-doc-mustache.css"/>
HTML-CIRCLE: <script src="./mustache-index.js"></script>
HTML-CIRCLE: <link rel="stylesheet" type="text/css" href="../clang-doc-mustache.css"/>
HTML-CIRCLE: <script src="../mustache-index.js"></script>
HTML-CIRCLE: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
HTML-CIRCLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
HTML-CIRCLE: <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/cpp.min.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/json/class-requires.cpp
Original file line number Diff line number Diff line change
@@ -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<typename T>
concept Addable = requires(T a, T b) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<typename T> struct MyClass {};

Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/json/class-template.cpp
Original file line number Diff line number Diff line change
@@ -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<typename T> struct MyClass {
T MemberTemplate;
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/json/class.cpp
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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<typename T> concept Incrementable = requires (T a) {
a++;
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/json/concept.cpp
Original file line number Diff line number Diff line change
@@ -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<typename T>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<typename T>
concept Incrementable = requires(T x) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {}

Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/json/method-template.cpp
Original file line number Diff line number Diff line change
@@ -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<class T> T methodTemplate(T param) {
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/test/clang-doc/json/multiple-namespaces.cpp
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/json/namespace.cpp
Original file line number Diff line number Diff line change
@@ -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 {};

Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/test/clang-doc/json/nested-namespace.cpp
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/test/clang-doc/long-name.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};

Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/test/clang-doc/mustache-index.cpp
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Loading