[clang-tools-extra] r365937 - [clang-doc] Add html links to references
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 12 13:55:15 PDT 2019
Hi Diego and Julie,
The tests you modified, emitFunctionHTML and emitRecordHTML are failing when run on Windows due to path separator differences.
http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/26925
FAIL: Extra Tools Unit Tests :: clang-doc/./ClangDocTests.exe/HTMLGeneratorTest.emitFunctionHTML (20152 of 51140)
******************** TEST 'Extra Tools Unit Tests :: clang-doc/./ClangDocTests.exe/HTMLGeneratorTest.emitFunctionHTML' FAILED ********************
Note: Google Test filter = HTMLGeneratorTest.emitFunctionHTML
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from HTMLGeneratorTest
[ RUN ] HTMLGeneratorTest.emitFunctionHTML
C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.src\tools\clang\tools\extra\unittests\clang-doc\HTMLGeneratorTest.cpp(174): error: Expected: Expected
Which is: "<!DOCTYPE html>\n<meta charset=\"utf-8\"/>\n<title></title>\n<div>\n <h3>f</h3>\n <p>\n <a href=\"path/to/float.html\">float</a>\n f(\n <a href=\"path/to/int.html\">int</a>\n P)\n </p>\n <p>\n Defined at line 10 of test.cpp\n </p>\n</div>\n"
To be equal to: Actual.str()
Which is: "<!DOCTYPE html>\n<meta charset=\"utf-8\"/>\n<title></title>\n<div>\n <h3>f</h3>\n <p>\n <a href=\"path/to\\float.html\">float</a>\n f(\n <a href=\"path/to\\int.html\">int</a>\n P)\n </p>\n <p>\n Defined at line 10 of test.cpp\n </p>\n</div>\n"
With diff:
@@ -5,7 +5,7 @@
<h3>f</h3>
<p>
- <a href=\"path/to/float.html\">float</a>
+ <a href=\"path/to\\float.html\">float</a>
f(
- <a href=\"path/to/int.html\">int</a>
+ <a href=\"path/to\\int.html\">int</a>
P)
</p>
[ FAILED ] HTMLGeneratorTest.emitFunctionHTML (1 ms)
[----------] 1 test from HTMLGeneratorTest (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] HTMLGeneratorTest.emitFunctionHTML
1 FAILED TEST
********************
PASS: Clangd Unit Tests :: ./ClangdTests.exe/CompletionTest.CompletionOptions (20153 of 51140)
FAIL: Extra Tools Unit Tests :: clang-doc/./ClangDocTests.exe/HTMLGeneratorTest.emitRecordHTML (20154 of 51140)
******************** TEST 'Extra Tools Unit Tests :: clang-doc/./ClangDocTests.exe/HTMLGeneratorTest.emitRecordHTML' FAILED ********************
Note: Google Test filter = HTMLGeneratorTest.emitRecordHTML
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from HTMLGeneratorTest
[ RUN ] HTMLGeneratorTest.emitRecordHTML
C:\ps4-buildslave2\llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast\llvm.src\tools\clang\tools\extra\unittests\clang-doc\HTMLGeneratorTest.cpp(135): error: Expected: Expected
Which is: "<!DOCTYPE html>\n<meta charset=\"utf-8\"/>\n<title>class r</title>\n<div>\n <h1>class r</h1>\n <p>\n Defined at line 10 of test.cpp\n </p>\n <p>\n Inherits from \n <a href=\"../../../path/to/F.html\">F</a>\n , G\n </p>\n <h2>Members</h2>\n <ul>\n <li>private <a href=\"../int.html\">int</a> X</li>\n </ul>\n <h2>Records</h2>\n <ul>\n <li>ChildStruct</li>\n </ul>\n <h2>Functions</h2>\n <div>\n <h3>OneFunction</h3>\n <p>\n OneFunction()\n </p>\n </div>\n <h2>Enums</h2>\n <div>\n <h3>enum OneEnum</h3>\n </div>\n</div>\n"
To be equal to: Actual.str()
Which is: "<!DOCTYPE html>\n<meta charset=\"utf-8\"/>\n<title>class r</title>\n<div>\n <h1>class r</h1>\n <p>\n Defined at line 10 of test.cpp\n </p>\n <p>\n Inherits from \n <a href=\"..\\..\\..\\path/to\\F.html\">F</a>\n , G\n </p>\n <h2>Members</h2>\n <ul>\n <li>private <a href=\"..\\int.html\">int</a> X</li>\n </ul>\n <h2>Records</h2>\n <ul>\n <li>ChildStruct</li>\n </ul>\n <h2>Functions</h2>\n <div>\n <h3>OneFunction</h3>\n <p>\n OneFunction()\n </p>\n </div>\n <h2>Enums</h2>\n <div>\n <h3>enum OneEnum</h3>\n </div>\n</div>\n"
With diff:
@@ -9,5 +9,5 @@
<p>
Inherits from
- <a href=\"../../../path/to/F.html\">F</a>
+ <a href=\"..\\..\\..\\path/to\\F.html\">F</a>
, G
</p>
@@ -14,5 +14,5 @@
<h2>Members</h2>
<ul>
- <li>private <a href=\"../int.html\">int</a> X</li>
+ <li>private <a href=\"..\\int.html\">int</a> X</li>
</ul>
<h2>Records</h2>
[ FAILED ] HTMLGeneratorTest.emitRecordHTML (1 ms)
[----------] 1 test from HTMLGeneratorTest (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (1 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] HTMLGeneratorTest.emitRecordHTML
1 FAILED TEST
Can you please take a look?
Douglas Yung
-----Original Message-----
From: cfe-commits <cfe-commits-bounces at lists.llvm.org> On Behalf Of Julie Hockett via cfe-commits
Sent: Friday, July 12, 2019 11:32
To: cfe-commits at lists.llvm.org
Subject: [clang-tools-extra] r365937 - [clang-doc] Add html links to references
Author: juliehockett
Date: Fri Jul 12 11:32:00 2019
New Revision: 365937
URL: http://llvm.org/viewvc/llvm-project?rev=365937&view=rev
Log:
[clang-doc] Add html links to references
<a> tags are added for the parents and members of records and return type and
params of functions. The link redirects to the reference's info file.
The directory path where each info file will be saved is now generated in the
serialization phase and stored as an attribute in each Info.
Bitcode writer and reader were modified to handle the new attributes.
Committed on behalf of Diego Astiazarán (diegoaat97 at gmail.com).
Differential Revision: https://reviews.llvm.org/D63663
Modified:
clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp
clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp
clang-tools-extra/trunk/clang-doc/BitcodeWriter.h
clang-tools-extra/trunk/clang-doc/Generators.cpp
clang-tools-extra/trunk/clang-doc/Generators.h
clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp
clang-tools-extra/trunk/clang-doc/MDGenerator.cpp
clang-tools-extra/trunk/clang-doc/Representation.cpp
clang-tools-extra/trunk/clang-doc/Representation.h
clang-tools-extra/trunk/clang-doc/Serialize.cpp
clang-tools-extra/trunk/clang-doc/YAMLGenerator.cpp
clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp
clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp
clang-tools-extra/trunk/unittests/clang-doc/YAMLGeneratorTest.cpp
Modified: clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/BitcodeReader.cpp Fri Jul 12 11:32:00 2019
@@ -148,6 +148,8 @@ llvm::Error parseRecord(Record R, unsign
return decodeRecord(R, I->USR, Blob);
case NAMESPACE_NAME:
return decodeRecord(R, I->Name, Blob);
+ case NAMESPACE_PATH:
+ return decodeRecord(R, I->Path, Blob);
default:
return llvm::make_error<llvm::StringError>(
"Invalid field for NamespaceInfo.\n", llvm::inconvertibleErrorCode());
@@ -161,6 +163,8 @@ llvm::Error parseRecord(Record R, unsign
return decodeRecord(R, I->USR, Blob);
case RECORD_NAME:
return decodeRecord(R, I->Name, Blob);
+ case RECORD_PATH:
+ return decodeRecord(R, I->Path, Blob);
case RECORD_DEFLOCATION:
return decodeRecord(R, I->DefLoc, Blob);
case RECORD_LOCATION:
@@ -286,6 +290,8 @@ llvm::Error parseRecord(Record R, unsign
return decodeRecord(R, I->Name, Blob);
case REFERENCE_TYPE:
return decodeRecord(R, I->RefType, Blob);
+ case REFERENCE_PATH:
+ return decodeRecord(R, I->Path, Blob);
case REFERENCE_FIELD:
return decodeRecord(R, F, Blob);
default:
@@ -685,7 +691,7 @@ ClangDocBitcodeReader::createInfo(unsign
std::unique_ptr<Info> I = llvm::make_unique<T>();
if (auto Err = readBlock(ID, static_cast<T *>(I.get())))
return std::move(Err);
- return std::unique_ptr<Info>{std::move(I)};;
+ return std::unique_ptr<Info>{std::move(I)};
}
llvm::Expected<std::unique_ptr<Info>>
Modified: clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/BitcodeWriter.cpp Fri Jul 12 11:32:00 2019
@@ -148,6 +148,7 @@ static const llvm::IndexedMap<RecordIdDs
{MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
{NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
{NAMESPACE_NAME, {"Name", &StringAbbrev}},
+ {NAMESPACE_PATH, {"Path", &StringAbbrev}},
{ENUM_USR, {"USR", &SymbolIDAbbrev}},
{ENUM_NAME, {"Name", &StringAbbrev}},
{ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
@@ -156,6 +157,7 @@ static const llvm::IndexedMap<RecordIdDs
{ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
{RECORD_USR, {"USR", &SymbolIDAbbrev}},
{RECORD_NAME, {"Name", &StringAbbrev}},
+ {RECORD_PATH, {"Path", &StringAbbrev}},
{RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
{RECORD_LOCATION, {"Location", &LocationAbbrev}},
{RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
@@ -169,6 +171,7 @@ static const llvm::IndexedMap<RecordIdDs
{REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
{REFERENCE_NAME, {"Name", &StringAbbrev}},
{REFERENCE_TYPE, {"RefType", &IntAbbrev}},
+ {REFERENCE_PATH, {"Path", &StringAbbrev}},
{REFERENCE_FIELD, {"Field", &IntAbbrev}}};
assert(Inits.size() == RecordIdCount);
for (const auto &Init : Inits) {
@@ -199,18 +202,20 @@ static const std::vector<std::pair<Block
{ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_MEMBER,
ENUM_SCOPED}},
// Namespace Block
- {BI_NAMESPACE_BLOCK_ID, {NAMESPACE_USR, NAMESPACE_NAME}},
+ {BI_NAMESPACE_BLOCK_ID,
+ {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},
// Record Block
{BI_RECORD_BLOCK_ID,
- {RECORD_USR, RECORD_NAME, RECORD_DEFLOCATION, RECORD_LOCATION,
- RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
+ {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,
+ RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
// Function Block
{BI_FUNCTION_BLOCK_ID,
{FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
// Reference Block
{BI_REFERENCE_BLOCK_ID,
- {REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_FIELD}}};
+ {REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_PATH,
+ REFERENCE_FIELD}}};
// AbbreviationMap
@@ -381,6 +386,7 @@ void ClangDocBitcodeWriter::emitBlock(co
emitRecord(R.USR, REFERENCE_USR);
emitRecord(R.Name, REFERENCE_NAME);
emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
+ emitRecord(R.Path, REFERENCE_PATH);
emitRecord((unsigned)Field, REFERENCE_FIELD);
}
@@ -428,6 +434,7 @@ void ClangDocBitcodeWriter::emitBlock(co
StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
emitRecord(I.USR, NAMESPACE_USR);
emitRecord(I.Name, NAMESPACE_NAME);
+ emitRecord(I.Path, NAMESPACE_PATH);
for (const auto &N : I.Namespace)
emitBlock(N, FieldId::F_namespace);
for (const auto &CI : I.Description)
@@ -463,6 +470,7 @@ void ClangDocBitcodeWriter::emitBlock(co
StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
emitRecord(I.USR, RECORD_USR);
emitRecord(I.Name, RECORD_NAME);
+ emitRecord(I.Path, RECORD_PATH);
for (const auto &N : I.Namespace)
emitBlock(N, FieldId::F_namespace);
for (const auto &CI : I.Description)
Modified: clang-tools-extra/trunk/clang-doc/BitcodeWriter.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/BitcodeWriter.h?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/BitcodeWriter.h (original)
+++ clang-tools-extra/trunk/clang-doc/BitcodeWriter.h Fri Jul 12 11:32:00 2019
@@ -91,6 +91,7 @@ enum RecordId {
MEMBER_TYPE_ACCESS,
NAMESPACE_USR,
NAMESPACE_NAME,
+ NAMESPACE_PATH,
ENUM_USR,
ENUM_NAME,
ENUM_DEFLOCATION,
@@ -99,6 +100,7 @@ enum RecordId {
ENUM_SCOPED,
RECORD_USR,
RECORD_NAME,
+ RECORD_PATH,
RECORD_DEFLOCATION,
RECORD_LOCATION,
RECORD_TAG_TYPE,
@@ -106,6 +108,7 @@ enum RecordId {
REFERENCE_USR,
REFERENCE_NAME,
REFERENCE_TYPE,
+ REFERENCE_PATH,
REFERENCE_FIELD,
RI_LAST,
RI_FIRST = VERSION
Modified: clang-tools-extra/trunk/clang-doc/Generators.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Generators.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Generators.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/Generators.cpp Fri Jul 12 11:32:00 2019
@@ -57,19 +57,6 @@ std::string getTagType(TagTypeKind AS) {
llvm_unreachable("Unknown TagTypeKind");
}
-// Generates a comma-separated list of Refs
-// Used to display the parents of a record
-std::string genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
- std::string Buffer;
- llvm::raw_string_ostream Stream(Buffer);
- for (const auto &R : Refs) {
- if (&R != Refs.begin())
- Stream << ", ";
- Stream << R.Name;
- }
- return Stream.str();
-}
-
// This anchor is used to force the linker to link in the generated object file
// and thus register the generators.
extern volatile int YAMLGeneratorAnchorSource;
Modified: clang-tools-extra/trunk/clang-doc/Generators.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Generators.h?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Generators.h (original)
+++ clang-tools-extra/trunk/clang-doc/Generators.h Fri Jul 12 11:32:00 2019
@@ -38,8 +38,6 @@ std::string getAccess(AccessSpecifier AS
std::string getTagType(TagTypeKind AS);
-std::string genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs);
-
} // namespace doc
} // namespace clang
Modified: clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/HTMLGenerator.cpp Fri Jul 12 11:32:00 2019
@@ -18,13 +18,6 @@ using namespace llvm;
namespace clang {
namespace doc {
-template <typename Derived, typename Base,
- typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
-static void AppendVector(std::vector<Derived> &&New,
- std::vector<Base> &Original) {
- std::move(New.begin(), New.end(), std::back_inserter(Original));
-}
-
namespace {
class HTMLTag {
@@ -40,6 +33,7 @@ public:
TAG_P,
TAG_UL,
TAG_LI,
+ TAG_A,
};
HTMLTag() = default;
@@ -58,15 +52,22 @@ private:
TagType Value;
};
+enum NodeType {
+ NODE_TEXT,
+ NODE_TAG,
+};
+
struct HTMLNode {
+ HTMLNode(NodeType Type) : Type(Type) {}
virtual ~HTMLNode() = default;
virtual void Render(llvm::raw_ostream &OS, int IndentationLevel) = 0;
+ NodeType Type; // Type of node
};
struct TextNode : public HTMLNode {
- TextNode(llvm::StringRef Text, bool Indented)
- : Text(Text), Indented(Indented) {}
+ TextNode(const Twine &Text, bool Indented = true)
+ : HTMLNode(NodeType::NODE_TEXT), Text(Text.str()), Indented(Indented) {}
std::string Text; // Content of node
bool Indented; // Indicates if an indentation must be rendered before the text
@@ -75,7 +76,8 @@ struct TextNode : public HTMLNode {
struct TagNode : public HTMLNode {
TagNode(HTMLTag Tag)
- : Tag(Tag), InlineChildren(Tag.HasInlineChildren()),
+ : HTMLNode(NodeType::NODE_TAG), Tag(Tag),
+ InlineChildren(Tag.HasInlineChildren()),
SelfClosing(Tag.IsSelfClosing()) {}
TagNode(HTMLTag Tag, const Twine &Text) : TagNode(Tag) {
Children.emplace_back(
@@ -121,6 +123,7 @@ bool HTMLTag::IsSelfClosing() const {
case HTMLTag::TAG_P:
case HTMLTag::TAG_UL:
case HTMLTag::TAG_LI:
+ case HTMLTag::TAG_A:
return false;
}
llvm_unreachable("Unhandled HTMLTag::TagType");
@@ -134,6 +137,7 @@ bool HTMLTag::HasInlineChildren() const
case HTMLTag::TAG_H2:
case HTMLTag::TAG_H3:
case HTMLTag::TAG_LI:
+ case HTMLTag::TAG_A:
return true;
case HTMLTag::TAG_DIV:
case HTMLTag::TAG_P:
@@ -163,6 +167,8 @@ llvm::SmallString<16> HTMLTag::ToString(
return llvm::SmallString<16>("ul");
case HTMLTag::TAG_LI:
return llvm::SmallString<16>("li");
+ case HTMLTag::TAG_A:
+ return llvm::SmallString<16>("a");
}
llvm_unreachable("Unhandled HTMLTag::TagType");
}
@@ -185,21 +191,87 @@ void TagNode::Render(llvm::raw_ostream &
OS << ">";
if (!InlineChildren)
OS << "\n";
- int ChildrenIndentation = InlineChildren ? 0 : IndentationLevel + 1;
+ bool NewLineRendered = true;
for (const auto &C : Children) {
+ int ChildrenIndentation =
+ InlineChildren || !NewLineRendered ? 0 : IndentationLevel + 1;
C->Render(OS, ChildrenIndentation);
- if (!InlineChildren)
+ if (!InlineChildren && (C == Children.back() ||
+ (C->Type != NodeType::NODE_TEXT ||
+ (&C + 1)->get()->Type != NodeType::NODE_TEXT))) {
OS << "\n";
+ NewLineRendered = true;
+ } else
+ NewLineRendered = false;
}
if (!InlineChildren)
OS.indent(IndentationLevel * 2);
OS << "</" << Tag.ToString() << ">";
}
+template <typename Derived, typename Base,
+ typename = std::enable_if<std::is_base_of<Derived, Base>::value>>
+static void AppendVector(std::vector<Derived> &&New,
+ std::vector<Base> &Original) {
+ std::move(New.begin(), New.end(), std::back_inserter(Original));
+}
+
+// Compute the relative path that names the file path relative to the given
+// directory.
+static SmallString<128> computeRelativePath(StringRef FilePath,
+ StringRef Directory) {
+ StringRef Path = FilePath;
+ while (!Path.empty()) {
+ if (Directory == Path)
+ return FilePath.substr(Path.size());
+ Path = llvm::sys::path::parent_path(Path);
+ }
+
+ StringRef Dir = Directory;
+ SmallString<128> Result;
+ while (!Dir.empty()) {
+ if (Dir == FilePath)
+ break;
+ Dir = llvm::sys::path::parent_path(Dir);
+ llvm::sys::path::append(Result, "..");
+ }
+ llvm::sys::path::append(Result, FilePath.substr(Dir.size()));
+ return Result;
+}
+
// HTML generation
+static std::unique_ptr<TagNode> genLink(const Twine &Text, const Twine &Link) {
+ auto LinkNode = llvm::make_unique<TagNode>(HTMLTag::TAG_A, Text);
+ LinkNode->Attributes.try_emplace("href", Link.str());
+ return LinkNode;
+}
+
+static std::unique_ptr<HTMLNode> genTypeReference(const Reference &Type,
+ StringRef CurrentDirectory) {
+ if (Type.Path.empty())
+ return llvm::make_unique<TextNode>(Type.Name);
+ llvm::SmallString<128> Path =
+ computeRelativePath(Type.Path, CurrentDirectory);
+ llvm::sys::path::append(Path, Type.Name + ".html");
+ return genLink(Type.Name, Path);
+}
+
+static std::vector<std::unique_ptr<HTMLNode>>
+genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs,
+ const StringRef &CurrentDirectory) {
+ std::vector<std::unique_ptr<HTMLNode>> Out;
+ for (const auto &R : Refs) {
+ if (&R != Refs.begin())
+ Out.emplace_back(llvm::make_unique<TextNode>(", "));
+ Out.emplace_back(genTypeReference(R, CurrentDirectory));
+ }
+ return Out;
+}
+
static std::vector<std::unique_ptr<TagNode>> genHTML(const EnumInfo &I);
-static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I);
+static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
+ StringRef ParentInfoDir);
static std::vector<std::unique_ptr<TagNode>>
genEnumsBlock(const std::vector<EnumInfo> &Enums) {
@@ -229,7 +301,8 @@ genEnumMembersBlock(const llvm::SmallVec
}
static std::vector<std::unique_ptr<TagNode>>
-genFunctionsBlock(const std::vector<FunctionInfo> &Functions) {
+genFunctionsBlock(const std::vector<FunctionInfo> &Functions,
+ StringRef ParentInfoDir) {
if (Functions.empty())
return {};
@@ -238,14 +311,15 @@ genFunctionsBlock(const std::vector<Func
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_DIV));
auto &DivBody = Out.back();
for (const auto &F : Functions) {
- std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(F);
+ std::vector<std::unique_ptr<TagNode>> Nodes = genHTML(F, ParentInfoDir);
AppendVector(std::move(Nodes), DivBody->Children);
}
return Out;
}
static std::vector<std::unique_ptr<TagNode>>
-genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members) {
+genRecordMembersBlock(const llvm::SmallVector<MemberTypeInfo, 4> &Members,
+ StringRef ParentInfoDir) {
if (Members.empty())
return {};
@@ -257,8 +331,11 @@ genRecordMembersBlock(const llvm::SmallV
std::string Access = getAccess(M.Access);
if (Access != "")
Access = Access + " ";
- ULBody->Children.emplace_back(llvm::make_unique<TagNode>(
- HTMLTag::TAG_LI, Access + M.Type.Name + " " + M.Name));
+ auto LIBody = llvm::make_unique<TagNode>(HTMLTag::TAG_LI);
+ LIBody->Children.emplace_back(llvm::make_unique<TextNode>(Access));
+ LIBody->Children.emplace_back(genTypeReference(M.Type, ParentInfoDir));
+ LIBody->Children.emplace_back(llvm::make_unique<TextNode>(" " + M.Name));
+ ULBody->Children.emplace_back(std::move(LIBody));
}
return Out;
}
@@ -346,25 +423,35 @@ static std::vector<std::unique_ptr<TagNo
return Out;
}
-static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I) {
+static std::vector<std::unique_ptr<TagNode>> genHTML(const FunctionInfo &I,
+ StringRef ParentInfoDir) {
std::vector<std::unique_ptr<TagNode>> Out;
Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_H3, I.Name));
- std::string Buffer;
- llvm::raw_string_ostream Stream(Buffer);
- for (const auto &P : I.Params) {
- if (&P != I.Params.begin())
- Stream << ", ";
- Stream << P.Type.Name + " " + P.Name;
- }
+ Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
+ auto &FunctionHeader = Out.back();
std::string Access = getAccess(I.Access);
if (Access != "")
- Access = Access + " ";
+ FunctionHeader->Children.emplace_back(
+ llvm::make_unique<TextNode>(Access + " "));
+ if (I.ReturnType.Type.Name != "") {
+ FunctionHeader->Children.emplace_back(
+ genTypeReference(I.ReturnType.Type, ParentInfoDir));
+ FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(" "));
+ }
+ FunctionHeader->Children.emplace_back(
+ llvm::make_unique<TextNode>(I.Name + "("));
- Out.emplace_back(llvm::make_unique<TagNode>(
- HTMLTag::TAG_P, Access + I.ReturnType.Type.Name + " " + I.Name + "(" +
- Stream.str() + ")"));
+ for (const auto &P : I.Params) {
+ if (&P != I.Params.begin())
+ FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(", "));
+ FunctionHeader->Children.emplace_back(
+ genTypeReference(P.Type, ParentInfoDir));
+ FunctionHeader->Children.emplace_back(
+ llvm::make_unique<TextNode>(" " + P.Name));
+ }
+ FunctionHeader->Children.emplace_back(llvm::make_unique<TextNode>(")"));
if (I.DefLoc)
Out.emplace_back(writeFileDefinition(I.DefLoc.getValue()));
@@ -398,7 +485,7 @@ static std::vector<std::unique_ptr<TagNo
AppendVector(std::move(ChildRecords), Out);
std::vector<std::unique_ptr<TagNode>> ChildFunctions =
- genFunctionsBlock(I.ChildFunctions);
+ genFunctionsBlock(I.ChildFunctions, I.Path);
AppendVector(std::move(ChildFunctions), Out);
std::vector<std::unique_ptr<TagNode>> ChildEnums =
genEnumsBlock(I.ChildEnums);
@@ -420,29 +507,34 @@ static std::vector<std::unique_ptr<TagNo
if (!I.Description.empty())
Out.emplace_back(genHTML(I.Description));
- std::string Parents = genReferenceList(I.Parents);
- std::string VParents = genReferenceList(I.VirtualParents);
+ std::vector<std::unique_ptr<HTMLNode>> Parents =
+ genReferenceList(I.Parents, I.Path);
+ std::vector<std::unique_ptr<HTMLNode>> VParents =
+ genReferenceList(I.VirtualParents, I.Path);
if (!Parents.empty() || !VParents.empty()) {
+ Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P));
+ auto &PBody = Out.back();
+ PBody->Children.emplace_back(llvm::make_unique<TextNode>("Inherits from "));
if (Parents.empty())
- Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P,
- "Inherits from " + VParents));
+ AppendVector(std::move(VParents), PBody->Children);
else if (VParents.empty())
- Out.emplace_back(llvm::make_unique<TagNode>(HTMLTag::TAG_P,
- "Inherits from " + Parents));
- else
- Out.emplace_back(llvm::make_unique<TagNode>(
- HTMLTag::TAG_P, "Inherits from " + Parents + ", " + VParents));
+ AppendVector(std::move(Parents), PBody->Children);
+ else {
+ AppendVector(std::move(Parents), PBody->Children);
+ PBody->Children.emplace_back(llvm::make_unique<TextNode>(", "));
+ AppendVector(std::move(VParents), PBody->Children);
+ }
}
std::vector<std::unique_ptr<TagNode>> Members =
- genRecordMembersBlock(I.Members);
+ genRecordMembersBlock(I.Members, I.Path);
AppendVector(std::move(Members), Out);
std::vector<std::unique_ptr<TagNode>> ChildRecords =
genReferencesBlock(I.ChildRecords, "Records");
AppendVector(std::move(ChildRecords), Out);
std::vector<std::unique_ptr<TagNode>> ChildFunctions =
- genFunctionsBlock(I.ChildFunctions);
+ genFunctionsBlock(I.ChildFunctions, I.Path);
AppendVector(std::move(ChildFunctions), Out);
std::vector<std::unique_ptr<TagNode>> ChildEnums =
genEnumsBlock(I.ChildEnums);
@@ -492,7 +584,7 @@ llvm::Error HTMLGenerator::generateDocFo
}
case InfoType::IT_function: {
std::vector<std::unique_ptr<TagNode>> Nodes =
- genHTML(*static_cast<clang::doc::FunctionInfo *>(I));
+ genHTML(*static_cast<clang::doc::FunctionInfo *>(I), "");
AppendVector(std::move(Nodes), MainContentNode->Children);
break;
}
Modified: clang-tools-extra/trunk/clang-doc/MDGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/MDGenerator.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/MDGenerator.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/MDGenerator.cpp Fri Jul 12 11:32:00 2019
@@ -28,6 +28,18 @@ static std::string genEmphasis(const Twi
return "**" + Text.str() + "**";
}
+static std::string
+genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
+ std::string Buffer;
+ llvm::raw_string_ostream Stream(Buffer);
+ for (const auto &R : Refs) {
+ if (&R != Refs.begin())
+ Stream << ", ";
+ Stream << R.Name;
+ }
+ return Stream.str();
+}
+
static void writeLine(const Twine &Text, raw_ostream &OS) {
OS << Text << "\n\n";
}
Modified: clang-tools-extra/trunk/clang-doc/Representation.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Representation.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/Representation.cpp Fri Jul 12 11:32:00 2019
@@ -118,6 +118,8 @@ void Info::mergeBase(Info &&Other) {
USR = Other.USR;
if (Name == "")
Name = Other.Name;
+ if (Path == "")
+ Path = Other.Path;
if (Namespace.empty())
Namespace = std::move(Other.Namespace);
// Unconditionally extend the description, since each decl may have a comment.
Modified: clang-tools-extra/trunk/clang-doc/Representation.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Representation.h?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Representation.h (original)
+++ clang-tools-extra/trunk/clang-doc/Representation.h Fri Jul 12 11:32:00 2019
@@ -114,8 +114,11 @@ struct CommentInfo {
struct Reference {
Reference() = default;
Reference(llvm::StringRef Name) : Name(Name) {}
+ Reference(llvm::StringRef Name, StringRef Path) : Name(Name), Path(Path) {}
Reference(SymbolID USR, StringRef Name, InfoType IT)
: USR(USR), Name(Name), RefType(IT) {}
+ Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef Path)
+ : USR(USR), Name(Name), RefType(IT), Path(Path) {}
bool operator==(const Reference &Other) const {
return std::tie(USR, Name, RefType) ==
@@ -127,6 +130,8 @@ struct Reference {
InfoType RefType = InfoType::IT_default; // Indicates the type of this
// Reference (namespace, record,
// function, enum, default).
+ llvm::SmallString<128> Path; // Path of directory where the clang-doc
+ // generated file will be saved
};
// A base struct for TypeInfos
@@ -134,7 +139,10 @@ struct TypeInfo {
TypeInfo() = default;
TypeInfo(SymbolID Type, StringRef Field, InfoType IT)
: Type(Type, Field, IT) {}
+ TypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path)
+ : Type(Type, Field, IT, Path) {}
TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
+ TypeInfo(llvm::StringRef RefName, StringRef Path) : Type(RefName, Path) {}
bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
@@ -144,11 +152,13 @@ struct TypeInfo {
// Info for field types.
struct FieldTypeInfo : public TypeInfo {
FieldTypeInfo() = default;
- FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT,
+ FieldTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
llvm::StringRef Name)
- : TypeInfo(Type, Field, IT), Name(Name) {}
+ : TypeInfo(Type, Field, IT, Path), Name(Name) {}
FieldTypeInfo(llvm::StringRef RefName, llvm::StringRef Name)
: TypeInfo(RefName), Name(Name) {}
+ FieldTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name)
+ : TypeInfo(RefName, Path), Name(Name) {}
bool operator==(const FieldTypeInfo &Other) const {
return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
@@ -160,12 +170,15 @@ struct FieldTypeInfo : public TypeInfo {
// Info for member types.
struct MemberTypeInfo : public FieldTypeInfo {
MemberTypeInfo() = default;
- MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT,
+ MemberTypeInfo(SymbolID Type, StringRef Field, InfoType IT, StringRef Path,
llvm::StringRef Name, AccessSpecifier Access)
- : FieldTypeInfo(Type, Field, IT, Name), Access(Access) {}
+ : FieldTypeInfo(Type, Field, IT, Path, Name), Access(Access) {}
MemberTypeInfo(llvm::StringRef RefName, llvm::StringRef Name,
AccessSpecifier Access)
: FieldTypeInfo(RefName, Name), Access(Access) {}
+ MemberTypeInfo(llvm::StringRef RefName, StringRef Path, llvm::StringRef Name,
+ AccessSpecifier Access)
+ : FieldTypeInfo(RefName, Path, Name), Access(Access) {}
bool operator==(const MemberTypeInfo &Other) const {
return std::tie(Type, Name, Access) ==
@@ -220,6 +233,8 @@ struct Info {
llvm::SmallVector<Reference, 4>
Namespace; // List of parent namespaces for this decl.
std::vector<CommentInfo> Description; // Comment description of this decl.
+ llvm::SmallString<128> Path; // Path of directory where the clang-doc
+ // generated file will be saved
void mergeBase(Info &&I);
bool mergeable(const Info &Other);
Modified: clang-tools-extra/trunk/clang-doc/Serialize.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/Serialize.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/Serialize.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/Serialize.cpp Fri Jul 12 11:32:00 2019
@@ -24,6 +24,43 @@ SymbolID hashUSR(llvm::StringRef USR) {
return llvm::SHA1::hash(arrayRefFromStringRef(USR));
}
+template <typename T>
+static void
+populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
+ const T *D, bool &IsAnonymousNamespace);
+
+// A function to extract the appropriate relative path for a given info's
+// documentation. The path returned is a composite of the parent namespaces.
+//
+// Example: Given the below, the diretory path for class C info will be
+// <root>/A/B
+//
+// namespace A {
+// namesapce B {
+//
+// class C {};
+//
+// }
+// }
+llvm::SmallString<128>
+getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
+ std::error_code OK;
+ llvm::SmallString<128> Path;
+ for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
+ llvm::sys::path::append(Path, R->Name);
+ return Path;
+}
+
+llvm::SmallString<128> getInfoRelativePath(const Decl *D) {
+ llvm::SmallVector<Reference, 4> Namespaces;
+ // The third arg in populateParentNamespaces is a boolean passed by reference,
+ // its value is not relevant in here so it's not used anywhere besides the
+ // function call
+ bool B = true;
+ populateParentNamespaces(Namespaces, D, B);
+ return getInfoRelativePath(Namespaces);
+}
+
class ClangDocCommentVisitor
: public ConstCommentVisitor<ClangDocCommentVisitor> {
public:
@@ -203,13 +240,13 @@ static void parseFields(RecordInfo &I, c
// valid, as opposed to an assert.
if (const auto *N = dyn_cast<EnumDecl>(T)) {
I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
- InfoType::IT_enum, F->getNameAsString(),
- N->getAccessUnsafe());
+ InfoType::IT_enum, getInfoRelativePath(N),
+ F->getNameAsString(), N->getAccessUnsafe());
continue;
} else if (const auto *N = dyn_cast<RecordDecl>(T)) {
I.Members.emplace_back(getUSRForDecl(T), N->getNameAsString(),
- InfoType::IT_record, F->getNameAsString(),
- N->getAccessUnsafe());
+ InfoType::IT_record, getInfoRelativePath(N),
+ F->getNameAsString(), N->getAccessUnsafe());
continue;
}
}
@@ -228,11 +265,13 @@ static void parseParameters(FunctionInfo
if (const auto *T = getDeclForType(P->getOriginalType())) {
if (const auto *N = dyn_cast<EnumDecl>(T)) {
I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
- InfoType::IT_enum, P->getNameAsString());
+ InfoType::IT_enum, getInfoRelativePath(N),
+ P->getNameAsString());
continue;
} else if (const auto *N = dyn_cast<RecordDecl>(T)) {
I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
- InfoType::IT_record, P->getNameAsString());
+ InfoType::IT_record, getInfoRelativePath(N),
+ P->getNameAsString());
continue;
}
}
@@ -254,14 +293,15 @@ static void parseBases(RecordInfo &I, co
InfoType::IT_record);
} else if (const RecordDecl *P = getDeclForType(B.getType()))
I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
- InfoType::IT_record);
+ InfoType::IT_record, getInfoRelativePath(P));
else
I.Parents.emplace_back(B.getType().getAsString());
}
for (const CXXBaseSpecifier &B : D->vbases()) {
if (const auto *P = getDeclForType(B.getType()))
I.VirtualParents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
- InfoType::IT_record);
+ InfoType::IT_record,
+ getInfoRelativePath(P));
else
I.VirtualParents.emplace_back(B.getType().getAsString());
}
@@ -270,14 +310,14 @@ static void parseBases(RecordInfo &I, co
template <typename T>
static void
populateParentNamespaces(llvm::SmallVector<Reference, 4> &Namespaces,
- const T *D, bool &IsAnonymousNamespace) {
+ const T *D, bool &IsInAnonymousNamespace) {
const auto *DC = dyn_cast<DeclContext>(D);
while ((DC = DC->getParent())) {
if (const auto *N = dyn_cast<NamespaceDecl>(DC)) {
std::string Namespace;
if (N->isAnonymousNamespace()) {
Namespace = "@nonymous_namespace";
- IsAnonymousNamespace = true;
+ IsInAnonymousNamespace = true;
} else
Namespace = N->getNameAsString();
Namespaces.emplace_back(getUSRForDecl(N), Namespace,
@@ -324,11 +364,11 @@ static void populateFunctionInfo(Functio
populateSymbolInfo(I, D, FC, LineNumber, Filename, IsInAnonymousNamespace);
if (const auto *T = getDeclForType(D->getReturnType())) {
if (dyn_cast<EnumDecl>(T))
- I.ReturnType =
- TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_enum);
+ I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
+ InfoType::IT_enum, getInfoRelativePath(T));
else if (dyn_cast<RecordDecl>(T))
- I.ReturnType =
- TypeInfo(getUSRForDecl(T), T->getNameAsString(), InfoType::IT_record);
+ I.ReturnType = TypeInfo(getUSRForDecl(T), T->getNameAsString(),
+ InfoType::IT_record, getInfoRelativePath(T));
} else {
I.ReturnType = TypeInfo(D->getReturnType().getAsString());
}
@@ -347,16 +387,18 @@ emitInfo(const NamespaceDecl *D, const F
I->Name = D->isAnonymousNamespace()
? llvm::SmallString<16>("@nonymous_namespace")
: I->Name;
+ I->Path = getInfoRelativePath(I->Namespace);
if (I->Namespace.empty() && I->USR == SymbolID())
return {std::unique_ptr<Info>{std::move(I)}, nullptr};
- SymbolID ParentUSR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
-
- auto Parent = llvm::make_unique<NamespaceInfo>();
- Parent->USR = ParentUSR;
- Parent->ChildNamespaces.emplace_back(I->USR, I->Name, InfoType::IT_namespace);
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = I->Namespace.empty() ? SymbolID() : I->Namespace[0].USR;
+ ParentI->ChildNamespaces.emplace_back(I->USR, I->Name,
+ InfoType::IT_namespace);
+ if (I->Namespace.empty())
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
@@ -378,32 +420,34 @@ emitInfo(const RecordDecl *D, const Full
}
parseBases(*I, C);
}
+ I->Path = getInfoRelativePath(I->Namespace);
if (I->Namespace.empty()) {
- auto Parent = llvm::make_unique<NamespaceInfo>();
- Parent->USR = SymbolID();
- Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = SymbolID();
+ ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
switch (I->Namespace[0].RefType) {
case InfoType::IT_namespace: {
- auto Parent = llvm::make_unique<NamespaceInfo>();
- Parent->USR = I->Namespace[0].USR;
- Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = I->Namespace[0].USR;
+ ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
case InfoType::IT_record: {
- auto Parent = llvm::make_unique<RecordInfo>();
- Parent->USR = I->Namespace[0].USR;
- Parent->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
+ auto ParentI = llvm::make_unique<RecordInfo>();
+ ParentI->USR = I->Namespace[0].USR;
+ ParentI->ChildRecords.emplace_back(I->USR, I->Name, InfoType::IT_record);
return {std::unique_ptr<Info>{std::move(I)},
- std::unique_ptr<Info>{std::move(Parent)}};
+ std::unique_ptr<Info>{std::move(ParentI)}};
}
default:
- llvm_unreachable("Invalid reference type");
+ llvm_unreachable("Invalid reference type for parent namespace");
}
}
@@ -420,14 +464,16 @@ emitInfo(const FunctionDecl *D, const Fu
Func.Access = clang::AccessSpecifier::AS_none;
// Wrap in enclosing scope
- auto I = llvm::make_unique<NamespaceInfo>();
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
if (!Func.Namespace.empty())
- I->USR = Func.Namespace[0].USR;
+ ParentI->USR = Func.Namespace[0].USR;
else
- I->USR = SymbolID();
- I->ChildFunctions.emplace_back(std::move(Func));
- // Info es wrapped in its parent scope so it's returned in the second position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+ ParentI->USR = SymbolID();
+ if (Func.Namespace.empty())
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
+ ParentI->ChildFunctions.emplace_back(std::move(Func));
+ // Info is wrapped in its parent scope so it's returned in the second position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
}
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
@@ -455,11 +501,13 @@ emitInfo(const CXXMethodDecl *D, const F
Func.Access = D->getAccess();
// Wrap in enclosing scope
- auto I = llvm::make_unique<RecordInfo>();
- I->USR = ParentUSR;
- I->ChildFunctions.emplace_back(std::move(Func));
+ auto ParentI = llvm::make_unique<RecordInfo>();
+ ParentI->USR = ParentUSR;
+ if (Func.Namespace.empty())
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
+ ParentI->ChildFunctions.emplace_back(std::move(Func));
// Info is wrapped in its parent scope so it's returned in the second position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
}
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
@@ -475,36 +523,38 @@ emitInfo(const EnumDecl *D, const FullCo
Enum.Scoped = D->isScoped();
parseEnumerators(Enum, D);
- // Wrap in enclosing scope
- if (!Enum.Namespace.empty()) {
- switch (Enum.Namespace[0].RefType) {
- case InfoType::IT_namespace: {
- auto I = llvm::make_unique<NamespaceInfo>();
- I->USR = Enum.Namespace[0].USR;
- I->ChildEnums.emplace_back(std::move(Enum));
- // Info is wrapped in its parent scope so it's returned in the second
- // position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
- }
- case InfoType::IT_record: {
- auto I = llvm::make_unique<RecordInfo>();
- I->USR = Enum.Namespace[0].USR;
- I->ChildEnums.emplace_back(std::move(Enum));
- // Info is wrapped in its parent scope so it's returned in the second
- // position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
- }
- default:
- break;
- }
+ // Put in global namespace
+ if (Enum.Namespace.empty()) {
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = SymbolID();
+ ParentI->ChildEnums.emplace_back(std::move(Enum));
+ ParentI->Path = getInfoRelativePath(ParentI->Namespace);
+ // Info is wrapped in its parent scope so it's returned in the second
+ // position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
}
- // Put in global namespace
- auto I = llvm::make_unique<NamespaceInfo>();
- I->USR = SymbolID();
- I->ChildEnums.emplace_back(std::move(Enum));
- // Info is wrapped in its parent scope so it's returned in the second position
- return {nullptr, std::unique_ptr<Info>{std::move(I)}};
+ // Wrap in enclosing scope
+ switch (Enum.Namespace[0].RefType) {
+ case InfoType::IT_namespace: {
+ auto ParentI = llvm::make_unique<NamespaceInfo>();
+ ParentI->USR = Enum.Namespace[0].USR;
+ ParentI->ChildEnums.emplace_back(std::move(Enum));
+ // Info is wrapped in its parent scope so it's returned in the second
+ // position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
+ }
+ case InfoType::IT_record: {
+ auto ParentI = llvm::make_unique<RecordInfo>();
+ ParentI->USR = Enum.Namespace[0].USR;
+ ParentI->ChildEnums.emplace_back(std::move(Enum));
+ // Info is wrapped in its parent scope so it's returned in the second
+ // position
+ return {nullptr, std::unique_ptr<Info>{std::move(ParentI)}};
+ }
+ default:
+ llvm_unreachable("Invalid reference type for parent namespace");
+ }
}
} // namespace serialize
Modified: clang-tools-extra/trunk/clang-doc/YAMLGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/YAMLGenerator.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/YAMLGenerator.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/YAMLGenerator.cpp Fri Jul 12 11:32:00 2019
@@ -113,6 +113,7 @@ static void FieldTypeInfoMapping(IO &IO,
static void InfoMapping(IO &IO, Info &I) {
IO.mapRequired("USR", I.USR);
IO.mapOptional("Name", I.Name, SmallString<16>());
+ IO.mapOptional("Path", I.Path, SmallString<128>());
IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
IO.mapOptional("Description", I.Description);
}
@@ -154,6 +155,7 @@ template <> struct MappingTraits<Referen
IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
IO.mapOptional("Name", Ref.Name, SmallString<16>());
IO.mapOptional("USR", Ref.USR, SymbolID());
+ IO.mapOptional("Path", Ref.Path, SmallString<128>());
}
};
Modified: clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp (original)
+++ clang-tools-extra/trunk/clang-doc/tool/ClangDocMain.cpp Fri Jul 12 11:32:00 2019
@@ -110,12 +110,13 @@ bool CreateDirectory(const Twine &DirNam
return false;
}
-// A function to extract the appropriate path name for a given info's
-// documentation. The path returned is a composite of the parent namespaces as
-// directories plus the decl name as the filename.
+// A function to extract the appropriate file name for a given info's
+// documentation. The path returned is a composite of the output directory, the
+// info's relative path and name and the extension. The relative path should
+// have been constructed in the serialization phase.
//
-// Example: Given the below, the <ext> path for class C will be <
-// root>/A/B/C.<ext>
+// Example: Given the below, the <ext> path for class C will be
+// <root>/A/B/C.<ext>
//
// namespace A {
// namesapce B {
@@ -124,16 +125,14 @@ bool CreateDirectory(const Twine &DirNam
//
// }
// }
-llvm::Expected<llvm::SmallString<128>>
-getInfoOutputFile(StringRef Root,
- llvm::SmallVectorImpl<doc::Reference> &Namespaces,
- StringRef Name, StringRef Ext) {
+llvm::Expected<llvm::SmallString<128>> getInfoOutputFile(StringRef Root,
+ StringRef RelativePath,
+ StringRef Name,
+ StringRef Ext) {
std::error_code OK;
llvm::SmallString<128> Path;
llvm::sys::path::native(Root, Path);
- for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
- llvm::sys::path::append(Path, R->Name);
-
+ llvm::sys::path::append(Path, RelativePath);
if (CreateDirectory(Path))
return llvm::make_error<llvm::StringError>("Unable to create directory.\n",
llvm::inconvertibleErrorCode());
@@ -223,12 +222,11 @@ int main(int argc, const char **argv) {
}
doc::Info *I = Reduced.get().get();
-
- auto InfoPath = getInfoOutputFile(OutDirectory, I->Namespace,
- I->extractName(), "." + Format);
+ auto InfoPath = getInfoOutputFile(OutDirectory, I->Path, I->extractName(),
+ "." + Format);
if (!InfoPath) {
llvm::errs() << toString(InfoPath.takeError()) << "\n";
- continue;
+ return 1;
}
std::error_code FileErr;
llvm::raw_fd_ostream InfoOS(InfoPath.get(), FileErr, llvm::sys::fs::F_None);
Modified: clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/HTMLGeneratorTest.cpp Fri Jul 12 11:32:00 2019
@@ -57,7 +57,7 @@ TEST(HTMLGeneratorTest, emitNamespaceHTM
<div>
<h3>OneFunction</h3>
<p>
- OneFunction()
+ OneFunction()
</p>
</div>
<h2>Enums</h2>
@@ -73,14 +73,16 @@ TEST(HTMLGeneratorTest, emitNamespaceHTM
TEST(HTMLGeneratorTest, emitRecordHTML) {
RecordInfo I;
I.Name = "r";
+ I.Path = "X/Y/Z";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
- I.Members.emplace_back("int", "X", AccessSpecifier::AS_private);
+ I.Members.emplace_back("int", "X/Y", "X", AccessSpecifier::AS_private);
I.TagType = TagTypeKind::TTK_Class;
- I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
+ I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record,
+ llvm::SmallString<128>("path/to"));
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
@@ -104,11 +106,13 @@ TEST(HTMLGeneratorTest, emitRecordHTML)
Defined at line 10 of test.cpp
</p>
<p>
- Inherits from F, G
+ Inherits from
+ <a href="../../../path/to/F.html">F</a>
+ , G
</p>
<h2>Members</h2>
<ul>
- <li>private int X</li>
+ <li>private <a href="../int.html">int</a> X</li>
</ul>
<h2>Records</h2>
<ul>
@@ -118,7 +122,7 @@ TEST(HTMLGeneratorTest, emitRecordHTML)
<div>
<h3>OneFunction</h3>
<p>
- OneFunction()
+ OneFunction()
</p>
</div>
<h2>Enums</h2>
@@ -139,8 +143,8 @@ TEST(HTMLGeneratorTest, emitFunctionHTML
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
- I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
- I.Params.emplace_back("int", "P");
+ I.ReturnType = TypeInfo(EmptySID, "float", InfoType::IT_default, "path/to");
+ I.Params.emplace_back("int", "path/to", "P");
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -156,7 +160,10 @@ TEST(HTMLGeneratorTest, emitFunctionHTML
<div>
<h3>f</h3>
<p>
- void f(int P)
+ <a href="path/to/float.html">float</a>
+ f(
+ <a href="path/to/int.html">int</a>
+ P)
</p>
<p>
Defined at line 10 of test.cpp
@@ -261,8 +268,7 @@ TEST(HTMLGeneratorTest, emitCommentHTML)
Brief description.
</p>
<p>
- Extended description that
- continues onto the next line.
+ Extended description that continues onto the next line.
</p>
</div>
</div>
Modified: clang-tools-extra/trunk/unittests/clang-doc/YAMLGeneratorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/YAMLGeneratorTest.cpp?rev=365937&r1=365936&r2=365937&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/YAMLGeneratorTest.cpp (original)
+++ clang-tools-extra/trunk/unittests/clang-doc/YAMLGeneratorTest.cpp Fri Jul 12 11:32:00 2019
@@ -25,6 +25,7 @@ std::unique_ptr<Generator> getYAMLGenera
TEST(YAMLGeneratorTest, emitNamespaceYAML) {
NamespaceInfo I;
I.Name = "Namespace";
+ I.Path = "path/to/A";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace",
@@ -45,6 +46,7 @@ TEST(YAMLGeneratorTest, emitNamespaceYAM
R"raw(---
USR: '0000000000000000000000000000000000000000'
Name: 'Namespace'
+Path: 'path/to/A'
Namespace:
- Type: Namespace
Name: 'A'
@@ -69,15 +71,18 @@ ChildEnums:
TEST(YAMLGeneratorTest, emitRecordYAML) {
RecordInfo I;
I.Name = "r";
+ I.Path = "path/to/r";
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
- I.Members.emplace_back("int", "X", AccessSpecifier::AS_private);
+ I.Members.emplace_back("int", "path/to/int", "X",
+ AccessSpecifier::AS_private);
I.TagType = TagTypeKind::TTK_Class;
- I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
- I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
+ I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "path/to/F");
+ I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
+ "path/to/G");
I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
I.ChildFunctions.emplace_back();
@@ -95,6 +100,7 @@ TEST(YAMLGeneratorTest, emitRecordYAML)
R"raw(---
USR: '0000000000000000000000000000000000000000'
Name: 'r'
+Path: 'path/to/r'
Namespace:
- Type: Namespace
Name: 'A'
@@ -108,14 +114,17 @@ TagType: Class
Members:
- Type:
Name: 'int'
+ Path: 'path/to/int'
Name: 'X'
Access: Private
Parents:
- Type: Record
Name: 'F'
+ Path: 'path/to/F'
VirtualParents:
- Type: Record
Name: 'G'
+ Path: 'path/to/G'
ChildRecords:
- Type: Record
Name: 'ChildStruct'
@@ -139,8 +148,9 @@ TEST(YAMLGeneratorTest, emitFunctionYAML
I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
- I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
- I.Params.emplace_back("int", "P");
+ I.ReturnType =
+ TypeInfo(EmptySID, "void", InfoType::IT_default, "path/to/void");
+ I.Params.emplace_back("int", "path/to/int", "P");
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
@@ -170,10 +180,12 @@ Parent:
Params:
- Type:
Name: 'int'
+ Path: 'path/to/int'
Name: 'P'
ReturnType:
Type:
Name: 'void'
+ Path: 'path/to/void'
...
)raw";
EXPECT_EQ(Expected, Actual.str());
_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list