From ed78539dbaf9d58ea8ff7c30eeea1501f6c32d3e Mon Sep 17 00:00:00 2001 From: alandefreitas Date: Sun, 29 Dec 2024 03:54:33 -0300 Subject: [PATCH] Corpus ordered traverse #feat --- include/mrdocs/Corpus.hpp | 90 ++++++++++++++++++++++++++++++++------ src/lib/Lib/CorpusImpl.cpp | 3 +- src/lib/Metadata/Info.cpp | 64 +++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 14 deletions(-) diff --git a/include/mrdocs/Corpus.hpp b/include/mrdocs/Corpus.hpp index b4bf5a605..500f27083 100644 --- a/include/mrdocs/Corpus.hpp +++ b/include/mrdocs/Corpus.hpp @@ -6,6 +6,7 @@ // // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) +// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -160,6 +161,32 @@ class MRDOCS_VISIBLE } } + /** Visit the members of specified Info in a stable order. + + @param I The Info to visit. + @param info The Info to visit. + @param f The function to invoke. + @param args The arguments to pass to the function. + */ + template + void + orderedTraverse( + T const& I, F&& f, Args&&... args) const + { + std::vector members(I.Members.begin(), I.Members.end()); + std::stable_sort(members.begin(), members.end(), [this](SymbolID const& lhs, SymbolID const& rhs) + { + auto const& lhsInfo = get(lhs); + auto const& rhsInfo = get(rhs); + return lhsInfo < rhsInfo; + }); + for (auto const& id : members) + { + visit(get(id), std::forward(f), + std::forward(args)...); + } + } + /** Visit the member overloads of specified ScopeInfo. This function iterates the members of the @@ -184,6 +211,14 @@ class MRDOCS_VISIBLE F&& f, Args&&... args) const; + /** Visit the member overloads of specified ScopeInfo in stable order + */ + template + void orderedTraverseOverloads( + ScopeInfo const& S, + F&& f, + Args&&... args) const; + //-------------------------------------------- /** Return the fully qualified name of the specified Info. @@ -238,25 +273,20 @@ get( template void -Corpus:: -traverseOverloads( +traverseOverloadsImpl( + Corpus const& c, + std::vector const& members0, ScopeInfo const& S, - F&& f, Args&&... args) const + F&& f, Args&&... args) { - MRDOCS_ASSERT(S.Members.empty() == S.Lookups.empty()); - for(const SymbolID& id : S.Members) + for(const SymbolID& id : members0) { - const Info& member = get(id); + const Info& member = c.get(id); const auto& members = S.Lookups.at(member.Name); auto first_func = std::ranges::find_if( - members, [this](const SymbolID& elem) + members, [&c](const SymbolID& elem) { - #if 0 - const Info& I = get(elem); - return I.isFunction() || I.isGuide(); - #else - return get(elem).isFunction(); - #endif + return c.get(elem).isFunction(); }); bool const nonOverloadedFunction = members.size() == 1; bool const notFunction = first_func == members.end(); @@ -278,6 +308,40 @@ traverseOverloads( } } +template +void +Corpus:: +traverseOverloads( + ScopeInfo const& S, + F&& f, Args&&... args) const +{ + MRDOCS_ASSERT(S.Members.empty() == S.Lookups.empty()); + return traverseOverloadsImpl( + *this, S.Members, S, std::forward(f), std::forward(args)...); + +} + +template +void +Corpus:: +orderedTraverseOverloads( + ScopeInfo const& S, + F&& f, + Args&&... args) const +{ + MRDOCS_ASSERT(S.Members.empty() == S.Lookups.empty()); + std::vector members(S.Members.begin(), S.Members.end()); + std::stable_sort(members.begin(), members.end(), [this](SymbolID const& lhs, SymbolID const& rhs) + { + auto const& lhsInfo = get(lhs); + auto const& rhsInfo = get(rhs); + return lhsInfo < rhsInfo; + }); + return traverseOverloadsImpl( + *this, members, S, std::forward(f), std::forward(args)...); +} + + class Corpus::iterator { const Corpus* corpus_; diff --git a/src/lib/Lib/CorpusImpl.cpp b/src/lib/Lib/CorpusImpl.cpp index ed7724c06..375a7d06d 100644 --- a/src/lib/Lib/CorpusImpl.cpp +++ b/src/lib/Lib/CorpusImpl.cpp @@ -6,6 +6,7 @@ // // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) +// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -18,7 +19,7 @@ #include "lib/Support/Chrono.hpp" #include #include -#include +#include #include namespace clang { diff --git a/src/lib/Metadata/Info.cpp b/src/lib/Metadata/Info.cpp index 30e7de697..7e7b6cecc 100644 --- a/src/lib/Metadata/Info.cpp +++ b/src/lib/Metadata/Info.cpp @@ -287,6 +287,70 @@ tag_invoke( }); } +bool +operator<( + Info const& lhs, + Info const& rhs) noexcept +{ + if (lhs.Kind != rhs.Kind) + { + return lhs.Kind < rhs.Kind; + } + if (lhs.Name != rhs.Name) + { + return lhs.Name < rhs.Name; + } + + // If kind and name are the same, compare by template arguments + TemplateInfo const* lhsTemplate = visit(lhs, [](auto const& U) + -> TemplateInfo const* + { + if constexpr (requires { U.Template; }) + { + if (U.Template) + { + return &*U.Template; + } + } + return nullptr; + }); + TemplateInfo const* rhsTemplate = visit(rhs, [](auto const& U) + -> TemplateInfo const* + { + if constexpr (requires { U.Template; }) + { + if (U.Template) + { + return &*U.Template; + } + } + return nullptr; + }); + if (!lhsTemplate && !rhsTemplate) + { + return false; + } + if (!lhsTemplate) + { + return true; + } + if (!rhsTemplate) + { + return false; + } + if (lhsTemplate->Args.size() != rhsTemplate->Args.size()) + { + return lhsTemplate->Args.size() < rhsTemplate->Args.size(); + } + for (std::size_t i = 0; i < lhsTemplate->Args.size(); ++i) + { + if (lhsTemplate->Args[i] != rhsTemplate->Args[i]) + { + return lhsTemplate->Args[i]->Kind < rhsTemplate->Args[i]->Kind; + } + } + return false; +} } // mrdocs } // clang