From a7a7330d59e4abfe92801620af0f9a0780890aba Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 27 Nov 2023 12:44:47 -0500 Subject: [PATCH] feat: tranches & overload sets for namespaces --- include/mrdocs/Corpus.hpp | 133 +----- include/mrdocs/Metadata/Interface.hpp | 68 +-- include/mrdocs/Metadata/Overloads.hpp | 7 +- .../asciidoc/layouts/overload-set.adoc.hbs | 4 +- .../partials/declarator-after.adoc.hbs | 8 +- .../partials/declarator-before.adoc.hbs | 14 +- .../asciidoc/partials/declarator-id.adoc.hbs | 6 +- .../asciidoc/partials/declarator.adoc.hbs | 6 +- .../asciidoc/partials/info-list.adoc.hbs | 8 +- .../asciidoc/partials/info-member.adoc.hbs | 9 + .../asciidoc/partials/qualified-path.adoc.hbs | 4 +- .../partials/symbols/enumerator.adoc.hbs | 5 +- .../partials/symbols/function.adoc.hbs | 2 +- .../partials/symbols/namespace.adoc.hbs | 12 +- .../asciidoc/partials/symbols/record.adoc.hbs | 14 +- .../asciidoc/partials/template-arg.adoc.hbs | 4 +- .../asciidoc/partials/template-args.adoc.hbs | 2 +- .../asciidoc/partials/tranche.adoc.hbs | 49 +- src/lib/Metadata/DomMetadata.cpp | 64 ++- src/lib/Metadata/Interface.cpp | 422 ++++++++++-------- 20 files changed, 389 insertions(+), 452 deletions(-) create mode 100644 share/mrdocs/addons/generator/asciidoc/partials/info-member.adoc.hbs diff --git a/include/mrdocs/Corpus.hpp b/include/mrdocs/Corpus.hpp index 0eda5f810..e792e2ba4 100644 --- a/include/mrdocs/Corpus.hpp +++ b/include/mrdocs/Corpus.hpp @@ -134,26 +134,6 @@ class MRDOCS_VISIBLE ScopeInfo const& S, F&& f, Args&&... args) const; - template - void traverseOverloads( - RecordInfo const& I, - F&& f, Args&&... args) const; - - template - void traverseOverloads( - NamespaceInfo const& I, - F&& f, Args&&... args) const; - - template - void traverseOverloads( - EnumInfo const& I, - F&& f, Args&&... args) const; - - template - void traverseOverloads( - SpecializationInfo const& I, - F&& f, Args&&... args) const; - //-------------------------------------------- // KRYSTIAN NOTE: temporary @@ -257,115 +237,22 @@ traverseOverloads( { const Info& member = get(id); const auto& lookup = S.Lookups.at(member.Name); - if(lookup.size() == 1 || member.Name.empty()) + auto first_func = std::ranges::find_if( + lookup, [this](const SymbolID& elem) + { + return get(elem).isFunction(); + }); + if(lookup.size() == 1 || + first_func == lookup.end()) { visit(member, std::forward(f), std::forward(args)...); } - else if(lookup.front() == id) + else if(*first_func == id) { OverloadSet overloads(member.Name, - member.Namespace.front(), lookup); - visit(overloads, std::forward(f), - std::forward(args)...); - } - } -} - -template -void -Corpus:: -traverseOverloads( - RecordInfo const& I, - F&& f, Args&&... args) const -{ - for(const SymbolID& id : I.Members) - { - const Info& member = get(id); - const auto& lookup = I.Lookups.at(member.Name); - if(lookup.size() == 1 || member.Name.empty()) - { - visit(member, std::forward(f), - std::forward(args)...); - } - else if(lookup.front() == id) - { - OverloadSet overloads(member.Name, I.id, lookup); - visit(overloads, std::forward(f), - std::forward(args)...); - } - } -} - -template -void -Corpus:: -traverseOverloads( - NamespaceInfo const& I, - F&& f, Args&&... args) const -{ - for(const SymbolID& id : I.Members) - { - const Info& member = get(id); - const auto& lookup = I.Lookups.at(member.Name); - if(lookup.size() == 1 || member.Name.empty()) - { - visit(member, std::forward(f), - std::forward(args)...); - } - else if(lookup.front() == id) - { - OverloadSet overloads(member.Name, I.id, lookup); - visit(overloads, std::forward(f), - std::forward(args)...); - } - } -} - -template -void -Corpus:: -traverseOverloads( - EnumInfo const& I, - F&& f, Args&&... args) const -{ - for(const SymbolID& id : I.Members) - { - const Info& member = get(id); - const auto& lookup = I.Lookups.at(member.Name); - if(lookup.size() == 1 || member.Name.empty()) - { - visit(member, std::forward(f), - std::forward(args)...); - } - else if(lookup.front() == id) - { - OverloadSet overloads(member.Name, I.id, lookup); - visit(overloads, std::forward(f), - std::forward(args)...); - } - } -} - -template -void -Corpus:: -traverseOverloads( - SpecializationInfo const& I, - F&& f, Args&&... args) const -{ - for(const SymbolID& id : I.Members) - { - const Info& member = get(id); - const auto& lookup = I.Lookups.at(member.Name); - if(lookup.size() == 1 || member.Name.empty()) - { - visit(member, std::forward(f), - std::forward(args)...); - } - else if(lookup.front() == id) - { - OverloadSet overloads(member.Name, I.id, lookup); + member.Namespace.front(), + member.Namespace, lookup); visit(overloads, std::forward(f), std::forward(args)...); } diff --git a/include/mrdocs/Metadata/Interface.hpp b/include/mrdocs/Metadata/Interface.hpp index fc122ca4f..7b81394b7 100644 --- a/include/mrdocs/Metadata/Interface.hpp +++ b/include/mrdocs/Metadata/Interface.hpp @@ -1,10 +1,10 @@ // -// This is a derivative work. originally part of the LLVM Project. // Licensed under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) +// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -23,41 +23,42 @@ namespace clang { namespace mrdocs { +/** A group of children that have the same access specifier. +*/ +struct Tranche +{ + std::vector Namespaces; + std::vector Records; + std::vector Functions; + std::vector Enums; + std::vector Types; + std::vector Fields; + std::vector StaticFunctions; + std::vector Variables; + std::vector Friends; + + ScopeInfo Overloads; + ScopeInfo StaticOverloads; +}; + /** The aggregated interface for a given struct, class, or union. */ class Interface { public: - /** A group of children that have the same access specifier. - */ - struct Tranche - { - std::span Records; - std::span Functions; - std::span Enums; - std::span Types; - std::span Data; - std::span StaticFunctions; - std::span StaticData; - std::span Friends; - }; - Corpus const& corpus; /** The aggregated public interfaces. */ - Tranche Public; + std::shared_ptr Public; /** The aggregated protected interfaces. */ - Tranche Protected; + std::shared_ptr Protected; /** The aggregated private interfaces. */ - Tranche Private; - - ScopeInfo Overloads; - ScopeInfo StaticOverloads; + std::shared_ptr Private; MRDOCS_DECL friend @@ -67,18 +68,7 @@ class Interface Corpus const& corpus); private: - class Build; - explicit Interface(Corpus const&) noexcept; - - std::vector records_; - std::vector functions_; - std::vector enums_; - std::vector types_; - std::vector data_; - std::vector staticfuncs_; - std::vector staticdata_; - std::vector friends_; }; //------------------------------------------------ @@ -99,6 +89,20 @@ makeInterface( RecordInfo const& Derived, Corpus const& corpus); +/** Return a tranche representing the members of a namespace. + + @return The tranche. + + @param Derived The namespace to build the tranche for. + + @param corpus The complete metadata. +*/ +MRDOCS_DECL +Tranche +makeTranche( + NamespaceInfo const& Namespace, + Corpus const& corpus); + } // mrdocs } // clang diff --git a/include/mrdocs/Metadata/Overloads.hpp b/include/mrdocs/Metadata/Overloads.hpp index 4c537a155..dd83a3dda 100644 --- a/include/mrdocs/Metadata/Overloads.hpp +++ b/include/mrdocs/Metadata/Overloads.hpp @@ -1,10 +1,9 @@ // -// This is a derivative work. originally part of the LLVM Project. // Licensed under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) +// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -27,14 +26,18 @@ struct OverloadSet SymbolID Parent; + std::span Namespace; + std::span Members; OverloadSet( std::string_view name, const SymbolID& parent, + std::span ns, std::span members) : Name(name) , Parent(parent) + , Namespace(ns) , Members(members) { } diff --git a/share/mrdocs/addons/generator/asciidoc/layouts/overload-set.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/layouts/overload-set.adoc.hbs index 3615a8218..5c7206018 100644 --- a/share/mrdocs/addons/generator/asciidoc/layouts/overload-set.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/layouts/overload-set.adoc.hbs @@ -1,7 +1,9 @@ {{#if relfileprefix}}:relfileprefix: {{relfileprefix}}{{/if}} [#{{#if (is_multipage)}}{{symbol.id}}{{else}}{{symbol.ref}}{{/if}}] -== {{#if symbol.name}}Overload set {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}}{{else}}Unnamed overload set{{/if}} += {{#if symbol.name}}Overload set {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}}{{else}}Unnamed overload set{{/if}} + +== Members {{#each symbol.members as | member |}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/declarator-after.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/declarator-after.adoc.hbs index 332053402..2b2f27f95 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/declarator-after.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/declarator-after.adoc.hbs @@ -1,15 +1,15 @@ {{#if pointee-type~}} {{#if (or (eq pointee-type.kind "array") (eq pointee-type.kind "function"))}}){{/if~}} - {{~>declarator-after pointee-type~}} + {{~>declarator-after pointee-type nolink=nolink~}} {{else if (eq kind "array")~}} [{{bounds-value}}] - {{~>declarator-after element-type~}} + {{~>declarator-after element-type nolink=nolink~}} {{else if (eq kind "function")~}} ({{#each param-types~}} - {{~>declarator~}}{{~#unless @last}}, {{/unless~}} + {{~>declarator nolink=../nolink~}}{{~#unless @last}}, {{/unless~}} {{/each~}}) {{~#if cv-qualifiers}} {{cv-qualifiers}}{{/if~}} {{#if (eq ref-qualifier "lvalue")}} &{{else if (eq ref-qualifier "rvalue")}} &&{{/if~}} {{#if exception-spec}} {{exception-spec}}{{/if~}} - {{~>declarator-after return-type~}} + {{~>declarator-after return-type nolink=nolink~}} {{/if}} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/declarator-before.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/declarator-before.adoc.hbs index 68f61c796..ccfb40f19 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/declarator-before.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/declarator-before.adoc.hbs @@ -1,10 +1,10 @@ {{#if pointee-type~}} - {{~>declarator-before pointee-type~}} + {{~>declarator-before pointee-type nolink=nolink~}} {{#if (or (eq pointee-type.kind "array") (eq pointee-type.kind "function"))}}({{/if~}} {{~/if~}} -{{#if element-type~}}{{~>declarator-before element-type~}}{{/if~}} -{{#if return-type~}}{{~>declarator-before return-type~}}{{/if~}} -{{#if parent-type~}}{{>declarator parent-type}}::{{/if~}} +{{#if element-type~}}{{~>declarator-before element-type nolink=nolink~}}{{/if~}} +{{#if return-type~}}{{~>declarator-before return-type nolink=nolink~}}{{/if~}} +{{#if parent-type~}}{{>declarator parent-type nolink=nolink}}::{{/if~}} {{#if (eq kind "lvalue-reference")}}&{{/if~}} {{#if (eq kind "rvalue-reference")}}&&{{/if~}} {{#if (eq kind "pointer")}}*{{/if~}} @@ -12,11 +12,11 @@ {{#if cv-qualifiers~}} {{#if pointee-type}} {{cv-qualifiers}}{{else}}{{cv-qualifiers}} {{/if~}} {{/if~}} -{{#if symbol~}} - {{#if (not parent-type)}}{{>qualified-path symbol=symbol.parent}}{{/if~}} +{{#if (and symbol (not parent-type))}}{{>qualified-path symbol=symbol.parent nolink=nolink}}{{/if~}} +{{#if (and symbol (not nolink))~}} xref:{{symbol.ref}}[{{name}}] {{~else if name}}{{name~}} {{/if~}} {{#if (eq kind "decltype")}}decltype({{operand}}){{/if~}} -{{#if (eq kind "specialization")}}{{>template-args args=args}}{{/if~}} +{{#if (eq kind "specialization")}}{{>template-args args=args nolink=nolink}}{{/if~}} {{#if is-pack~}}...{{/if}} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/declarator-id.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/declarator-id.adoc.hbs index 2bbca8020..2a6c9266c 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/declarator-id.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/declarator-id.adoc.hbs @@ -1,8 +1,8 @@ {{#if (and (eq kind "function") (eq class "conversion"))~}} - operator {{>declarator return~}} + operator {{>declarator return nolink=nolink~}} {{else~}} - {{#if link.ref}}xref:{{link.ref}}[{{name}}]{{else}}{{name}}{{/if~}} + {{#if (and link.ref (not nolink))}}xref:{{link.ref}}[{{name}}]{{else}}{{name}}{{/if~}} {{#if (or (eq template.kind "explicit") (eq template.kind "partial"))~}} - {{>template-args args=template.args~}} + {{>template-args args=template.args nolink=nolink~}} {{/if~}} {{/if}} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/declarator.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/declarator.adoc.hbs index e52afcfbb..bbef8fdfe 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/declarator.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/declarator.adoc.hbs @@ -1,5 +1,5 @@ -{{>declarator-before~}} +{{>declarator-before nolink=nolink~}} {{~#if decl-name}} {{decl-name~}} -{{~#if decl-name-targs~}}{{>template-args args=decl-name-targs}}{{~/if~}} +{{~#if decl-name-targs~}}{{>template-args args=decl-name-targs nolink=nolink}}{{~/if~}} {{~/if~}} -{{~>declarator-after}} \ No newline at end of file +{{~>declarator-after nolink=nolink}} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/info-list.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/info-list.adoc.hbs index 3c36dd54e..ae1d2100a 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/info-list.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/info-list.adoc.hbs @@ -1,8 +1,10 @@ +{{#if members}} +== {{title}} [,cols=2] |=== |Name |Description -{{#each .}} -|xref:{{ref}}[`pass:v[{{name}}]`] | {{#if (ne kind "overload")}}{{doc.brief}}{{else}}{{#each (unique (pluck (pluck members "doc") "brief"))}}{{.}} -{{/each}}{{/if}} +{{#each members}} +{{>info-member .}} {{/each}} |=== +{{/if}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/info-member.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/info-member.adoc.hbs new file mode 100644 index 000000000..70c7d2b2c --- /dev/null +++ b/share/mrdocs/addons/generator/asciidoc/partials/info-member.adoc.hbs @@ -0,0 +1,9 @@ +{{!-- |xref:{{ref}}[`pass:v[{{name}}]`] | --}} +|xref:{{ref}}[`pass:v[{{>declarator-id . nolink=true}}]`] | +{{#if (ne kind "overload")~}} + {{~doc.brief}} +{{else~}} + {{#each (unique (pluck (pluck members "doc") "brief"))~}} + {{.}} + {{/each~}} +{{/if}} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/qualified-path.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/qualified-path.adoc.hbs index 391f36cfa..466a25acb 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/qualified-path.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/qualified-path.adoc.hbs @@ -1,7 +1,7 @@ {{#unless (contains @root.symbol.namespace symbol)~}} {{#if symbol.parent~}} -{{>qualified-path symbol=symbol.parent~}} +{{>qualified-path symbol=symbol.parent nolink=nolink~}} {{else~}} {{/if~}} -{{#if symbol.name}}xref:{{symbol.ref}}[{{symbol.name}}]::{{/if~}} +{{#if symbol.name}}{{#if (not nolink)}}xref:{{symbol.ref}}[{{symbol.name}}]{{else}}{{symbol.name}}{{/if}}::{{/if~}} {{/unless}} \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/enumerator.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/symbols/enumerator.adoc.hbs index 08a113038..6c56ef2a4 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/symbols/enumerator.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/symbols/enumerator.adoc.hbs @@ -1,5 +1,5 @@ {{!-- enumerator --}} -= {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}} += Enumerator {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}} {{symbol.doc.brief}} @@ -9,7 +9,8 @@ [source,cpp,subs="verbatim,macros,-callouts"] ---- -{{>signature/enumerator symbol=symbol}}; +{{>signature/enumerator symbol=symbol}} + ---- {{#if symbol.doc.description}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/function.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/symbols/function.adoc.hbs index cf8227247..fcf0e3280 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/symbols/function.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/symbols/function.adoc.hbs @@ -1,5 +1,5 @@ {{!-- function --}} -= {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}} += Function {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}} {{symbol.doc.brief}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/namespace.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/symbols/namespace.adoc.hbs index 6fdfd1f31..bb94e909e 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/symbols/namespace.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/symbols/namespace.adoc.hbs @@ -1,14 +1,4 @@ {{!-- namespace --}} = {{#if symbol.name}}Namespace {{>nested-name-specifier symbol=symbol.parent}}{{symbol.name}}{{else if symbol.parent}}Unnamed namespace{{else}}Global namespace{{/if}} -{{#each (group_by symbol.members "kind")}} -== {{#if (eq @key "record")}}Types{{else if (eq @key "variable")}}Constants{{else}}{{capitalize @key}}s{{/if}} - -[,cols=2] -|=== -|Name |Description -{{#each (sort_by . "name")}} -|xref:{{ref}}[`pass:v[{{name}}]`] |{{doc.brief}} -{{/each}} -|=== -{{/each}} +{{> tranche tranche=symbol.interface label="" is-namespace=true}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/symbols/record.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/symbols/record.adoc.hbs index 8aac00d5b..952a126e7 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/symbols/record.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/symbols/record.adoc.hbs @@ -13,17 +13,9 @@ ---- {{#with symbol.interface}} -{{#if overloads}} -== Member Functions -{{>info-list overloads}} -{{/if}} -{{#if static-overloads}} -== Static Member Functions -{{>info-list static-overloads}} -{{/if}} -{{> tranche tranche=public label=""}} -{{> tranche tranche=protected label="Protected"}} -{{> tranche tranche=private label="Private"}} +{{> tranche tranche=public label="" is-namespace=false}} +{{> tranche tranche=protected label="Protected" is-namespace=false}} +{{> tranche tranche=private label="Private" is-namespace=false}} {{/with}} {{#if symbol.doc.description}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/template-arg.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/template-arg.adoc.hbs index be16d6847..130b144a0 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/template-arg.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/template-arg.adoc.hbs @@ -1,8 +1,8 @@ {{#if (eq kind "type")~}} -{{~>declarator type~}} +{{~>declarator type nolink=nolink~}} {{else if (eq kind "non-type")~}} {{~value~}} {{else if (eq kind "template")~}} -{{#if template}}xref:{{template.ref}}[{{name~}}]{{else~}}{{name~}}{{/if~}} +{{#if (and template (not nolink))}}xref:{{template.ref}}[{{name~}}]{{else~}}{{name~}}{{/if~}} {{/if~}} {{~#if is-pack}}...{{/if~}} diff --git a/share/mrdocs/addons/generator/asciidoc/partials/template-args.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/template-args.adoc.hbs index 8596dc941..4a86d8c00 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/template-args.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/template-args.adoc.hbs @@ -1,4 +1,4 @@ <{{~#each args~}} -{{~>template-arg .~}} +{{~>template-arg nolink=../nolink~}} {{~#if (not @last)}}, {{/if~}} {{~/each~}}> \ No newline at end of file diff --git a/share/mrdocs/addons/generator/asciidoc/partials/tranche.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/tranche.adoc.hbs index 843740d6d..78ae69483 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/tranche.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/tranche.adoc.hbs @@ -1,40 +1,13 @@ -{{#if tranche.records}} -== {{label}} Types -{{>info-list tranche.records}} -{{/if}} -{{#if tranche.types}} -{{#if label}} -== {{label}} Types +{{>info-list members=tranche.namespaces title="Namespaces"}} +{{>info-list members=(concat tranche.records tranche.types) title=(concat label " " "Types")}} +{{>info-list members=tranche.enums title=(concat label " " "Enums")}} +{{#if is-namespace}} +{{>info-list members=tranche.overloads title="Functions"}} +{{>info-list members=tranche.variables title="Variables"}} {{else}} -== Types -{{/if}} -{{>info-list tranche.types}} -{{/if}} -{{!-- -{{#if tranche.functions}} -== {{label}} Member Functions -{{>info-list tranche.functions}} -{{/if}} ---}} -{{#if tranche.enums}} -== {{label}} Enums -{{>info-list tranche.enums}} -{{/if}} -{{#if tranche.fields}} -== {{label}} Data Members -{{>info-list tranche.fields}} -{{/if}} -{{#if tranche.staticfunctions}} -== {{label}} Static Member Functions -{{>info-list tranche.staticfunctions}} -{{/if}} -{{!-- -{{#if tranche.staticdata}} -== {{label}} Static Data Members -{{>info-list tranche.staticdata}} -{{/if}} ---}} -{{#if tranche.friends}} -== {{label}} Friends -{{>info-list tranche.friends}} +{{>info-list members=tranche.overloads title=(concat label " " "Member Functions")}} +{{>info-list members=tranche.staticoverloads title=(concat label " " "Static Member Functions")}} +{{>info-list members=tranche.fields title=(concat label " " "Data Members")}} +{{>info-list members=tranche.variables title=(concat label " " "Static Data Members")}} +{{>info-list members=tranche.friends title=(concat label " " "Friends")}} {{/if}} diff --git a/src/lib/Metadata/DomMetadata.cpp b/src/lib/Metadata/DomMetadata.cpp index c7a9042a4..cfd5cde7f 100644 --- a/src/lib/Metadata/DomMetadata.cpp +++ b/src/lib/Metadata/DomMetadata.cpp @@ -80,6 +80,8 @@ domCreate( { "name", overloads.Name }, { "members", dom::newArray( overloads.Members, domCorpus) }, + { "namespace", dom::newArray( + overloads.Namespace, domCorpus) }, { "parent", domCorpus.get(overloads.Parent) } }); } @@ -529,13 +531,13 @@ class DomBaseArray : public dom::ArrayImpl template class DomTrancheArray : public dom::ArrayImpl { - std::span list_; + std::span list_; std::shared_ptr sp_; DomCorpus const& domCorpus_; public: DomTrancheArray( - std::span list, + std::span list, std::shared_ptr const& sp, DomCorpus const& domCorpus) : list_(list) @@ -558,37 +560,44 @@ class DomTrancheArray : public dom::ArrayImpl class DomTranche : public dom::DefaultObjectImpl { - std::shared_ptr sp_; - Interface::Tranche const& tranche_; + std::shared_ptr tranche_; DomCorpus const& domCorpus_; - template static dom::Value init( - std::span list, - std::shared_ptr const& sp, + std::span list, DomCorpus const& domCorpus) { - return dom::newArray>(list, sp, domCorpus); + return dom::newArray(list, domCorpus); + } + + static + dom::Value + init( + const ScopeInfo& scope, + DomCorpus const& domCorpus) + { + return dom::newArray(scope, domCorpus); } public: DomTranche( - Interface::Tranche const& tranche, - std::shared_ptr const& sp, + std::shared_ptr const& tranche, DomCorpus const& domCorpus) noexcept : dom::DefaultObjectImpl({ - { "records", init(tranche.Records, sp, domCorpus) }, - { "functions", init(tranche.Functions, sp, domCorpus) }, - { "enums", init(tranche.Enums, sp, domCorpus) }, - { "types", init(tranche.Types, sp, domCorpus) }, - { "field", init(tranche.Data, sp, domCorpus) }, - { "staticfuncs",init(tranche.StaticFunctions, sp, domCorpus) }, - { "staticdata", init(tranche.StaticData, sp, domCorpus) }, - { "friends", init(tranche.Friends, sp, domCorpus) } + { "namespaces", init(tranche->Namespaces, domCorpus) }, + { "records", init(tranche->Records, domCorpus) }, + { "functions", init(tranche->Functions, domCorpus) }, + { "enums", init(tranche->Enums, domCorpus) }, + { "types", init(tranche->Types, domCorpus) }, + { "fields", init(tranche->Fields, domCorpus) }, + { "staticfuncs", init(tranche->StaticFunctions, domCorpus) }, + { "variables", init(tranche->Variables, domCorpus) }, + { "friends", init(tranche->Friends, domCorpus) }, + { "overloads", init(tranche->Overloads, domCorpus) }, + { "staticoverloads", init(tranche->StaticOverloads, domCorpus) } }) - , sp_(sp) , tranche_(tranche) , domCorpus_(domCorpus) { @@ -615,11 +624,11 @@ class DomInterface : public dom::LazyObjectImpl { sp_ = std::make_shared(makeInterface(I_, *domCorpus_)); return dom::Object({ - { "public", dom::newObject(sp_->Public, sp_, domCorpus_) }, - { "protected", dom::newObject(sp_->Protected, sp_, domCorpus_) }, - { "private", dom::newObject(sp_->Private, sp_, domCorpus_) }, - { "overloads", dom::newArray(sp_->Overloads, domCorpus_) }, - { "static-overloads", dom::newArray(sp_->StaticOverloads, domCorpus_) } + { "public", dom::newObject(sp_->Public, domCorpus_) }, + { "protected", dom::newObject(sp_->Protected, domCorpus_) }, + { "private", dom::newObject(sp_->Private, domCorpus_) }, + // { "overloads", dom::newArray(sp_->Overloads, domCorpus_) }, + // { "static-overloads", dom::newArray(sp_->StaticOverloads, domCorpus_) } }); } }; @@ -698,6 +707,13 @@ DomInfo::construct() const { entries.emplace_back("loc", domCreate(I_)); } + if constexpr(T::isNamespace()) + { + entries.emplace_back("interface", dom::newObject( + std::make_shared( + makeTranche(I_, *domCorpus_)), + domCorpus_)); + } if constexpr(T::isRecord()) { entries.insert(entries.end(), { diff --git a/src/lib/Metadata/Interface.cpp b/src/lib/Metadata/Interface.cpp index 340b82518..89e442231 100644 --- a/src/lib/Metadata/Interface.cpp +++ b/src/lib/Metadata/Interface.cpp @@ -1,10 +1,10 @@ // -// This is a derivative work. originally part of the LLVM Project. // Licensed under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) +// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -28,34 +28,90 @@ namespace clang { namespace mrdocs { -//------------------------------------------------ +namespace { -class Interface::Build +class TrancheBuilder { - Interface& I_; - Corpus const& corpus_; - bool includePrivate_; - - template - using Table = std::vector< - std::pair>; - - Table records_; - Table functions_; - Table enums_; - Table types_; - Table data_; - Table staticfuncs_; - Table staticdata_; - Table friends_; - - void addOverload(const FunctionInfo& F, ScopeInfo& S) + const Corpus& corpus_; + const Info& parent_; + Tranche* none_; + Tranche* public_; + Tranche* protected_; + Tranche* private_; + + bool includePrivate_ = true; + + Tranche* trancheFor(AccessKind access) + { + switch(access) + { + case AccessKind::Public: + return public_; + case AccessKind::Protected: + return protected_; + case AccessKind::Private: + return private_; + case AccessKind::None: + return none_; + default: + MRDOCS_UNREACHABLE(); + } + } + + void + push( + ScopeInfo& S, + const Info& I) + { + if(std::ranges::find(S.Members, I.id) == S.Members.end()) + S.Members.emplace_back(I.id); + auto& lookups = S.Lookups.try_emplace(I.Name).first->second; + if(std::ranges::find(lookups, I.id) == lookups.end()) + lookups.emplace_back(I.id); + } + + void + push( + std::vector& M, + const Info& I) { - if(std::ranges::find(S.Members, F.id) == S.Members.end()) - S.Members.emplace_back(F.id); - auto& lookups = S.Lookups.try_emplace(F.Name).first->second; - if(std::ranges::find(lookups, F.id) == lookups.end()) - lookups.emplace_back(F.id); + M.emplace_back(I.id); + } + + template + void + push( + ListTy Tranche::* list, + AccessKind access, + const Info& member) + { + if(Tranche* tranche = trancheFor(access)) + push(tranche->*list, member); + } + + static + AccessKind + effectiveAccess( + AccessKind memberAccess, + AccessKind baseAccess) noexcept + { + if(memberAccess == AccessKind::None || + baseAccess == AccessKind::None) + return AccessKind::None; + if(memberAccess == AccessKind::Private || + baseAccess == AccessKind::Private) + return AccessKind::Private; + if(memberAccess == AccessKind::Protected || + baseAccess == AccessKind::Protected) + return AccessKind::Protected; + return AccessKind::Public; + } + + bool + isFromParent(const Info& I) + { + return ! I.Namespace.empty() && + I.Namespace.front() == parent_.id; } const Info* @@ -86,48 +142,44 @@ class Interface::Build } public: - Build( - Interface& I, - RecordInfo const& Derived, - Corpus const& corpus) noexcept - : I_(I) - , corpus_(corpus) + TrancheBuilder( + const Corpus& corpus, + const Info& Parent, + Tranche* None, + Tranche* Public, + Tranche* Protected, + Tranche* Private) + : corpus_(corpus) + , parent_(Parent) + , none_(None) + , public_(Public) + , protected_(Protected) + , private_(Private) { auto& config = static_cast< ConfigImpl const&>(corpus_.config); includePrivate_ = config->inaccessibleMembers != ConfigImpl::SettingsImpl::ExtractPolicy::Never; - // treat `Derived` as a public base, - append(AccessKind::Public, Derived, true); - - finish(); } -private: - static - AccessKind - effectiveAccess( - AccessKind memberAccess, - AccessKind baseAccess) noexcept + void + add( + const SymbolID& id, + AccessKind baseAccess) { - if(memberAccess == AccessKind::Private || - baseAccess == AccessKind::Private) - return AccessKind::Private; - if(memberAccess == AccessKind::Protected || - baseAccess == AccessKind::Protected) - return AccessKind::Protected; - return AccessKind::Public; + const auto& I = corpus_.get(id); + auto actualAccess = effectiveAccess(I.Access, baseAccess); + visit(I, *this, actualAccess); } void - append( - AccessKind access, - RecordInfo const& From, - bool isDerived) + addFrom( + const RecordInfo& I, + AccessKind baseAccess) { - for(auto const& B : From.Bases) + for(auto const& B : I.Bases) { - auto actualAccess = effectiveAccess(access, B.Access); + auto actualAccess = effectiveAccess(baseAccess, B.Access); if( ! includePrivate_ && actualAccess == AccessKind::Private) @@ -136,150 +188,143 @@ class Interface::Build getTypeAsTag(B.Type)); if(! Base || ! Base->isRecord()) continue; + addFrom(*static_cast< + const RecordInfo*>(Base), actualAccess); + } + for(auto const& id : I.Members) + add(id, baseAccess); + } + + void addFrom(const NamespaceInfo& I) + { + for(auto const& id : I.Members) + add(id, AccessKind::None); + } + + void operator()( + const NamespaceInfo& I, + AccessKind access) + { + push(&Tranche::Namespaces, access, I); + } + + void operator()( + const RecordInfo& I, + AccessKind access) + { + push(&Tranche::Records, access, I); + } + + void operator()( + const SpecializationInfo& I, + AccessKind access) + { + // KRYSTIAN FIXME: currently unimplemented + } + + void operator()( + const FunctionInfo& I, + AccessKind access) + { + // do not inherit constructors, destructors, + // or deduction guides + if(parent_.isRecord() && ! isFromParent(I) && + (I.Class == FunctionClass::Constructor || + I.Class == FunctionClass::Destructor || + I.Class == FunctionClass::Deduction)) + return; - append(actualAccess, *static_cast< - const RecordInfo*>(Base), false); + bool isStatic = I.specs0.storageClass == StorageClassKind::Static; + if(! parent_.isRecord() || ! isStatic) + { + push(&Tranche::Functions, access, I); + push(&Tranche::Overloads, access, I); } - for(auto const& id : From.Members) + else if(isStatic) { - const auto& I = corpus_.get(id); - auto actualAccess = effectiveAccess(access, I.Access); - if(I.Kind == InfoKind::Function) - { - const auto& F = static_cast(I); - // do not inherit constructors, destructors, - // or deduction guides - if(!isDerived && - (F.Class == FunctionClass::Constructor || - F.Class == FunctionClass::Destructor || - F.Class == FunctionClass::Deduction)) - continue; - auto const isRecFinal = From.specs.isFinal.get(); - if( includePrivate_ || - actualAccess != AccessKind::Private || ( - ! isRecFinal && F.specs0.isVirtual)) - { - if(F.specs0.storageClass == StorageClassKind::Static) - { - addOverload(F, I_.StaticOverloads); - staticfuncs_.push_back({ actualAccess, &F }); - } - else - { - addOverload(F, I_.Overloads); - functions_.push_back({ actualAccess, &F }); - } - } - continue; - } - else if(! includePrivate_ && - actualAccess == AccessKind::Private) - { - continue; - } - switch(I.Kind) - { - case InfoKind::Enum: - enums_.push_back({ actualAccess, - static_cast(&I) }); - break; - case InfoKind::Field: - data_.push_back({ actualAccess, - static_cast(&I) }); - break; - case InfoKind::Record: - records_.push_back({ actualAccess, - static_cast(&I) }); - break; - case InfoKind::Typedef: - types_.push_back({ actualAccess, - static_cast(&I) }); - break; - case InfoKind::Variable: - staticdata_.push_back({ actualAccess, - static_cast(&I) }); - break; - case InfoKind::Friend: - friends_.push_back({ actualAccess, - static_cast(&I) }); - break; - default: - MRDOCS_UNREACHABLE(); - } + push(&Tranche::StaticFunctions, access, I); + push(&Tranche::StaticOverloads, access, I); } } - template - void - sort( - std::span Interface::Tranche::*member, - std::vector& dest, - Table& src) + void operator()( + const TypedefInfo& I, + AccessKind access) { - std::ranges::stable_sort( - src, - []( auto const& p0, - auto const& p1) noexcept - { - return - to_underlying(p0.first) < - to_underlying(p1.first); - }); - dest.resize(0); - dest.reserve(src.size()); - for(auto const& v : src) - dest.push_back(v.second); - - auto it0 = src.begin(); - auto it = std::find_if_not( - it0, src.end(), - [](auto const& p) noexcept - { - return p.first == AccessKind::Public; - }); - std::size_t const nPublic = it - it0; - it0 = it; - it = std::find_if_not( - it0, src.end(), - [](auto const& p) noexcept - { - return p.first == AccessKind::Protected; - }); - std::size_t const nPrivate = src.end() - it; -//MRDOCS_ASSERT(nPrivate == 0); - I_.Public.*member = { dest.begin(), dest.begin() + nPublic }; - I_.Protected.*member = { dest.begin() + nPublic, dest.end() - nPrivate }; - I_.Private.*member = { dest.end() - nPrivate, dest.end() }; + push(&Tranche::Types, access, I); } - void - finish() + void operator()( + const EnumInfo& I, + AccessKind access) + { + push(&Tranche::Enums, access, I); + } + + void operator()( + const FieldInfo& I, + AccessKind access) + { + push(&Tranche::Fields, access, I); + } + + void operator()( + const VariableInfo& I, + AccessKind access) + { + push(&Tranche::Variables, access, I); + } + + void operator()( + const FriendInfo& I, + AccessKind access) { - sort(&Interface::Tranche::Records, I_.records_, records_); - sort(&Interface::Tranche::Functions, I_.functions_, functions_); - sort(&Interface::Tranche::Enums, I_.enums_, enums_); - sort(&Interface::Tranche::Types, I_.types_, types_); - sort(&Interface::Tranche::Data, I_.data_, data_); - sort(&Interface::Tranche::StaticFunctions, I_.staticfuncs_,staticfuncs_); - sort(&Interface::Tranche::StaticData, I_.staticdata_, staticdata_); - sort(&Interface::Tranche::Friends, I_.friends_, friends_); -#if 0 -MRDOCS_ASSERT(I_.Private.Records.empty()); -MRDOCS_ASSERT(I_.Private.Functions.empty()); -MRDOCS_ASSERT(I_.Private.Enums.empty()); -MRDOCS_ASSERT(I_.Private.Types.empty()); -MRDOCS_ASSERT(I_.Private.Data.empty()); -MRDOCS_ASSERT(I_.Private.StaticFunctions.empty()); -MRDOCS_ASSERT(I_.Private.StaticData.empty()); -#endif + push(&Tranche::Friends, access, I); + } + + void operator()( + const EnumeratorInfo& I, + AccessKind access) + { + // KRYSTIAN FIXME: currently unimplemented } }; +void +buildTranches( + const Corpus& corpus, + const Info& I, + Tranche* None, + Tranche* Public, + Tranche* Protected, + Tranche* Private) +{ + TrancheBuilder builder( + corpus, + I, + None, + Public, + Protected, + Private); + visit(I, [&](const InfoTy& II) + { + if constexpr(InfoTy::isRecord()) + builder.addFrom(II, AccessKind::Public); + if constexpr(InfoTy::isNamespace()) + builder.addFrom(II); + }); +} + +} // (anon) + Interface:: Interface( Corpus const& corpus_) noexcept : corpus(corpus_) { + Public = std::make_shared(); + Protected = std::make_shared(); + Private = std::make_shared(); } Interface @@ -288,9 +333,22 @@ makeInterface( Corpus const& corpus) { Interface I(corpus); - Interface::Build(I, Derived, corpus); + buildTranches(corpus, Derived, nullptr, + I.Public.get(), I.Protected.get(), I.Private.get()); return I; } +Tranche +makeTranche( + NamespaceInfo const& Namespace, + Corpus const& corpus) +{ + Tranche T; + buildTranches(corpus, Namespace, &T, + nullptr, nullptr, nullptr); + return T; +} + + } // mrdocs } // clang