This revision was automatically updated to reflect the committed changes. Closed by commit rG7003f64c1eb2: [clang-doc] Improving Markdown Output (authored by phosek).
Changed prior to commit: https://reviews.llvm.org/D72954?vs=248338&id=248875#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D72954/new/ https://reviews.llvm.org/D72954 Files: clang-tools-extra/clang-doc/HTMLGenerator.cpp clang-tools-extra/clang-doc/MDGenerator.cpp clang-tools-extra/clang-doc/Representation.cpp clang-tools-extra/clang-doc/Representation.h clang-tools-extra/clang-doc/assets/index.js clang-tools-extra/clang-doc/tool/ClangDocMain.cpp clang-tools-extra/test/clang-doc/single-file.cpp clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp
Index: clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp =================================================================== --- clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp +++ clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp @@ -47,14 +47,12 @@ ## Namespaces -ChildNamespace - +* [ChildNamespace](../ChildNamespace/index.md) ## Records -ChildStruct - +* [ChildStruct](../ChildStruct.md) ## Functions @@ -106,7 +104,7 @@ assert(!Err); std::string Expected = R"raw(# class r -*Defined at line 10 of test.cpp* +*Defined at test.cpp#10* Inherits from F, G @@ -171,7 +169,7 @@ *void f(int P)* -*Defined at line 10 of test.cpp* +*Defined at test.cpp#10* )raw"; @@ -202,7 +200,7 @@ | X | -*Defined at line 10 of test.cpp* +*Defined at test.cpp#10* )raw"; @@ -331,7 +329,7 @@ *void f(int I, int J)* -*Defined at line 10 of test.cpp* +*Defined at test.cpp#10* Index: clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp =================================================================== --- clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp +++ clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp @@ -63,24 +63,24 @@ std::string Expected = R"raw(<!DOCTYPE html> <meta charset="utf-8"/> <title>namespace Namespace</title> -<link rel="stylesheet" href="clang-doc-default-stylesheet.css"/> -<link rel="stylesheet" href="user-provided-stylesheet.css"/> -<script src="index.js"></script> +<link rel="stylesheet" href="../clang-doc-default-stylesheet.css"/> +<link rel="stylesheet" href="../user-provided-stylesheet.css"/> +<script src="../index.js"></script> <header id="project-title">test-project</header> <main> - <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> + <div id="sidebar-left" path="Namespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div> <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content"> <h1>namespace Namespace</h1> <h2 id="Namespaces">Namespaces</h2> <ul> <li> - <a href="Namespace/ChildNamespace.html">ChildNamespace</a> + <a href="ChildNamespace/index.html">ChildNamespace</a> </li> </ul> <h2 id="Records">Records</h2> <ul> <li> - <a href="Namespace/ChildStruct.html">ChildStruct</a> + <a href="ChildStruct.html">ChildStruct</a> </li> </ul> <h2 id="Functions">Functions</h2> @@ -196,14 +196,14 @@ <ul> <li> private - <a href="../int.html">int</a> + <a href="../../../X/Y/int.html">int</a> X </li> </ul> <h2 id="Records">Records</h2> <ul> <li> - <a href="r/ChildStruct.html">ChildStruct</a> + <a href="../../../X/Y/Z/r/ChildStruct.html">ChildStruct</a> </li> </ul> <h2 id="Functions">Functions</h2> Index: clang-tools-extra/test/clang-doc/single-file.cpp =================================================================== --- clang-tools-extra/test/clang-doc/single-file.cpp +++ clang-tools-extra/test/clang-doc/single-file.cpp @@ -3,7 +3,7 @@ // RUN: echo "" > %t/compile_flags.txt // RUN: cp "%s" "%t/test.cpp" // RUN: clang-doc --doxygen --executor=standalone -p %t %t/test.cpp -output=%t/docs -// RUN: cat %t/docs/GlobalNamespace.yaml | FileCheck %s --check-prefix=CHECK +// RUN: cat %t/docs/GlobalNamespace/index.yaml | FileCheck %s --check-prefix=CHECK // RUN: rm -rf %t void function(int x); @@ -12,20 +12,20 @@ // CHECK: --- // CHECK-NEXT: USR: '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}' -// CHECK-NEXT: ChildFunctions: +// CHECK-NEXT: ChildFunctions: // CHECK-NEXT: - USR: '{{[0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z][0-9A-Z]}}' // CHECK-NEXT: Name: 'function' -// CHECK-NEXT: DefLocation: +// CHECK-NEXT: DefLocation: // CHECK-NEXT: LineNumber: [[@LINE-8]] // CHECK-NEXT: Filename: '{{.*}} -// CHECK-NEXT: Location: +// CHECK-NEXT: Location: // CHECK-NEXT: - LineNumber: [[@LINE-13]] // CHECK-NEXT: Filename: '{{.*}}' -// CHECK-NEXT: Params: -// CHECK-NEXT: - Type: +// CHECK-NEXT: Params: +// CHECK-NEXT: - Type: // CHECK-NEXT: Name: 'int' // CHECK-NEXT: Name: 'x' -// CHECK-NEXT: ReturnType: -// CHECK-NEXT: Type: +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: // CHECK-NEXT: Name: 'void' // CHECK-NEXT:... Index: clang-tools-extra/clang-doc/tool/ClangDocMain.cpp =================================================================== --- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp +++ clang-tools-extra/clang-doc/tool/ClangDocMain.cpp @@ -293,8 +293,9 @@ } doc::Info *I = Reduced.get().get(); - auto InfoPath = getInfoOutputFile(OutDirectory, I->Path, I->extractName(), - "." + Format); + auto InfoPath = + getInfoOutputFile(OutDirectory, I->getRelativeFilePath(""), + I->getFileBaseName(), "." + Format); if (!InfoPath) { llvm::errs() << toString(InfoPath.takeError()) << "\n"; Error = true; @@ -303,9 +304,9 @@ std::error_code FileErr; llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, llvm::sys::fs::OF_None); - if (FileErr != OK) { - llvm::errs() << "Error opening info file: " << FileErr.message() - << "\n"; + if (FileErr) { + llvm::errs() << "Error opening info file " << InfoPath.get() << ": " + << FileErr.message() << "\n"; return; } Index: clang-tools-extra/clang-doc/assets/index.js =================================================================== --- clang-tools-extra/clang-doc/assets/index.js +++ clang-tools-extra/clang-doc/assets/index.js @@ -31,8 +31,12 @@ function genLink(Ref, CurrentDirectory) { var Path = computeRelativePath(Ref.Path, CurrentDirectory); - Path = append(Path, Ref.Name + ".html") - ANode = document.createElement("a"); + if (Ref.RefType == "namespace") + Path = append(Path, "index.html"); + else + Path = append(Path, Ref.Name + ".html") + + ANode = document.createElement("a"); ANode.setAttribute("href", Path); var TextNode = document.createTextNode(Ref.Name); ANode.appendChild(TextNode); Index: clang-tools-extra/clang-doc/Representation.h =================================================================== --- clang-tools-extra/clang-doc/Representation.h +++ clang-tools-extra/clang-doc/Representation.h @@ -135,6 +135,12 @@ bool mergeable(const Reference &Other); void merge(Reference &&I); + /// Returns the path for this Reference relative to CurrentPath. + llvm::SmallString<64> getRelativeFilePath(const StringRef &CurrentPath) const; + + /// Returns the basename that should be used for this Reference. + llvm::SmallString<16> getFileBaseName() const; + SymbolID USR = SymbolID(); // Unique identifier for referenced decl SmallString<16> Name; // Name of type (possibly unresolved). InfoType RefType = InfoType::IT_default; // Indicates the type of this @@ -262,6 +268,12 @@ llvm::SmallString<16> extractName() const; + /// Returns the file path for this Info relative to CurrentPath. + llvm::SmallString<64> getRelativeFilePath(const StringRef &CurrentPath) const; + + /// Returns the basename that should be used for this Info. + llvm::SmallString<16> getFileBaseName() const; + // Returns a reference to the parent scope (that is, the immediate parent // namespace or class in which this decl resides). llvm::Expected<Reference> getEnclosingScope(); Index: clang-tools-extra/clang-doc/Representation.cpp =================================================================== --- clang-tools-extra/clang-doc/Representation.cpp +++ clang-tools-extra/clang-doc/Representation.cpp @@ -114,6 +114,52 @@ } } +static llvm::SmallString<64> +calculateRelativeFilePath(const InfoType &Type, const StringRef &Path, + const StringRef &Name, const StringRef &CurrentPath) { + llvm::SmallString<64> FilePath; + + if (CurrentPath != Path) { + // iterate back to the top + for (llvm::sys::path::const_iterator I = + llvm::sys::path::begin(CurrentPath); + I != llvm::sys::path::end(CurrentPath); ++I) + llvm::sys::path::append(FilePath, ".."); + llvm::sys::path::append(FilePath, Path); + } + + // Namespace references have a Path to the parent namespace, but + // the file is actually in the subdirectory for the namespace. + if (Type == doc::InfoType::IT_namespace) + llvm::sys::path::append(FilePath, Name); + + return llvm::sys::path::relative_path(FilePath); +} + +llvm::SmallString<64> +Reference::getRelativeFilePath(const StringRef &CurrentPath) const { + return calculateRelativeFilePath(RefType, Path, Name, CurrentPath); +} + +llvm::SmallString<16> Reference::getFileBaseName() const { + if (RefType == InfoType::IT_namespace) + return llvm::SmallString<16>("index"); + + return Name; +} + +llvm::SmallString<64> +Info::getRelativeFilePath(const StringRef &CurrentPath) const { + return calculateRelativeFilePath(IT, Path, extractName(), CurrentPath); +} + +llvm::SmallString<16> Info::getFileBaseName() const { + if (IT == InfoType::IT_namespace) + return llvm::SmallString<16>("index"); + + return extractName(); +} + bool Reference::mergeable(const Reference &Other) { return RefType == Other.RefType && USR == Other.USR; } Index: clang-tools-extra/clang-doc/MDGenerator.cpp =================================================================== --- clang-tools-extra/clang-doc/MDGenerator.cpp +++ clang-tools-extra/clang-doc/MDGenerator.cpp @@ -50,10 +50,20 @@ OS << std::string(Num, '#') + " " + Text << "\n\n"; } -static void writeFileDefinition(const Location &L, raw_ostream &OS) { - OS << genItalic("Defined at line " + std::to_string(L.LineNumber) + " of " + - L.Filename) - << "\n\n"; +static void writeFileDefinition(const ClangDocContext &CDCtx, const Location &L, + raw_ostream &OS) { + + if (!CDCtx.RepositoryUrl) { + OS << "*Defined at " << L.Filename << "#" << std::to_string(L.LineNumber) + << "*"; + } else { + OS << "*Defined at [" << L.Filename << "#" << std::to_string(L.LineNumber) + << "](" << StringRef{CDCtx.RepositoryUrl.getValue()} + << llvm::sys::path::relative_path(L.Filename) << "#" + << std::to_string(L.LineNumber) << ")" + << "*"; + } + OS << "\n\n"; } static void writeDescription(const CommentInfo &I, raw_ostream &OS) { @@ -104,7 +114,18 @@ } } -static void genMarkdown(const EnumInfo &I, llvm::raw_ostream &OS) { +static void writeNameLink(const StringRef &CurrentPath, const Reference &R, + llvm::raw_ostream &OS) { + llvm::SmallString<64> Path = R.getRelativeFilePath(CurrentPath); + // Paths in Markdown use POSIX separators. + llvm::sys::path::native(Path, llvm::sys::path::Style::posix); + llvm::sys::path::append(Path, llvm::sys::path::Style::posix, + R.getFileBaseName() + ".md"); + OS << "[" << R.Name << "](" << Path << ")"; +} + +static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I, + llvm::raw_ostream &OS) { if (I.Scoped) writeLine("| enum class " + I.Name + " |", OS); else @@ -118,13 +139,14 @@ Members << "| " << N << " |\n"; writeLine(Members.str(), OS); if (I.DefLoc) - writeFileDefinition(I.DefLoc.getValue(), OS); + writeFileDefinition(CDCtx, I.DefLoc.getValue(), OS); for (const auto &C : I.Description) writeDescription(C, OS); } -static void genMarkdown(const FunctionInfo &I, llvm::raw_ostream &OS) { +static void genMarkdown(const ClangDocContext &CDCtx, const FunctionInfo &I, + llvm::raw_ostream &OS) { std::string Buffer; llvm::raw_string_ostream Stream(Buffer); bool First = true; @@ -145,13 +167,14 @@ Stream.str() + ")"), OS); if (I.DefLoc) - writeFileDefinition(I.DefLoc.getValue(), OS); + writeFileDefinition(CDCtx, I.DefLoc.getValue(), OS); for (const auto &C : I.Description) writeDescription(C, OS); } -static void genMarkdown(const NamespaceInfo &I, llvm::raw_ostream &OS) { +static void genMarkdown(const ClangDocContext &CDCtx, const NamespaceInfo &I, + llvm::raw_ostream &OS) { if (I.Name == "") writeHeader("Global Namespace", 1, OS); else @@ -164,36 +187,47 @@ writeNewLine(OS); } + llvm::SmallString<64> BasePath = I.getRelativeFilePath(""); + if (!I.ChildNamespaces.empty()) { writeHeader("Namespaces", 2, OS); - for (const auto &R : I.ChildNamespaces) - writeLine(R.Name, OS); + for (const auto &R : I.ChildNamespaces) { + OS << "* "; + writeNameLink(BasePath, R, OS); + OS << "\n"; + } writeNewLine(OS); } + if (!I.ChildRecords.empty()) { writeHeader("Records", 2, OS); - for (const auto &R : I.ChildRecords) - writeLine(R.Name, OS); + for (const auto &R : I.ChildRecords) { + OS << "* "; + writeNameLink(BasePath, R, OS); + OS << "\n"; + } writeNewLine(OS); } + if (!I.ChildFunctions.empty()) { writeHeader("Functions", 2, OS); for (const auto &F : I.ChildFunctions) - genMarkdown(F, OS); + genMarkdown(CDCtx, F, OS); writeNewLine(OS); } if (!I.ChildEnums.empty()) { writeHeader("Enums", 2, OS); for (const auto &E : I.ChildEnums) - genMarkdown(E, OS); + genMarkdown(CDCtx, E, OS); writeNewLine(OS); } } -static void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS) { +static void genMarkdown(const ClangDocContext &CDCtx, const RecordInfo &I, + llvm::raw_ostream &OS) { writeHeader(getTagType(I.TagType) + " " + I.Name, 1, OS); if (I.DefLoc) - writeFileDefinition(I.DefLoc.getValue(), OS); + writeFileDefinition(CDCtx, I.DefLoc.getValue(), OS); if (!I.Description.empty()) { for (const auto &C : I.Description) @@ -234,17 +268,86 @@ if (!I.ChildFunctions.empty()) { writeHeader("Functions", 2, OS); for (const auto &F : I.ChildFunctions) - genMarkdown(F, OS); + genMarkdown(CDCtx, F, OS); writeNewLine(OS); } if (!I.ChildEnums.empty()) { writeHeader("Enums", 2, OS); for (const auto &E : I.ChildEnums) - genMarkdown(E, OS); + genMarkdown(CDCtx, E, OS); writeNewLine(OS); } } +static void serializeReference(llvm::raw_fd_ostream &OS, Index &I, int Level) { + // Write out the heading level starting at ## + OS << "##" << std::string(Level, '#') << " "; + writeNameLink("", I, OS); + OS << "\n"; +} + +static llvm::Error serializeIndex(ClangDocContext &CDCtx) { + std::error_code FileErr; + llvm::SmallString<128> FilePath; + llvm::sys::path::native(CDCtx.OutDirectory, FilePath); + llvm::sys::path::append(FilePath, "all_files.md"); + llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None); + if (FileErr) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "error creating index file: " + + FileErr.message()); + + CDCtx.Idx.sort(); + OS << "# All Files"; + if (!CDCtx.ProjectName.empty()) + OS << " for " << CDCtx.ProjectName; + OS << "\n\n"; + + for (auto C : CDCtx.Idx.Children) + serializeReference(OS, C, 0); + + return llvm::Error::success(); +} + +static llvm::Error genIndex(ClangDocContext &CDCtx) { + std::error_code FileErr; + llvm::SmallString<128> FilePath; + llvm::sys::path::native(CDCtx.OutDirectory, FilePath); + llvm::sys::path::append(FilePath, "index.md"); + llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_None); + if (FileErr) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "error creating index file: " + + FileErr.message()); + CDCtx.Idx.sort(); + OS << "# " << CDCtx.ProjectName << " C/C++ Reference\n\n"; + for (auto C : CDCtx.Idx.Children) { + if (!C.Children.empty()) { + const char *Type; + switch (C.RefType) { + case InfoType::IT_namespace: + Type = "Namespace"; + break; + case InfoType::IT_record: + Type = "Type"; + break; + case InfoType::IT_enum: + Type = "Enum"; + break; + case InfoType::IT_function: + Type = "Function"; + break; + case InfoType::IT_default: + Type = "Other"; + } + OS << "* " << Type << ": [" << C.Name << "]("; + if (!C.Path.empty()) + OS << C.Path << "/"; + OS << C.Name << ")\n"; + } + } + return llvm::Error::success(); +} /// Generator for Markdown documentation. class MDGenerator : public Generator { public: @@ -252,6 +355,7 @@ llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS, const ClangDocContext &CDCtx) override; + llvm::Error createResources(ClangDocContext &CDCtx) override; }; const char *MDGenerator::Format = "md"; @@ -260,16 +364,16 @@ const ClangDocContext &CDCtx) { switch (I->IT) { case InfoType::IT_namespace: - genMarkdown(*static_cast<clang::doc::NamespaceInfo *>(I), OS); + genMarkdown(CDCtx, *static_cast<clang::doc::NamespaceInfo *>(I), OS); break; case InfoType::IT_record: - genMarkdown(*static_cast<clang::doc::RecordInfo *>(I), OS); + genMarkdown(CDCtx, *static_cast<clang::doc::RecordInfo *>(I), OS); break; case InfoType::IT_enum: - genMarkdown(*static_cast<clang::doc::EnumInfo *>(I), OS); + genMarkdown(CDCtx, *static_cast<clang::doc::EnumInfo *>(I), OS); break; case InfoType::IT_function: - genMarkdown(*static_cast<clang::doc::FunctionInfo *>(I), OS); + genMarkdown(CDCtx, *static_cast<clang::doc::FunctionInfo *>(I), OS); break; case InfoType::IT_default: return createStringError(llvm::inconvertibleErrorCode(), @@ -278,11 +382,25 @@ return llvm::Error::success(); } +llvm::Error MDGenerator::createResources(ClangDocContext &CDCtx) { + // Write an all_files.md + auto Err = serializeIndex(CDCtx); + if (Err) + return Err; + + // Generate the index page. + Err = genIndex(CDCtx); + if (Err) + return Err; + + return llvm::Error::success(); +} + static GeneratorRegistry::Add<MDGenerator> MD(MDGenerator::Format, "Generator for MD output."); -// This anchor is used to force the linker to link in the generated object file -// and thus register the generator. +// This anchor is used to force the linker to link in the generated object +// file and thus register the generator. volatile int MDGeneratorAnchorSource = 0; } // namespace doc Index: clang-tools-extra/clang-doc/HTMLGenerator.cpp =================================================================== --- clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -314,9 +314,9 @@ else return genLink(Type.Name, "#" + JumpToSection.getValue()); } - llvm::SmallString<128> Path = - computeRelativePath(Type.Path, CurrentDirectory); - llvm::sys::path::append(Path, Type.Name + ".html"); + llvm::SmallString<64> Path = Type.getRelativeFilePath(CurrentDirectory); + llvm::sys::path::append(Path, Type.getFileBaseName() + ".html"); + // Paths in HTML must be in posix-style llvm::sys::path::native(Path, llvm::sys::path::Style::posix); if (JumpToSection) @@ -730,15 +730,17 @@ if (!I.Description.empty()) Out.emplace_back(genHTML(I.Description)); + llvm::SmallString<64> BasePath = I.getRelativeFilePath(""); + std::vector<std::unique_ptr<TagNode>> ChildNamespaces = - genReferencesBlock(I.ChildNamespaces, "Namespaces", I.Path); + genReferencesBlock(I.ChildNamespaces, "Namespaces", BasePath); AppendVector(std::move(ChildNamespaces), Out); std::vector<std::unique_ptr<TagNode>> ChildRecords = - genReferencesBlock(I.ChildRecords, "Records", I.Path); + genReferencesBlock(I.ChildRecords, "Records", BasePath); AppendVector(std::move(ChildRecords), Out); std::vector<std::unique_ptr<TagNode>> ChildFunctions = - genFunctionsBlock(I.ChildFunctions, CDCtx, I.Path); + genFunctionsBlock(I.ChildFunctions, CDCtx, BasePath); AppendVector(std::move(ChildFunctions), Out); std::vector<std::unique_ptr<TagNode>> ChildEnums = genEnumsBlock(I.ChildEnums, CDCtx); @@ -860,8 +862,8 @@ "unexpected info type"); } - HTMLFile F = - genInfoFile(InfoTitle, I->Path, MainContentNodes, InfoIndex, CDCtx); + HTMLFile F = genInfoFile(InfoTitle, I->getRelativeFilePath(""), + MainContentNodes, InfoIndex, CDCtx); F.Render(OS); return llvm::Error::success(); @@ -902,7 +904,7 @@ J.attribute("USR", toHex(llvm::toStringRef(I.USR))); J.attribute("Name", I.Name); J.attribute("RefType", getRefType(I.RefType)); - J.attribute("Path", I.Path); + J.attribute("Path", I.getRelativeFilePath("")); J.attributeArray("Children", [&] { for (const Index &C : I.Children) IndexToJSON(C);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits