From cea7b46d67203f2f00f33a995f09f509a8ae23dd Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Fri, 21 Apr 2023 06:00:24 -0700 Subject: [PATCH] refactor function overloads --- include/mrdox/Corpus.hpp | 20 ++ include/mrdox/Metadata.hpp | 1 + include/mrdox/MetadataFwd.hpp | 2 + .../FunctionOverloads.hpp} | 29 ++- include/mrdox/meta/Info.hpp | 2 + include/mrdox/meta/Scope.hpp | 14 +- source/lib/Corpus.cpp | 90 ++++++++ source/lib/ast/FrontendAction.cpp | 7 - source/lib/format/asciidoc/Asciidoc.cpp | 204 ++---------------- source/lib/format/asciidoc/Asciidoc.hpp | 8 +- source/lib/format/asciidoc/PagesBuilder.cpp | 137 ++++++++++++ source/lib/format/asciidoc/PagesBuilder.hpp | 55 +++++ .../FunctionOverloads.cpp} | 37 ++-- source/lib/meta/Namespace.cpp | 2 + source/lib/meta/Record.cpp | 1 + 15 files changed, 383 insertions(+), 226 deletions(-) rename include/mrdox/{format/OverloadSet.hpp => meta/FunctionOverloads.hpp} (56%) create mode 100644 source/lib/format/asciidoc/PagesBuilder.cpp create mode 100644 source/lib/format/asciidoc/PagesBuilder.hpp rename source/lib/{format/OverloadSet.cpp => meta/FunctionOverloads.cpp} (65%) diff --git a/include/mrdox/Corpus.hpp b/include/mrdox/Corpus.hpp index 3a919aaee..649ecd93e 100644 --- a/include/mrdox/Corpus.hpp +++ b/include/mrdox/Corpus.hpp @@ -38,6 +38,17 @@ class Corpus } public: + struct Visitor + { + virtual ~Visitor() = default; + virtual void visit(NamespaceInfo const&) {} + virtual void visit(RecordInfo const&) {} + virtual void visit(FunctionOverloads const&) {} + virtual void visit(FunctionInfo const&) {} + virtual void visit(EnumInfo const&) {} + virtual void visit(TypedefInfo const&) {} + }; + //-------------------------------------------- // // Observers @@ -135,6 +146,15 @@ class Corpus return allSymbols_; } + /** Visit the specified symbol ID or node. + */ + /** @{ */ + void visit(SymbolID id, Visitor& f) const; + void visit(Scope const& I, Visitor& f) const; + void visitWithOverloads(Scope const& I, Visitor& f) const; + void visit(Info const& I, Visitor& f) const; + /** @} */ + //-------------------------------------------- // // Modifiers diff --git a/include/mrdox/Metadata.hpp b/include/mrdox/Metadata.hpp index f3122adb5..7ab6206fa 100644 --- a/include/mrdox/Metadata.hpp +++ b/include/mrdox/Metadata.hpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/include/mrdox/MetadataFwd.hpp b/include/mrdox/MetadataFwd.hpp index 75143a6e6..e2c3ab271 100644 --- a/include/mrdox/MetadataFwd.hpp +++ b/include/mrdox/MetadataFwd.hpp @@ -25,6 +25,8 @@ struct EnumValueInfo; struct EnumInfo; struct FieldTypeInfo; struct FunctionInfo; +struct FunctionOverloads; +struct FunctionOverloadsSet; struct Index; struct Info; struct Javadoc; diff --git a/include/mrdox/format/OverloadSet.hpp b/include/mrdox/meta/FunctionOverloads.hpp similarity index 56% rename from include/mrdox/format/OverloadSet.hpp rename to include/mrdox/meta/FunctionOverloads.hpp index 606ae10e0..d12b8da87 100644 --- a/include/mrdox/format/OverloadSet.hpp +++ b/include/mrdox/meta/FunctionOverloads.hpp @@ -9,12 +9,12 @@ // Official repository: https://github.com/cppalliance/mrdox // -#ifndef MRDOX_META_OVERLOADSET_HPP -#define MRDOX_META_OVERLOADSET_HPP +#ifndef MRDOX_META_FUNCTIONOVERLOADS_HPP +#define MRDOX_META_FUNCTIONOVERLOADS_HPP #include +#include #include -#include namespace clang { namespace mrdox { @@ -22,17 +22,32 @@ namespace mrdox { class Corpus; struct Scope; -struct OverloadSet +/** A list of overloads for one function name. +*/ +struct FunctionOverloads { llvm::StringRef name; std::vector list; }; -std::vector -makeOverloadSet( +/** A set of unique function names in a scope +*/ +struct FunctionOverloadsSet +{ + /** The access control of this scope. + */ + AccessSpecifier access; + + /** The list of function overloads in the scope. + */ + std::vector list; +}; + +FunctionOverloadsSet +makeFunctionOverloadsSet( Corpus const& corpus, Scope const& scope, - std::function filter); + AccessSpecifier access); } // mrdox } // clang diff --git a/include/mrdox/meta/Info.hpp b/include/mrdox/meta/Info.hpp index 2b1a4424e..177e883c2 100644 --- a/include/mrdox/meta/Info.hpp +++ b/include/mrdox/meta/Info.hpp @@ -53,6 +53,8 @@ struct Info // generated file will be saved llvm::SmallString<128> Path; + llvm::SmallString<128> mangledName; + //-------------------------------------------- virtual ~Info() = default; diff --git a/include/mrdox/meta/Scope.hpp b/include/mrdox/meta/Scope.hpp index 16bec9377..5466ff0e5 100644 --- a/include/mrdox/meta/Scope.hpp +++ b/include/mrdox/meta/Scope.hpp @@ -12,8 +12,9 @@ #ifndef MRDOX_META_SCOPE_HPP #define MRDOX_META_SCOPE_HPP -#include +#include #include +#include #include namespace clang { @@ -23,6 +24,8 @@ namespace mrdox { */ struct Scope { + bool isNamespaceScope = true; + // Namespaces and Records are references because they will be properly // documented in their own info, while the entirety of Functions and Enums are // included here because they should not have separate documentation from @@ -33,8 +36,15 @@ struct Scope std::vector Namespaces; std::vector Records; std::vector Functions; - std::vector Enums; std::vector Typedefs; + std::vector Enums; + + explicit + Scope( + bool isNamespaceScope_) noexcept + : isNamespaceScope(isNamespaceScope_) + { + } }; } // mrdox diff --git a/source/lib/Corpus.cpp b/source/lib/Corpus.cpp index 39cf57a50..7c0c00164 100644 --- a/source/lib/Corpus.cpp +++ b/source/lib/Corpus.cpp @@ -79,6 +79,96 @@ exists(SymbolID const& id) const noexcept return find(id) != nullptr; } +//------------------------------------------------ + +void +Corpus:: +visit(SymbolID id, Visitor& f) const +{ + visit(get(id), f); +} + +void +Corpus:: +visit(Scope const& I, Visitor& f) const +{ + for(auto const& ref : I.Namespaces) + visit(get(ref.USR), f); + for(auto const& ref : I.Records) + visit(get(ref.USR), f); + for(auto const& ref : I.Functions) + visit(get(ref.USR), f); + for(auto const& J : I.Typedefs) + visit(J, f); + for(auto const& J : I.Enums) + visit(J, f); +} + +void +Corpus:: +visitWithOverloads( + Scope const& I, Visitor& f) const +{ + for(auto const& ref : I.Namespaces) + visit(get(ref.USR), f); + for(auto const& ref : I.Records) + visit(get(ref.USR), f); + if(I.isNamespaceScope) + { + // VFALCO Should this be AS_public + auto const set = makeFunctionOverloadsSet( + *this, I, AccessSpecifier::AS_none); + for(auto const& functionOverloads : set.list) + f.visit(functionOverloads); + } + else + { + { + auto const& set = makeFunctionOverloadsSet( + *this, I, AccessSpecifier::AS_public); + for(auto const& functionOverloads : set.list) + f.visit(functionOverloads); + } + { + auto const& set = makeFunctionOverloadsSet( + *this, I, AccessSpecifier::AS_protected); + for(auto const& functionOverloads : set.list) + f.visit(functionOverloads); + } + { + auto const& set = makeFunctionOverloadsSet( + *this, I, AccessSpecifier::AS_private); + for(auto const& functionOverloads : set.list) + f.visit(functionOverloads); + } + } + for(auto const& J : I.Typedefs) + visit(J, f); + for(auto const& J : I.Enums) + visit(J, f); +} + +void +Corpus:: +visit(Info const& I, Visitor& f) const +{ + switch(I.IT) + { + case InfoType::IT_namespace: + return f.visit(static_cast(I)); + case InfoType::IT_record: + return f.visit(static_cast(I)); + case InfoType::IT_function: + return f.visit(static_cast(I)); + case InfoType::IT_typedef: + return f.visit(static_cast(I)); + case InfoType::IT_enum: + return f.visit(static_cast(I)); + default: + llvm_unreachable("wrong InfoType for viist"); + } +} + //------------------------------------------------ // // Modifiers diff --git a/source/lib/ast/FrontendAction.cpp b/source/lib/ast/FrontendAction.cpp index 250c578a9..90488d93f 100644 --- a/source/lib/ast/FrontendAction.cpp +++ b/source/lib/ast/FrontendAction.cpp @@ -20,13 +20,6 @@ #include #include -#if 0 -#include -#include -#include -#include -#endif - // // This file implements the Mapper piece of the clang-doc tool. It implements // a RecursiveASTVisitor to look at each declaration and populate the info diff --git a/source/lib/format/asciidoc/Asciidoc.cpp b/source/lib/format/asciidoc/Asciidoc.cpp index 2f2d4339b..0c816987c 100644 --- a/source/lib/format/asciidoc/Asciidoc.cpp +++ b/source/lib/format/asciidoc/Asciidoc.cpp @@ -10,182 +10,20 @@ // #include "Asciidoc.hpp" +#include "PagesBuilder.hpp" #include -#include +#include #include namespace clang { namespace mrdox { -//------------------------------------------------ -// -// Pages -// -//------------------------------------------------ - -struct CorpusVisitor -{ - Corpus const& corpus_; - - virtual ~CorpusVisitor() = default; - - explicit - CorpusVisitor( - Corpus const& corpus) noexcept - : corpus_(corpus) - { - } - - void - visit(SymbolID id) - { - auto I = corpus_.find(id); - assert(I); - switch(I->IT) - { - default: - case InfoType::IT_default: - llvm_unreachable("unknown type"); - case InfoType::IT_namespace: - return visit(*static_cast(I)); - case InfoType::IT_record: - return visit(*static_cast(I)); - case InfoType::IT_function: - return visit(*static_cast(I)); - case InfoType::IT_enum: - return visit(*static_cast(I)); - case InfoType::IT_typedef: - return visit(*static_cast(I)); - } - } - - virtual - void - visit(Scope const& scope) - { - for(auto const& ref : scope.Namespaces) - visit(ref.USR); - for(auto const& ref : scope.Records) - visit(ref.USR); - for(auto const& ref : scope.Functions) - visit(ref.USR); - for(auto const& symbol : scope.Typedefs) - visit(symbol); - for(auto const& symbol : scope.Enums) - visit(symbol); - } - - virtual - void - visit(NamespaceInfo const& symbol) - { - visit(symbol.Children); - } - - virtual - void - visit(RecordInfo const& symbol) - { - } - - virtual - void - visit(FunctionInfo const& symbol) - { - } - - virtual - void - visit(EnumInfo const& symbol) - { - } - - virtual - void - visit(TypedefInfo const& symbol) - { - } -}; - -//------------------------------------------------ - -namespace { - -struct PageBuilder : CorpusVisitor -{ - PageBuilder( - Corpus const& corpus) noexcept - : CorpusVisitor(corpus) - { - } - - void - build() - { - this->CorpusVisitor::visit(corpus_.globalNamespace()); - } - - void - visit(RecordInfo const& symbol) override - { - } - - void - visit(FunctionInfo const& symbol) override - { - } - - void - visit(EnumInfo const& symbol) override - { - } - - void - visit(TypedefInfo const& symbol) override - { - } -}; - -} // (anon) - //------------------------------------------------ // // AsciidocGenerator // //------------------------------------------------ -/* - Pages are as follows: - - Class - Class Template - Class Template Specialization - OverloadSet - Nested Class - Free Function - Variable/Constant - Typedef - Enum - - Page name: - - /{namespace}/{symbol}.html -*/ -struct AsciidocGenerator:: - Pages -{ -}; - -void -AsciidocGenerator:: -calculatePages() const -{ - //PageBuilder builder(corpus_); - - -} - - bool AsciidocGenerator:: build( @@ -238,7 +76,8 @@ build( } return true; #else - calculatePages(); + //PagesBuilder builder(corpus); + //builder.scan(); llvm::SmallString<0> fileName(rootPath); path::append(fileName, "reference.adoc"); @@ -446,13 +285,10 @@ writeRecord( AccessSpecifier::AS_public); // Member Functions - writeOverloadSet( + writeFunctionOverloads( "Member Functions", - makeOverloadSet(corpus_, I.Children, - [](FunctionInfo const& I) - { - return I.Access == AccessSpecifier::AS_public; - })); + makeFunctionOverloadsSet(corpus_, I.Children, + AccessSpecifier::AS_public)); // Data Members (protected) writeDataMembers( @@ -461,13 +297,10 @@ writeRecord( AccessSpecifier::AS_protected); // Member Functiosn (protected) - writeOverloadSet( + writeFunctionOverloads( "Protected Member Functions", - makeOverloadSet(corpus_, I.Children, - [](FunctionInfo const& I) - { - return I.Access == AccessSpecifier::AS_protected; - })); + makeFunctionOverloadsSet(corpus_, I.Children, + AccessSpecifier::AS_protected)); // Data Members (private) writeDataMembers( @@ -476,13 +309,10 @@ writeRecord( AccessSpecifier::AS_private); // Member Functions (private) - writeOverloadSet( + writeFunctionOverloads( "Private Member Functions", - makeOverloadSet(corpus_, I.Children, - [](FunctionInfo const& I) - { - return I.Access == AccessSpecifier::AS_private; - })); + makeFunctionOverloadsSet(corpus_, I.Children, + AccessSpecifier::AS_private)); closeSection(); } @@ -588,11 +418,11 @@ writeBase( void AsciidocGenerator:: Writer:: -writeOverloadSet( +writeFunctionOverloads( llvm::StringRef sectionName, - std::vector const& list) + FunctionOverloadsSet const& set) { - if(list.empty()) + if(set.list.empty()) return; openSection(sectionName); os_ << @@ -601,7 +431,7 @@ writeOverloadSet( "|===\n" << "|Name |Description\n" << "\n"; - for(auto const& J : list) + for(auto const& J : set.list) { os_ << "|`" << J.name << "`\n" << diff --git a/source/lib/format/asciidoc/Asciidoc.hpp b/source/lib/format/asciidoc/Asciidoc.hpp index 390286a1c..1ed6f6eb8 100644 --- a/source/lib/format/asciidoc/Asciidoc.hpp +++ b/source/lib/format/asciidoc/Asciidoc.hpp @@ -32,7 +32,6 @@ class AsciidocGenerator : public Generator { public: - struct Pages; class Writer; llvm::StringRef @@ -47,9 +46,6 @@ class AsciidocGenerator return "adoc"; } - void - calculatePages() const; - bool build( llvm::StringRef rootPath, @@ -106,9 +102,9 @@ class AsciidocGenerator::Writer void writeTypedef(TypedefInfo const& I) override; void writeBase(BaseRecordInfo const& I); - void writeOverloadSet( + void writeFunctionOverloads( llvm::StringRef sectionName, - std::vector const& list); + FunctionOverloadsSet const& set); void writeNestedTypes( llvm::StringRef sectionName, std::vector const& list, diff --git a/source/lib/format/asciidoc/PagesBuilder.cpp b/source/lib/format/asciidoc/PagesBuilder.cpp new file mode 100644 index 000000000..7dd26c761 --- /dev/null +++ b/source/lib/format/asciidoc/PagesBuilder.cpp @@ -0,0 +1,137 @@ +// +// 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) +// +// Official repository: https://github.com/cppalliance/mrdox +// + +#include "PagesBuilder.hpp" +#include +#include +#include + +namespace clang { +namespace mrdox { + +/* + Pages are as follows: + + Class + Class Template + Class Template Specialization + OverloadSet + Nested Class + Free Function + Variable/Constant + Typedef + Enum + + Page name: + + /{namespace}/{symbol}.html +*/ + +void +PagesBuilder:: +scan() +{ + // visit the children not the namespace + corpus_.visitWithOverloads(corpus_.globalNamespace().Children, *this); + + std::sort(pages.begin(), pages.end(), + [](Page& p0, Page& p1) + { + return Corpus::symbolCompare( + p0.fileName, p1.fileName); + }); +} + +void +PagesBuilder:: +visit( + NamespaceInfo const& I) +{ + namespace path = llvm::sys::path; + + auto saved = filePrefix_; + path::append(filePrefix_, I.Name); + corpus_.visit(I.Children, *this); + filePrefix_ = saved; +} + +void +PagesBuilder:: +visit( + RecordInfo const& I) +{ + namespace path = llvm::sys::path; + + int i = 0; + if(I.Name == "ipv4_address") + { + i = 1; + } + + auto filePath = filePrefix_; + path::append(filePath, I.Name); + path::replace_extension(filePath, "adoc"); + pages.emplace_back(std::move(filePath)); + + auto saved = filePrefix_; + path::append(filePrefix_, I.Name); + corpus_.visitWithOverloads(I.Children, *this); + filePrefix_ = saved; + +} + +void +PagesBuilder:: +visit( + FunctionOverloads const& I) +{ + namespace path = llvm::sys::path; + + auto filePath = filePrefix_; + path::append(filePath, I.name); + path::replace_extension(filePath, "adoc"); + pages.emplace_back(std::move(filePath)); +} + +void +PagesBuilder:: +visit( + FunctionInfo const& I) +{ +} + +void +PagesBuilder:: +visit( + TypedefInfo const& I) +{ + namespace path = llvm::sys::path; + + auto filePath = filePrefix_; + path::append(filePath, I.Name); + path::replace_extension(filePath, "adoc"); + pages.emplace_back(std::move(filePath)); +} + +void +PagesBuilder:: +visit( + EnumInfo const& I) +{ + namespace path = llvm::sys::path; + + auto filePath = filePrefix_; + path::append(filePath, I.Name); + path::replace_extension(filePath, "adoc"); + pages.emplace_back(std::move(filePath)); +} + +} // mrdox +} // clang diff --git a/source/lib/format/asciidoc/PagesBuilder.hpp b/source/lib/format/asciidoc/PagesBuilder.hpp new file mode 100644 index 000000000..a8dc0cec7 --- /dev/null +++ b/source/lib/format/asciidoc/PagesBuilder.hpp @@ -0,0 +1,55 @@ +// +// 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) +// +// Official repository: https://github.com/cppalliance/mrdox +// + +#ifndef MRDOX_SOURCE_FORMAT_ASCIIDOC_PAGESBUILDER_HPP +#define MRDOX_SOURCE_FORMAT_ASCIIDOC_PAGESBUILDER_HPP + +#include +#include +#include + +namespace clang { +namespace mrdox { + +class PagesBuilder : Corpus::Visitor +{ + Corpus const& corpus_; + +public: + struct Page + { + llvm::SmallString<0> fileName; + }; + + std::vector pages; + + PagesBuilder( + Corpus const& corpus) noexcept + : corpus_(corpus) + { + } + + void scan(); + + void visit(NamespaceInfo const&) override; + void visit(RecordInfo const&) override; + void visit(FunctionOverloads const&) override; + void visit(FunctionInfo const&) override; + void visit(TypedefInfo const&) override; + void visit(EnumInfo const&) override; + +private: + llvm::SmallString<0> filePrefix_; +}; + +} // mrdox +} // clang + +#endif diff --git a/source/lib/format/OverloadSet.cpp b/source/lib/meta/FunctionOverloads.cpp similarity index 65% rename from source/lib/format/OverloadSet.cpp rename to source/lib/meta/FunctionOverloads.cpp index e74c4e783..3c05b4325 100644 --- a/source/lib/format/OverloadSet.cpp +++ b/source/lib/meta/FunctionOverloads.cpp @@ -10,52 +10,55 @@ // #include -#include #include +#include #include namespace clang { namespace mrdox { -std::vector -makeOverloadSet( +FunctionOverloadsSet +makeFunctionOverloadsSet( Corpus const& corpus, Scope const& scope, - std::function filter) + AccessSpecifier access) { - std::vector result; - std::vector list; - list.reserve(scope.Functions.size()); + FunctionOverloadsSet result; + result.access = access; + + std::vector temp; + temp.reserve(scope.Functions.size()); for(auto const& ref : scope.Functions) { auto const& I = corpus.get(ref.USR); - if(filter(I)) - list.push_back(&I); + if(I.Access == access) + temp.push_back(&I); } - if(list.empty()) - return {}; - std::sort(list.begin(), list.end(), + if(temp.empty()) + return result; + + std::sort(temp.begin(), temp.end(), []( FunctionInfo const* f0, FunctionInfo const* f1) { return f0->Name < f1->Name; }); - auto it0 = list.begin(); + auto it0 = temp.begin(); auto it = it0; do { ++it; - if( it == list.end() || + if( it == temp.end() || (*it)->Name != (*it0)->Name) { - result.emplace_back( - OverloadSet{ + result.list.emplace_back( + FunctionOverloads{ (*it0)->Name, std::vector(it0, it)}); it0 = it; } } - while(it != list.end()); + while(it != temp.end()); return result; } diff --git a/source/lib/meta/Namespace.cpp b/source/lib/meta/Namespace.cpp index 620226585..f29916de6 100644 --- a/source/lib/meta/Namespace.cpp +++ b/source/lib/meta/Namespace.cpp @@ -25,6 +25,7 @@ NamespaceInfo() EmptySID, "", "") + , Children(true) { } @@ -34,6 +35,7 @@ NamespaceInfo( StringRef Name, StringRef Path) : Info(InfoType::IT_namespace, USR, Name, Path) + , Children(true) { } diff --git a/source/lib/meta/Record.cpp b/source/lib/meta/Record.cpp index 639e46c28..c593e3939 100644 --- a/source/lib/meta/Record.cpp +++ b/source/lib/meta/Record.cpp @@ -23,6 +23,7 @@ RecordInfo( StringRef Name, StringRef Path) : SymbolInfo(InfoType::IT_record, USR, Name, Path) + , Children(false) { }