[clang-tools-extra] r365937 - [clang-doc] Add html links to references
Diego Astiazarán via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 12 15:10:11 PDT 2019
Hi Douglas,
This revision (https://reviews.llvm.org/D64669) should fix that.
On Fri, Jul 12, 2019 at 1:55 PM <douglas.yung at sony.com> wrote:
> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190712/5e0f9951/attachment-0001.html>
More information about the cfe-commits
mailing list