From c0fcf40d20df36f710f8998499317c57ffacbde3 Mon Sep 17 00:00:00 2001 From: alandefreitas Date: Mon, 31 Mar 2025 22:38:35 -0300 Subject: [PATCH] reserved legible names are automatically generated #improvement --- include/mrdocs/ADT/UnorderedStringMap.hpp | 7 +- include/mrdocs/Metadata/Info.hpp | 54 +++- include/mrdocs/Metadata/Source.hpp | 10 + include/mrdocs/Support/String.hpp | 277 ++++++++++++++++++ src/lib/AST/ASTVisitor.cpp | 60 ++-- src/lib/Gen/hbs/VisitorHelpers.cpp | 4 +- src/lib/Lib/CorpusImpl.cpp | 4 +- .../Finalizers/BaseMembersFinalizer.cpp | 6 +- .../Finalizers/BaseMembersFinalizer.hpp | 2 +- .../Metadata/Finalizers/DerivedFinalizer.cpp | 4 +- .../Metadata/Finalizers/Javadoc/Overloads.hpp | 2 +- .../Metadata/Finalizers/JavadocFinalizer.cpp | 20 +- .../Finalizers/NamespacesFinalizer.cpp | 2 +- .../Finalizers/NamespacesFinalizer.hpp | 3 +- .../Finalizers/OverloadsFinalizer.cpp | 22 +- .../Finalizers/OverloadsFinalizer.hpp | 3 +- .../Finalizers/SortMembersFinalizer.cpp | 10 +- .../Finalizers/SortMembersFinalizer.hpp | 3 +- src/lib/Metadata/Info.cpp | 2 +- src/lib/Metadata/Info/Concept.cpp | 4 +- src/lib/Metadata/Info/Enum.cpp | 2 +- src/lib/Metadata/Info/EnumConstant.cpp | 2 +- src/lib/Metadata/Info/Field.cpp | 2 +- src/lib/Metadata/Info/Friend.cpp | 2 +- src/lib/Metadata/Info/Function.cpp | 4 +- src/lib/Metadata/Info/Guide.cpp | 4 +- src/lib/Metadata/Info/Namespace.cpp | 4 +- src/lib/Metadata/Info/NamespaceAlias.cpp | 2 +- src/lib/Metadata/Info/Overloads.cpp | 4 +- src/lib/Metadata/Info/Record.cpp | 4 +- src/lib/Metadata/Info/Typedef.cpp | 4 +- src/lib/Metadata/Info/Using.cpp | 2 +- src/lib/Metadata/Info/Variable.cpp | 4 +- src/lib/Support/LegibleNames.cpp | 67 ++--- .../config/legible-names/constructor.adoc | 207 +++++++++++++ .../config/legible-names/constructor.cpp | 9 + .../config/legible-names/constructor.html | 276 +++++++++++++++++ .../config/legible-names/constructor.xml | 79 +++++ 38 files changed, 1039 insertions(+), 138 deletions(-) create mode 100644 test-files/golden-tests/config/legible-names/constructor.adoc create mode 100644 test-files/golden-tests/config/legible-names/constructor.cpp create mode 100644 test-files/golden-tests/config/legible-names/constructor.html create mode 100644 test-files/golden-tests/config/legible-names/constructor.xml diff --git a/include/mrdocs/ADT/UnorderedStringMap.hpp b/include/mrdocs/ADT/UnorderedStringMap.hpp index 35784c2bd..71c086c59 100644 --- a/include/mrdocs/ADT/UnorderedStringMap.hpp +++ b/include/mrdocs/ADT/UnorderedStringMap.hpp @@ -17,7 +17,7 @@ namespace clang::mrdocs { -struct string_hash +struct StringHash { using hash_type = std::hash; using is_transparent = void; @@ -27,7 +27,10 @@ struct string_hash }; template -using UnorderedStringMap = std::unordered_map>; +using UnorderedStringMap = std::unordered_map>; + +template +using UnorderedStringMultiMap = std::unordered_multimap>; } // clang::mrdocs diff --git a/include/mrdocs/Metadata/Info.hpp b/include/mrdocs/Metadata/Info.hpp index ecf56351b..f57c53927 100644 --- a/include/mrdocs/Metadata/Info.hpp +++ b/include/mrdocs/Metadata/Info.hpp @@ -59,6 +59,16 @@ tag_invoke( v = toString(kind); } +consteval +std::underlying_type_t +countInfoKind() +{ + std::underlying_type_t count = 0; +#define INFO(Type) count++; +#include + return count; +} + /** Base class with common properties of all symbols */ struct MRDOCS_VISIBLE Info @@ -136,7 +146,49 @@ struct MRDOCS_VISIBLE Info { } - #define INFO(Type) constexpr bool is##Type() const noexcept { return Kind == InfoKind::Type; } + #define INFO(Type) constexpr bool is##Type() const noexcept { \ + return Kind == InfoKind::Type; \ + } + #include + + constexpr Info const& asInfo() const noexcept + { + return *this; + } + + constexpr Info& asInfo() noexcept + { + return *this; + } + + #define INFO(Type) \ + constexpr Type##Info const& as##Type() const noexcept { \ + if (Kind == InfoKind::Type) \ + return reinterpret_cast(*this); \ + MRDOCS_UNREACHABLE(); \ + } + #include + + #define INFO(Type) \ + constexpr Type##Info & as##Type() noexcept { \ + if (Kind == InfoKind::Type) \ + return reinterpret_cast(*this); \ + MRDOCS_UNREACHABLE(); \ + } + #include + + #define INFO(Type) \ + constexpr Type##Info const* as##Type##Ptr() const noexcept { \ + if (Kind == InfoKind::Type) { return reinterpret_cast(this); } \ + return nullptr; \ + } + #include + + #define INFO(Type) \ + constexpr Type##Info * as##Type##Ptr() noexcept { \ + if (Kind == InfoKind::Type) { return reinterpret_cast(this); } \ + return nullptr; \ + } #include auto operator<=>(Info const&) const = default; diff --git a/include/mrdocs/Metadata/Source.hpp b/include/mrdocs/Metadata/Source.hpp index e9d9fa28e..06d990d99 100644 --- a/include/mrdocs/Metadata/Source.hpp +++ b/include/mrdocs/Metadata/Source.hpp @@ -127,6 +127,16 @@ struct MRDOCS_DECL */ std::vector Loc; + constexpr SourceInfo const& asSourceInfo() const noexcept + { + return *this; + } + + constexpr SourceInfo& asSourceInfo() noexcept + { + return *this; + } + constexpr virtual ~SourceInfo() = default; auto operator<=>(SourceInfo const&) const = default; diff --git a/include/mrdocs/Support/String.hpp b/include/mrdocs/Support/String.hpp index 7ebc1dbb8..74dcbc06e 100644 --- a/include/mrdocs/Support/String.hpp +++ b/include/mrdocs/Support/String.hpp @@ -118,6 +118,283 @@ endsWithOneOf(std::string_view s, std::string_view chars) noexcept return !s.empty() && chars.find(s.back()) != std::string_view::npos; } +constexpr +bool +isLowerCase(char const c) noexcept +{ + return c >= 'a' && c <= 'z'; +} + +constexpr +bool +isLowerCase(std::string_view const s) noexcept +{ + for (char const c : s) + { + if (!isLowerCase(c)) + { + return false; + } + } + return true; +} + +constexpr +bool +isUpperCase(char const c) noexcept +{ + return c >= 'A' && c <= 'Z'; +} + +constexpr +bool +isUpperCase(std::string_view const s) noexcept +{ + for (char const c : s) + { + if (!isUpperCase(c)) + { + return false; + } + } + return true; +} + +constexpr +char +toLowerCase(char const c) noexcept +{ + return isUpperCase(c) ? c + ('a' - 'A') : c; +} + +constexpr +std::string +toLowerCase(std::string_view const s) noexcept +{ + std::string result; + result.reserve(s.size()); + for (char const c : s) + { + result.push_back(toLowerCase(c)); + } + return result; +} + +constexpr +char +toUpperCase(char const c) noexcept +{ + return isLowerCase(c) ? c - ('a' - 'A') : c; +} + +constexpr +std::string +toUpperCase(std::string_view const s) noexcept +{ + std::string result; + result.reserve(s.size()); + for (char const c : s) + { + result.push_back(toUpperCase(c)); + } + return result; +} + +constexpr +bool +isDigit(char const c) noexcept +{ + return c >= '0' && c <= '9'; +} + +constexpr +bool +isDigit(std::string_view const s) noexcept +{ + for (char const c : s) + { + if (!isDigit(c)) + { + return false; + } + } + return true; +} + +constexpr +bool +isAlphabetic(char const c) noexcept +{ + return isLowerCase(c) || isUpperCase(c); +} + +constexpr +bool +isAlphabetic(std::string_view const s) noexcept +{ + for (char const c : s) + { + if (!isAlphabetic(c)) + { + return false; + } + } + return true; +} + +constexpr +bool +isAlphaNumeric(char const c) noexcept +{ + return isAlphabetic(c) || isDigit(c); +} + +constexpr +bool +isAlphaNumeric(std::string_view const s) noexcept +{ + for (char const c : s) + { + if (!isAlphaNumeric(c)) + { + return false; + } + } + return true; +} + +constexpr +std::string +toKebabCase(std::string_view const input) +{ + std::string result; + size_t extraSizeCount = 0; + for (std::size_t i = 1; i < input.size(); ++i) { + if (isUpperCase(input[i])) { + ++extraSizeCount; + } + } + result.reserve(input.size() + extraSizeCount); + for (size_t i = 0; i < input.size(); ++i) { + if (char const c = input[i]; + isUpperCase(c)) + { + if (i != 0) { + result.push_back('-'); + } + result.push_back(toLowerCase(c)); + } + else if (isLowerCase(c) || isDigit(c)) + { + result.push_back(c); + } + else + { + result.push_back('-'); + } + } + return result; +} + +constexpr +std::string +toSnakeCase(std::string_view const input) +{ + std::string result; + size_t extraSizeCount = 0; + for (std::size_t i = 1; i < input.size(); ++i) { + if (isUpperCase(input[i])) + { + ++extraSizeCount; + } + } + result.reserve(input.size() + extraSizeCount); + for (size_t i = 0; i < input.size(); ++i) { + if (char const c = input[i]; + isUpperCase(c)) + { + if (i != 0) + { + result.push_back('_'); + } + result.push_back(toLowerCase(c)); + } + else if (isLowerCase(c) || isDigit(c)) + { + result.push_back(c); + } + else + { + result.push_back('_'); + } + } + return result; +} + +constexpr +std::string +toCamelCase(std::string_view const input) +{ + std::string result; + result.reserve(input.size()); + bool forceUppercaseNext = false; + for (char const c : input) + { + if (isAlphaNumeric(c)) + { + if (result.empty()) + { + result.push_back(toLowerCase(c)); + forceUppercaseNext = false; + } + else if (forceUppercaseNext) + { + result.push_back(toUpperCase(c)); + forceUppercaseNext = false; + } + else + { + result.push_back(c); + } + } + else + { + forceUppercaseNext = true; + } + } + return result; +} + +constexpr +std::string +toPascalCase(std::string_view const input) +{ + std::string result; + result.reserve(input.size()); + bool forceUppercaseNext = true; + for (char const c : input) + { + if (isAlphaNumeric(c)) + { + if (forceUppercaseNext) + { + result.push_back(toUpperCase(c)); + forceUppercaseNext = false; + } + else + { + result.push_back(c); + } + } + else + { + forceUppercaseNext = true; + } + } + return result; +} + + } // clang::mrdocs #endif diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index 98194b647..75404c987 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -123,7 +123,7 @@ traverse(DeclTy const* D) // Populate the base classes with the necessary information. // Even when the object is new, we want to update the source locations // and the documentation status. - populate(dynamic_cast(I), isNew, D); + populate(I.asInfo(), isNew, D); // Populate the derived Info object with the necessary information // when the object is new. If the object already exists, this @@ -167,8 +167,8 @@ traverse(UsingDirectiveDecl const* D) MRDOCS_SYMBOL_TRACE(P, context_); Info* PI = findOrTraverse(P); MRDOCS_CHECK_OR(PI, nullptr); - auto* const PNI = dynamic_cast(PI); - MRDOCS_CHECK_OR(PNI, nullptr); + MRDOCS_CHECK_OR(PI->isNamespace(), nullptr); + auto& PNI = PI->asNamespace(); // Find the nominated namespace Decl const* ND = D->getNominatedNamespace(); @@ -181,9 +181,9 @@ traverse(UsingDirectiveDecl const* D) MRDOCS_ASSERT(res); MRDOCS_ASSERT(res->isIdentifier()); if (NameInfo NI = *res; - !contains(PNI->UsingDirectives, NI)) + !contains(PNI.UsingDirectives, NI)) { - PNI->UsingDirectives.push_back(std::move(NI)); + PNI.UsingDirectives.push_back(std::move(NI)); } return nullptr; } @@ -524,7 +524,7 @@ ASTVisitor:: populate(Info& I, bool const isNew, DeclTy const* D) { populate(I.javadoc, D); - populate(dynamic_cast(I), D); + populate(I.asSourceInfo(), D); // All other information is redundant if the symbol is not new MRDOCS_CHECK_OR(isNew); @@ -549,7 +549,7 @@ populate(SourceInfo& I, DeclTy const* D) if (Loc.isValid()) { populate( - dynamic_cast(I), + I.asSourceInfo(), Loc, isDefinition(D), isDocumented(D)); @@ -1642,52 +1642,52 @@ addMember( NamespaceInfo& I, Info const& Member) { - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asNamespacePtr()) { addMember(I.Members.Namespaces, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asNamespaceAliasPtr()) { addMember(I.Members.NamespaceAliases, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asTypedefPtr()) { addMember(I.Members.Typedefs, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asRecordPtr()) { addMember(I.Members.Records, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asEnumPtr()) { addMember(I.Members.Enums, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asFunctionPtr()) { addMember(I.Members.Functions, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asVariablePtr()) { addMember(I.Members.Variables, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asConceptPtr()) { addMember(I.Members.Concepts, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asGuidePtr()) { addMember(I.Members.Guides, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asUsingPtr()) { addMember(I.Members.Usings, *U); return; @@ -1724,27 +1724,27 @@ void ASTVisitor:: addMember(RecordTranche& T, Info const& Member) { - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asNamespaceAliasPtr()) { addMember(T.NamespaceAliases, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asTypedefPtr()) { addMember(T.Typedefs, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asRecordPtr()) { addMember(T.Records, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asEnumPtr()) { addMember(T.Enums, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asFunctionPtr()) { if (U->StorageClass != StorageClassKind::Static) { @@ -1756,32 +1756,32 @@ addMember(RecordTranche& T, Info const& Member) } return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asFieldPtr()) { addMember(T.Variables, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asVariablePtr()) { addMember(T.StaticVariables, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asConceptPtr()) { addMember(T.Concepts, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asGuidePtr()) { addMember(T.Guides, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asFriendPtr()) { addMember(T.Friends, *U); return; } - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asUsingPtr()) { addMember(T.Usings, *U); return; @@ -1795,7 +1795,7 @@ void ASTVisitor:: addMember(EnumInfo& I, Info const& Member) const { - if (auto const* U = dynamic_cast(&Member)) + if (auto const* U = Member.asEnumConstantPtr()) { addMember(I.Constants, *U); return; @@ -3468,7 +3468,7 @@ checkUndocumented( // Populate the location auto handle = undocumented_.extract(undocIt); UndocumentedInfo& UI = handle.value(); - populate(dynamic_cast(UI), D); + populate(UI.asSourceInfo(), D); undocumented_.insert(std::move(handle)); } return Unexpected(Error("Undocumented")); diff --git a/src/lib/Gen/hbs/VisitorHelpers.cpp b/src/lib/Gen/hbs/VisitorHelpers.cpp index ae3c09b9a..5464e1f40 100644 --- a/src/lib/Gen/hbs/VisitorHelpers.cpp +++ b/src/lib/Gen/hbs/VisitorHelpers.cpp @@ -47,9 +47,9 @@ namespace { Info const* resolveTypedef(Corpus const& c, Info const& I) { - if (I.Kind == InfoKind::Typedef) + if (I.isTypedef()) { - auto const& TI = dynamic_cast(I); + auto const& TI = I.asTypedef(); Polymorphic const& T = TI.Type; MRDOCS_CHECK_OR(T && T->Kind == TypeKind::Named, &I); auto const& NT = dynamic_cast(*T); diff --git a/src/lib/Lib/CorpusImpl.cpp b/src/lib/Lib/CorpusImpl.cpp index a207cc2af..64ab59e5e 100644 --- a/src/lib/Lib/CorpusImpl.cpp +++ b/src/lib/Lib/CorpusImpl.cpp @@ -467,7 +467,7 @@ lookupImpl( report::trace(" Context: '{}'", contextPtr->Name); // If context is a typedef, lookup in the resolved type - if (auto* TI = dynamic_cast(contextPtr)) + if (auto* TI = contextPtr->asTypedefPtr()) { MRDOCS_CHECK_OR(TI->Type, nullptr); SymbolID resolvedSymbolID = TI->Type->namedSymbol(); @@ -602,7 +602,7 @@ lookupImpl( // Function parameters size match MRDOCS_CHECK_OR(checkParameters && ref.HasFunctionParameters, matchRes); MRDOCS_CHECK_OR(MInfoTy::isFunction(), matchRes); - auto const& F = dynamic_cast(M); + auto const& F = M.asFunction(); MRDOCS_CHECK_OR(F.Params.size() == ref.FunctionParameters.size(), matchRes); matchRes = MatchLevel::FunctionParametersSize; diff --git a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp index 2ab9511ac..296f766ed 100644 --- a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp @@ -187,7 +187,7 @@ finalizeRecords(std::vector const& ids) { Info* infoPtr = corpus_.find(id); MRDOCS_CHECK_OR_CONTINUE(infoPtr); - auto record = dynamic_cast(infoPtr); + auto* record = infoPtr->asRecordPtr(); MRDOCS_CHECK_OR_CONTINUE(record); operator()(*record); } @@ -201,7 +201,7 @@ finalizeNamespaces(std::vector const& ids) { Info* infoPtr = corpus_.find(id); MRDOCS_CHECK_OR_CONTINUE(infoPtr); - auto* ns = dynamic_cast(infoPtr); + auto* ns = infoPtr->asNamespacePtr(); MRDOCS_CHECK_OR_CONTINUE(ns); operator()(*ns); } @@ -244,7 +244,7 @@ operator()(RecordInfo& I) MRDOCS_CHECK_OR_CONTINUE(baseID); auto basePtr = corpus_.find(baseID); MRDOCS_CHECK_OR_CONTINUE(basePtr); - auto* baseRecord = dynamic_cast(basePtr); + auto* baseRecord = basePtr->asRecordPtr(); MRDOCS_CHECK_OR_CONTINUE(baseRecord); operator()(*baseRecord); inheritBaseMembers(I, *baseRecord, baseI.Access); diff --git a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp index 6a016080f..efd2b774c 100644 --- a/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp +++ b/src/lib/Metadata/Finalizers/BaseMembersFinalizer.hpp @@ -68,7 +68,7 @@ class BaseMembersFinalizer { Info* info = corpus_.find(SymbolID::global); MRDOCS_CHECK_OR(info); - operator()(*dynamic_cast(info)); + operator()(info->asNamespace()); } void diff --git a/src/lib/Metadata/Finalizers/DerivedFinalizer.cpp b/src/lib/Metadata/Finalizers/DerivedFinalizer.cpp index a44e45092..2c106c563 100644 --- a/src/lib/Metadata/Finalizers/DerivedFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/DerivedFinalizer.cpp @@ -24,7 +24,7 @@ build() MRDOCS_ASSERT(I); MRDOCS_CHECK_OR_CONTINUE(I->Extraction == ExtractionMode::Regular); MRDOCS_CHECK_OR_CONTINUE(I->isRecord()); - auto& record = dynamic_cast(*I); + auto& record = I->asRecord(); MRDOCS_CHECK_OR_CONTINUE(!record.Bases.empty()); for (BaseInfo& base: record.Bases) { @@ -39,7 +39,7 @@ build() MRDOCS_CHECK_OR_CONTINUE(baseInfoPtr); MRDOCS_CHECK_OR_CONTINUE(baseInfoPtr->isRecord()); MRDOCS_CHECK_OR_CONTINUE(baseInfoPtr->Extraction == ExtractionMode::Regular); - if (auto& baseRecord = dynamic_cast(*baseInfoPtr); + if (auto& baseRecord = baseInfoPtr->asRecord(); !contains(baseRecord.Derived, record.id)) { // Insert in order by name diff --git a/src/lib/Metadata/Finalizers/Javadoc/Overloads.hpp b/src/lib/Metadata/Finalizers/Javadoc/Overloads.hpp index 16fe6c10d..9bfa06d7e 100644 --- a/src/lib/Metadata/Finalizers/Javadoc/Overloads.hpp +++ b/src/lib/Metadata/Finalizers/Javadoc/Overloads.hpp @@ -34,7 +34,7 @@ overloadFunctionsRange(OverloadsInfo const& O, CorpusImpl& corpus_) }) | std::views::transform([](Info const* infoPtr) -> FunctionInfo const& { - return *dynamic_cast(infoPtr); + return infoPtr->asFunction(); }); return functions; } diff --git a/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp b/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp index dd0eee3f2..5acfb80eb 100644 --- a/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/JavadocFinalizer.cpp @@ -72,7 +72,7 @@ build() { I.javadoc.emplace(); } - populateOverloadJavadoc(dynamic_cast(*infoPtr)); + populateOverloadJavadoc(infoPtr->asOverloads()); } } @@ -98,7 +98,7 @@ build() Info& I = *infoPtr; MRDOCS_CHECK_OR_CONTINUE(I.isFunction()); MRDOCS_CHECK_OR_CONTINUE(I.Extraction != ExtractionMode::Dependency); - populateFunctionJavadoc(dynamic_cast(I)); + populateFunctionJavadoc(I.asFunction()); } } @@ -138,9 +138,9 @@ finalizeBrief(Info& I) I.javadoc.emplace(); } // The brief of an overload is always empty - auto& OI = dynamic_cast(I); - for (auto& MemberIDs = OI.Members; - auto& memberID : MemberIDs) + auto& OI = I.asOverloads(); + for (auto const& MemberIDs = OI.Members; + auto& memberID : MemberIDs) { Info* member = corpus_.find(memberID); MRDOCS_CHECK_OR_CONTINUE(member); @@ -369,11 +369,11 @@ finalizeMetadataCopies(Info& I) // function parameters declaration. if (I.isFunction()) { - auto& destF = dynamic_cast(I); + auto& destF = I.asFunction(); for (Info const& srcInfo: srcInfos) { MRDOCS_CHECK_OR_CONTINUE(srcInfo.isFunction()); - auto const& srcFunction = dynamic_cast(srcInfo); + auto const& srcFunction = srcInfo.asFunction(); MRDOCS_CHECK_OR_CONTINUE(srcFunction.javadoc); for (Javadoc const& srcJavadoc = *srcFunction.javadoc; auto const& srcDocParam: srcJavadoc.params) @@ -438,7 +438,7 @@ finalizeMetadataCopies(Info& I) // and the destination is not noexcept bool const destIsNoExcept = I.isFunction() ? - dynamic_cast(I).Noexcept.Kind == NoexceptKind::False : + I.asFunction().Noexcept.Kind == NoexceptKind::False : false; if (destJavadoc.exceptions.empty() && !destIsNoExcept) @@ -531,7 +531,7 @@ finalizeMetadataCopies(Info& I) } else { - auto& OI = dynamic_cast(res); + auto& OI = res.asOverloads(); SmallVector srcInfos; srcInfos.reserve(OI.Members.size()); for (auto& memberID: OI.Members) @@ -639,7 +639,7 @@ populateOverloadJavadoc(OverloadsInfo& I) }) | std::views::transform([](Info const* infoPtr) -> FunctionInfo const& { - return *dynamic_cast(infoPtr); + return infoPtr->asFunction(); }); if (!I.javadoc) { diff --git a/src/lib/Metadata/Finalizers/NamespacesFinalizer.cpp b/src/lib/Metadata/Finalizers/NamespacesFinalizer.cpp index be862fe22..424f4cebf 100644 --- a/src/lib/Metadata/Finalizers/NamespacesFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/NamespacesFinalizer.cpp @@ -28,7 +28,7 @@ operator()(NamespaceInfo& I) { MRDOCS_ASSERT(info.isNamespace()); SymbolID memberID = info.id; - auto& member = dynamic_cast(info); + auto& member = info.asNamespace(); if (auto const res = (*this)(member); res == FinalizerResult::Removed) { diff --git a/src/lib/Metadata/Finalizers/NamespacesFinalizer.hpp b/src/lib/Metadata/Finalizers/NamespacesFinalizer.hpp index 89fed02d3..1b62047fb 100644 --- a/src/lib/Metadata/Finalizers/NamespacesFinalizer.hpp +++ b/src/lib/Metadata/Finalizers/NamespacesFinalizer.hpp @@ -38,7 +38,8 @@ class NamespacesFinalizer { Info* info = corpus_.find(SymbolID::global); MRDOCS_CHECK_OR(info); - operator()(*dynamic_cast(info)); + MRDOCS_ASSERT(info->isNamespace()); + operator()(info->asNamespace()); } enum class FinalizerResult { diff --git a/src/lib/Metadata/Finalizers/OverloadsFinalizer.cpp b/src/lib/Metadata/Finalizers/OverloadsFinalizer.cpp index 28e83af9a..56a750734 100644 --- a/src/lib/Metadata/Finalizers/OverloadsFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/OverloadsFinalizer.cpp @@ -20,9 +20,8 @@ foldRecordMembers(std::vector const& ids) { Info* infoPtr = corpus_.find(id); MRDOCS_CHECK_OR_CONTINUE(infoPtr); - auto* record = dynamic_cast(infoPtr); - MRDOCS_CHECK_OR_CONTINUE(record); - operator()(*record); + MRDOCS_CHECK_OR_CONTINUE(infoPtr->isRecord()); + operator()(infoPtr->asRecord()); } } @@ -34,9 +33,8 @@ foldNamespaceMembers(std::vector const& namespaceIds) { Info* namespaceInfoPtr = corpus_.find(namespaceId); MRDOCS_CHECK_OR_CONTINUE(namespaceInfoPtr); - auto* ns = dynamic_cast(namespaceInfoPtr); - MRDOCS_CHECK_OR_CONTINUE(ns); - operator()(*ns); + MRDOCS_CHECK_OR_CONTINUE(namespaceInfoPtr->isNamespace()); + operator()(namespaceInfoPtr->asNamespace()); } } @@ -49,13 +47,13 @@ findBaseClassPermutation( { Info* info = corpus.find(contextId); MRDOCS_CHECK_OR(info, SymbolID::invalid); - if (auto* record = dynamic_cast(info)) + if (auto const* record = info->asRecordPtr()) { for (auto const& base: record->Bases) { auto const baseInfo = corpus.find(base.Type->namedSymbol()); MRDOCS_CHECK_OR_CONTINUE(baseInfo); - auto const baseRecord = dynamic_cast(baseInfo); + auto const baseRecord = baseInfo->asRecordPtr(); MRDOCS_CHECK_OR_CONTINUE(baseRecord); RecordTranche* tranchesPtrs[] = { &baseRecord->Interface.Public, @@ -76,7 +74,7 @@ findBaseClassPermutation( Info* baseFuncMember = corpus.find(baseID); MRDOCS_CHECK_OR_CONTINUE(baseFuncMember); MRDOCS_CHECK_OR_CONTINUE(baseFuncMember->isOverloads()); - auto* overloads = dynamic_cast(baseFuncMember); + auto* overloads = baseFuncMember->asOverloadsPtr(); MRDOCS_CHECK_OR_CONTINUE(overloads); // Does this overload set have the same functions MRDOCS_CHECK_OR_CONTINUE( @@ -104,7 +102,7 @@ foldOverloads(SymbolID const& contextId, std::vector& functionIds) // Get the FunctionInfo for the current id auto recordInfoPtr = corpus_.find(*functionIdIt); MRDOCS_CHECK_OR_CONTINUE(recordInfoPtr); - auto* function = dynamic_cast(recordInfoPtr); + auto* function = recordInfoPtr->asFunctionPtr(); MRDOCS_CHECK_OR_CONTINUE(function); // Check if the FunctionInfo is unique @@ -163,7 +161,7 @@ foldOverloads(SymbolID const& contextId, std::vector& functionIds) { Info* otherInfoPtr = corpus_.find(*otherIt); MRDOCS_CHECK_OR_CONTINUE(otherInfoPtr); - auto* otherFunction = dynamic_cast(otherInfoPtr); + auto* otherFunction = otherInfoPtr->asFunctionPtr(); MRDOCS_CHECK_OR_CONTINUE(otherFunction); if (function->Name == otherFunction->Name) { @@ -201,7 +199,7 @@ operator()(RecordInfo& I) MRDOCS_CHECK_OR(NI.id); Info* baseInfo = corpus_.find(NI.id); MRDOCS_CHECK_OR(baseInfo); - auto* baseRecord = dynamic_cast(baseInfo); + auto* baseRecord = baseInfo->asRecordPtr(); MRDOCS_CHECK_OR(baseRecord); operator()(*baseRecord); } diff --git a/src/lib/Metadata/Finalizers/OverloadsFinalizer.hpp b/src/lib/Metadata/Finalizers/OverloadsFinalizer.hpp index fc5c70aff..9fe914cdd 100644 --- a/src/lib/Metadata/Finalizers/OverloadsFinalizer.hpp +++ b/src/lib/Metadata/Finalizers/OverloadsFinalizer.hpp @@ -50,7 +50,8 @@ class OverloadsFinalizer { auto const globalPtr = corpus_.find(SymbolID::global); MRDOCS_CHECK_OR(globalPtr); - operator()(*dynamic_cast(globalPtr)); + MRDOCS_ASSERT(globalPtr->isNamespace()); + operator()(globalPtr->asNamespace()); } void diff --git a/src/lib/Metadata/Finalizers/SortMembersFinalizer.cpp b/src/lib/Metadata/Finalizers/SortMembersFinalizer.cpp index 29f35674e..cf5e882b6 100644 --- a/src/lib/Metadata/Finalizers/SortMembersFinalizer.cpp +++ b/src/lib/Metadata/Finalizers/SortMembersFinalizer.cpp @@ -158,8 +158,8 @@ struct SymbolIDCompareFn (lhsOp && *lhsOp == OperatorKind::Equal && rhsOp && *rhsOp == OperatorKind::Equal)) { - auto& lhsF = dynamic_cast(lhs); - auto& rhsF = dynamic_cast(rhs); + auto& lhsF = lhs.asFunction(); + auto& rhsF = rhs.asFunction(); if (lhsF.Params.size() == 1 && rhsF.Params.size() == 1) { auto isCopyOrMoveConstOrAssign = [](FunctionInfo const& I) { @@ -276,7 +276,7 @@ sortNamespaceMembers(std::vector& ids) { auto infoPtr = corpus_.find(id); MRDOCS_CHECK_OR_CONTINUE(infoPtr); - auto* ns = dynamic_cast(infoPtr); + auto* ns = infoPtr->asNamespacePtr(); MRDOCS_CHECK_OR_CONTINUE(ns); operator()(*ns); } @@ -290,7 +290,7 @@ sortRecordMembers(std::vector& ids) { auto infoPtr = corpus_.find(id); MRDOCS_CHECK_OR_CONTINUE(infoPtr); - auto* record = dynamic_cast(infoPtr); + auto* record = infoPtr->asRecordPtr(); MRDOCS_CHECK_OR_CONTINUE(record); operator()(*record); } @@ -304,7 +304,7 @@ sortOverloadMembers(std::vector& ids) { auto infoPtr = corpus_.find(id); MRDOCS_CHECK_OR_CONTINUE(infoPtr); - auto* overloads = dynamic_cast(infoPtr); + auto* overloads = infoPtr->asOverloadsPtr(); MRDOCS_CHECK_OR_CONTINUE(overloads); operator()(*overloads); } diff --git a/src/lib/Metadata/Finalizers/SortMembersFinalizer.hpp b/src/lib/Metadata/Finalizers/SortMembersFinalizer.hpp index 192b81fd5..f9bcbc8f5 100644 --- a/src/lib/Metadata/Finalizers/SortMembersFinalizer.hpp +++ b/src/lib/Metadata/Finalizers/SortMembersFinalizer.hpp @@ -59,7 +59,8 @@ class SortMembersFinalizer { Info* globalPtr = corpus_.find(SymbolID::global); MRDOCS_CHECK_OR(globalPtr); - operator()(*dynamic_cast(globalPtr)); + MRDOCS_ASSERT(globalPtr->isNamespace()); + operator()(globalPtr->asNamespace()); } void diff --git a/src/lib/Metadata/Info.cpp b/src/lib/Metadata/Info.cpp index db2746b0f..077c60bb2 100644 --- a/src/lib/Metadata/Info.cpp +++ b/src/lib/Metadata/Info.cpp @@ -40,7 +40,7 @@ void merge(Info& I, Info&& Other) { MRDOCS_ASSERT(I.id); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asSourceInfo(), std::move(Other.asSourceInfo())); if (I.Name == "") { I.Name = Other.Name; diff --git a/src/lib/Metadata/Info/Concept.cpp b/src/lib/Metadata/Info/Concept.cpp index 3204acc64..a0cdb3a9c 100644 --- a/src/lib/Metadata/Info/Concept.cpp +++ b/src/lib/Metadata/Info/Concept.cpp @@ -55,14 +55,14 @@ operator<=>(ConceptInfo const& other) const return cmp; } } - return dynamic_cast(*this) <=> dynamic_cast(other); + return this->asInfo() <=> other.asInfo(); } void merge(ConceptInfo& I, ConceptInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (I.Constraint.Written.empty()) { I.Constraint = std::move(Other.Constraint); diff --git a/src/lib/Metadata/Info/Enum.cpp b/src/lib/Metadata/Info/Enum.cpp index d84e249fa..47405e1f5 100644 --- a/src/lib/Metadata/Info/Enum.cpp +++ b/src/lib/Metadata/Info/Enum.cpp @@ -38,7 +38,7 @@ void merge(EnumInfo& I, EnumInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.Scoped) { I.Scoped = Other.Scoped; diff --git a/src/lib/Metadata/Info/EnumConstant.cpp b/src/lib/Metadata/Info/EnumConstant.cpp index 98a0188b1..558ed222b 100644 --- a/src/lib/Metadata/Info/EnumConstant.cpp +++ b/src/lib/Metadata/Info/EnumConstant.cpp @@ -19,7 +19,7 @@ void merge(EnumConstantInfo& I, EnumConstantInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (I.Initializer.Written.empty()) { I.Initializer = std::move(Other.Initializer); diff --git a/src/lib/Metadata/Info/Field.cpp b/src/lib/Metadata/Info/Field.cpp index ae31c6966..b6ba7f364 100644 --- a/src/lib/Metadata/Info/Field.cpp +++ b/src/lib/Metadata/Info/Field.cpp @@ -19,7 +19,7 @@ void merge(FieldInfo& I, FieldInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.Type) { I.Type = std::move(Other.Type); diff --git a/src/lib/Metadata/Info/Friend.cpp b/src/lib/Metadata/Info/Friend.cpp index 9a99be0ab..7b387997d 100644 --- a/src/lib/Metadata/Info/Friend.cpp +++ b/src/lib/Metadata/Info/Friend.cpp @@ -19,7 +19,7 @@ void merge(FriendInfo& I, FriendInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.FriendSymbol) { I.FriendSymbol = Other.FriendSymbol; diff --git a/src/lib/Metadata/Info/Function.cpp b/src/lib/Metadata/Info/Function.cpp index f3147ab7d..702cd5082 100644 --- a/src/lib/Metadata/Info/Function.cpp +++ b/src/lib/Metadata/Info/Function.cpp @@ -379,14 +379,14 @@ operator<=>(FunctionInfo const& other) const return cmp; } } - return dynamic_cast(*this) <=> dynamic_cast(other); + return this->asInfo() <=> other.asInfo(); } void merge(FunctionInfo& I, FunctionInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (I.Class == FunctionClass::Normal) { I.Class = Other.Class; diff --git a/src/lib/Metadata/Info/Guide.cpp b/src/lib/Metadata/Info/Guide.cpp index 9ec5712d9..391f0bb95 100644 --- a/src/lib/Metadata/Info/Guide.cpp +++ b/src/lib/Metadata/Info/Guide.cpp @@ -65,14 +65,14 @@ operator<=>(GuideInfo const& other) const return cmp; } } - return dynamic_cast(*this) <=> dynamic_cast(other); + return this->asInfo() <=> other.asInfo(); } void merge(GuideInfo& I, GuideInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.Deduced) { I.Deduced = std::move(Other.Deduced); diff --git a/src/lib/Metadata/Info/Namespace.cpp b/src/lib/Metadata/Info/Namespace.cpp index ff4e074a7..5ae737ac8 100644 --- a/src/lib/Metadata/Info/Namespace.cpp +++ b/src/lib/Metadata/Info/Namespace.cpp @@ -19,7 +19,7 @@ std::strong_ordering NamespaceInfo:: operator<=>(NamespaceInfo const& other) const { - if (auto const res = dynamic_cast(*this) <=> dynamic_cast(other); + if (auto const res = this->asInfo() <=> other.asInfo(); std::is_neq(res)) { return res; @@ -106,7 +106,7 @@ void merge(NamespaceInfo& I, NamespaceInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); merge(I.Members, std::move(Other.Members)); reduceNames(I.UsingDirectives, std::move(Other.UsingDirectives)); I.IsInline |= Other.IsInline; diff --git a/src/lib/Metadata/Info/NamespaceAlias.cpp b/src/lib/Metadata/Info/NamespaceAlias.cpp index f30eb6738..a8afd5897 100644 --- a/src/lib/Metadata/Info/NamespaceAlias.cpp +++ b/src/lib/Metadata/Info/NamespaceAlias.cpp @@ -19,7 +19,7 @@ void merge(NamespaceAliasInfo& I, NamespaceAliasInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.AliasedSymbol) { I.AliasedSymbol = std::move(Other.AliasedSymbol); diff --git a/src/lib/Metadata/Info/Overloads.cpp b/src/lib/Metadata/Info/Overloads.cpp index b91078ff0..ddebdd344 100644 --- a/src/lib/Metadata/Info/Overloads.cpp +++ b/src/lib/Metadata/Info/Overloads.cpp @@ -32,7 +32,7 @@ OverloadsInfo(SymbolID const& Parent, std::string_view Name) noexcept void merge(OverloadsInfo& I, OverloadsInfo&& Other) { - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); namespace stdr = std::ranges; namespace stdv = std::ranges::views; auto newMembers = stdv::filter(Other.Members, [&](auto const& Member) { @@ -61,7 +61,7 @@ addMember(OverloadsInfo& I, FunctionInfo const& Member) I.ReturnType = {}; } } - merge(dynamic_cast(I), dynamic_cast(Member)); + merge(I.asSourceInfo(), Member.asSourceInfo()); I.Members.push_back(Member.id); } diff --git a/src/lib/Metadata/Info/Record.cpp b/src/lib/Metadata/Info/Record.cpp index e8c2bcbb3..00859cb8a 100644 --- a/src/lib/Metadata/Info/Record.cpp +++ b/src/lib/Metadata/Info/Record.cpp @@ -88,7 +88,7 @@ operator<=>(RecordInfo const& other) const return cmp; } } - return dynamic_cast(*this) <=> dynamic_cast(other); + return this->asInfo() <=> other.asInfo(); } void @@ -118,7 +118,7 @@ merge(RecordInterface& I, RecordInterface&& Other) void merge(RecordInfo& I, RecordInfo&& Other) { - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (Other.KeyKind != RecordKeyKind::Struct && I.KeyKind != Other.KeyKind) { diff --git a/src/lib/Metadata/Info/Typedef.cpp b/src/lib/Metadata/Info/Typedef.cpp index e82a6a6fe..47f13cd2b 100644 --- a/src/lib/Metadata/Info/Typedef.cpp +++ b/src/lib/Metadata/Info/Typedef.cpp @@ -56,13 +56,13 @@ operator<=>(TypedefInfo const& other) const return cmp; } } - return dynamic_cast(*this) <=> dynamic_cast(other); + return this->asInfo() <=> other.asInfo(); } void merge(TypedefInfo& I, TypedefInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.IsUsing) { I.IsUsing = Other.IsUsing; diff --git a/src/lib/Metadata/Info/Using.cpp b/src/lib/Metadata/Info/Using.cpp index e5d76989d..1f3cbe650 100644 --- a/src/lib/Metadata/Info/Using.cpp +++ b/src/lib/Metadata/Info/Using.cpp @@ -38,7 +38,7 @@ void merge(UsingInfo& I, UsingInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); reduceSymbolIDs(I.UsingSymbols, std::move(Other.UsingSymbols)); if (I.Class == UsingClass::Normal) { diff --git a/src/lib/Metadata/Info/Variable.cpp b/src/lib/Metadata/Info/Variable.cpp index 598b18a1d..f31a0052e 100644 --- a/src/lib/Metadata/Info/Variable.cpp +++ b/src/lib/Metadata/Info/Variable.cpp @@ -55,14 +55,14 @@ operator<=>(VariableInfo const& other) const return cmp; } } - return dynamic_cast(*this) <=> dynamic_cast(other); + return this->asInfo() <=> other.asInfo(); } void merge(VariableInfo& I, VariableInfo&& Other) { MRDOCS_ASSERT(canMerge(I, Other)); - merge(dynamic_cast(I), std::move(dynamic_cast(Other))); + merge(I.asInfo(), std::move(Other.asInfo())); if (!I.Type) { I.Type = std::move(Other.Type); diff --git a/src/lib/Support/LegibleNames.cpp b/src/lib/Support/LegibleNames.cpp index 19f9a1f15..bb8b1d5b1 100644 --- a/src/lib/Support/LegibleNames.cpp +++ b/src/lib/Support/LegibleNames.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,7 @@ namespace clang::mrdocs { namespace { -std::string_view +std::string getUnnamedInfoName(Info const& I) { // All valid c++ identifiers begin with @@ -46,54 +47,41 @@ getUnnamedInfoName(Info const& I) "2destructor" }; std::size_t func_idx = 0; - if (auto const* FI = dynamic_cast(&I)) + if (auto const* FI = I.asFunctionPtr()) { // don't use the reserved prefix for overloaded operators if(FI->Class == FunctionClass::Normal && FI->OverloadedOperator != OperatorKind::None) { - return getSafeOperatorName( - FI->OverloadedOperator, true); + return std::string(getSafeOperatorName( + FI->OverloadedOperator, true)); } func_idx = to_underlying(FI->Class); } - if (auto const* FI = dynamic_cast(&I)) + if (auto const* FI = I.asOverloadsPtr()) { // don't use the reserved prefix for overloaded operators if(FI->Class == FunctionClass::Normal && FI->OverloadedOperator != OperatorKind::None) { - return getSafeOperatorName( - FI->OverloadedOperator, true); + return std::string(getSafeOperatorName( + FI->OverloadedOperator, true)); } func_idx = to_underlying(FI->Class); } MRDOCS_ASSERT(func_idx < std::size(func_reserved)); - return func_reserved[func_idx]; + return std::string(func_reserved[func_idx]); } - static - constexpr - std::string_view - reserved[] = { - "00namespace", - "01record", - "02function", - "03overloads", - "04enum", - "05enum-constant", - "06typedef", - "07variable", - "08field", - "09friend", - "10guide", - "11namespace-alias", - "12using", - "13concept" - }; std::size_t const idx = to_underlying(I.Kind) - 1; - MRDOCS_ASSERT(idx < std::size(reserved)); - return reserved[idx]; + std::string res; + // push idx as two digits + res.push_back(static_cast('0' + (idx / 10))); + res.push_back(static_cast('0' + (idx % 10))); + // push the name of the kind as kebab-case + auto const kindStr = std::string(toString(I.Kind)); + res += toKebabCase(kindStr); + return res; } } // namespace @@ -116,7 +104,7 @@ class LegibleNames::Impl { /* Raw unqualified name for the symbol */ - std::string_view unqualified; + std::string unqualified; /* Number of characters from the SymbolID string required to uniquely identify this symbol @@ -134,7 +122,7 @@ class LegibleNames::Impl /* Maps unqualified names to all symbols with that name within the current scope */ - std::unordered_multimap disambiguation_map_; + UnorderedStringMultiMap disambiguation_map_; public: /* Build the map of legible names for all symbols in the corpus @@ -172,10 +160,9 @@ class LegibleNames::Impl buildLegibleMember(M, raw); // Traverse non inherited function overloads inline - if (M.isOverloads()) + if (auto* MO = M.asOverloadsPtr()) { - auto const& O = static_cast(M); - corpus_.traverse(O, [this, &I](Info const& M2) + corpus_.traverse(*MO, [this, &I](Info const& M2) { // Not inherited in regard to I MRDOCS_CHECK_OR(M2.Parent == I.id); @@ -215,7 +202,7 @@ class LegibleNames::Impl /* @copydoc getRawUnqualified(SymbolID const&) */ - std::string_view + std::string getRawUnqualified(Info const& I) { MRDOCS_ASSERT(I.id && I.id != SymbolID::global); @@ -224,7 +211,7 @@ class LegibleNames::Impl return getUnnamedInfoName(I); } - return visit(I, [&](T const& t) -> std::string_view + return visit(I, [&](T const& t) -> std::string { MRDOCS_ASSERT(!t.Name.empty()); if constexpr( @@ -256,8 +243,8 @@ class LegibleNames::Impl { // Generate the legible name information for this symbol auto const idAsString = toBase16(I.id, true); - LegibleNameInfo LI(rawName, 0, idAsString); - LegibleNameInfo& info = map_.emplace(I.id, LI).first->second; + LegibleNameInfo LI(std::string(rawName), 0, idAsString); + LegibleNameInfo& info = map_.emplace(I.id, std::move(LI)).first->second; // Look for symbols with the same unqualified name auto [first, last] = disambiguation_map_.equal_range(rawName); @@ -335,8 +322,8 @@ class LegibleNames::Impl { MRDOCS_ASSERT(corpus_.exists(id)); auto const& I = corpus_.get(id); - auto const curParent = I.Parent; - if (curParent != SymbolID::invalid && + if (auto const curParent = I.Parent; + curParent != SymbolID::invalid && curParent != SymbolID::global) { getLegibleQualified(result, curParent, delim); diff --git a/test-files/golden-tests/config/legible-names/constructor.adoc b/test-files/golden-tests/config/legible-names/constructor.adoc new file mode 100644 index 000000000..b000bbbbc --- /dev/null +++ b/test-files/golden-tests/config/legible-names/constructor.adoc @@ -0,0 +1,207 @@ += Reference +:mrdocs: + +[#index] +== Global namespace + +=== Types + +[cols=1] +|=== +| Name +| <> +|=== + +[#X] +== X + +=== Synopsis + +Declared in `<constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +struct X; +---- + +=== Member Functions + +[cols=2] +|=== +| Name +| Description +| <> [.small]#[constructor]# +| Constructors +|=== + +[#X-2constructor-08] +== <>::X + +Constructors + +=== Synopses + +Declared in `<constructor.cpp>` + +Default constructor + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>(); +---- + +[.small]#<># + +Copy constructor + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>(<> const& other); +---- + +[.small]#<># + +Move constructor + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>(<>&& other); +---- + +[.small]#<># + +Construct from `int` + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>(int value); +---- + +[.small]#<># + +Construct from `double` + + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +<>(double value); +---- + +[.small]#<># + +[#X-2constructor-0e8] +== <>::X + +Default constructor + +=== Synopsis + +Declared in `<constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +X(); +---- + +[#X-2constructor-0e0] +== <>::X + +Copy constructor + +=== Synopsis + +Declared in `<constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +X(<> const& other); +---- + +=== Parameters + +[cols=2] +|=== +| Name +| Description +| *other* +| The object to copy construct from +|=== + +[#X-2constructor-069] +== <>::X + +Move constructor + +=== Synopsis + +Declared in `<constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +X(<>&& other); +---- + +=== Parameters + +[cols=2] +|=== +| Name +| Description +| *other* +| The object to move construct from +|=== + +[#X-2constructor-07] +== <>::X + +Construct from `int` + +=== Synopsis + +Declared in `<constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +X(int value); +---- + +=== Parameters + +[cols=2] +|=== +| Name +| Description +| *value* +| The value to construct from +|=== + +[#X-2constructor-06f] +== <>::X + +Construct from `double` + +=== Synopsis + +Declared in `<constructor.cpp>` + +[source,cpp,subs="verbatim,replacements,macros,-callouts"] +---- +X(double value); +---- + +=== Parameters + +[cols=2] +|=== +| Name +| Description +| *value* +| The value to construct from +|=== + + +[.small]#Created with https://www.mrdocs.com[MrDocs]# diff --git a/test-files/golden-tests/config/legible-names/constructor.cpp b/test-files/golden-tests/config/legible-names/constructor.cpp new file mode 100644 index 000000000..5d39f0dbd --- /dev/null +++ b/test-files/golden-tests/config/legible-names/constructor.cpp @@ -0,0 +1,9 @@ +// Disambiguate constructors + +struct X { + X(); + X(X const& other); + X(X&& other); + X(int); + X(double); +}; \ No newline at end of file diff --git a/test-files/golden-tests/config/legible-names/constructor.html b/test-files/golden-tests/config/legible-names/constructor.html new file mode 100644 index 000000000..82250f571 --- /dev/null +++ b/test-files/golden-tests/config/legible-names/constructor.html @@ -0,0 +1,276 @@ + + +Reference + + +
+

Reference

+
+
+

Global namespace

+
+

Types

+ + + + + + + + + + +
Name
X
+ +
+
+
+

X

+
+
+

Synopsis

+
+Declared in <constructor.cpp>
+
+
+struct X;
+
+
+
+

Member Functions

+ + + + + + + + + + + +
NameDescription
X [constructor]Constructors
+ + + +
+
+
+

X::X

+
+Constructors + +
+
+
+

Synopses

+
+Declared in <constructor.cpp>
+Default constructor +
+
+X();
+
+
» more... + +Copy constructor +
+
+X(X const& other);
+
+
» more... + +Move constructor +
+
+X(X&& other);
+
+
» more... + +Construct from int +
+
+X(int value);
+
+
» more... + +Construct from double +
+
+X(double value);
+
+
» more... + + +
+
+
+
+

X::X

+
+Default constructor + +
+
+
+

Synopsis

+
+Declared in <constructor.cpp>
+
+
+X();
+
+
+
+
+
+
+

X::X

+
+Copy constructor + +
+
+
+

Synopsis

+
+Declared in <constructor.cpp>
+
+
+X(X const& other);
+
+
+
+
+

Parameters

+ + + + + + + + + + + + + +
NameDescription
otherThe object to copy construct from
+
+
+
+
+

X::X

+
+Move constructor + +
+
+
+

Synopsis

+
+Declared in <constructor.cpp>
+
+
+X(X&& other);
+
+
+
+
+

Parameters

+ + + + + + + + + + + + + +
NameDescription
otherThe object to move construct from
+
+
+
+
+

X::X

+
+Construct from int + +
+
+
+

Synopsis

+
+Declared in <constructor.cpp>
+
+
+X(int value);
+
+
+
+
+

Parameters

+ + + + + + + + + + + + + +
NameDescription
valueThe value to construct from
+
+
+
+
+

X::X

+
+Construct from double + +
+
+
+

Synopsis

+
+Declared in <constructor.cpp>
+
+
+X(double value);
+
+
+
+
+

Parameters

+ + + + + + + + + + + + + +
NameDescription
valueThe value to construct from
+
+
+ +
+
+

Created with MrDocs

+
+ + \ No newline at end of file diff --git a/test-files/golden-tests/config/legible-names/constructor.xml b/test-files/golden-tests/config/legible-names/constructor.xml new file mode 100644 index 000000000..f2e44968b --- /dev/null +++ b/test-files/golden-tests/config/legible-names/constructor.xml @@ -0,0 +1,79 @@ + + + + + + + + + + Default constructor + + + + + + + + + + + + + Copy constructor + + + The object to copy construct from + + + + + + + + + + + + + Move constructor + + + The object to move construct from + + + + + + + + + + + Construct from + int + + + The value to construct from + + + + + + + + + + + Construct from + double + + + The value to construct from + + + + + +