Skip to content

Conversation

@gennaroprota
Copy link
Collaborator

This introduces Boost.Describe and Boost.Mp11 and applies them across metadata types (symbols, enums, inline elements) to replace hand-written io.map() calls with reflection-based code. This improves maintainability without altering the public API or user-facing features.

@alandefreitas: Please have a look at normalizeMemberName() in SymbolDescribeMapper.hpp: Some names are special-cased there. If you prefer, I can remove the special cases and modify the Handlebars templates to use the canonical names.

@github-actions
Copy link

github-actions bot commented Dec 9, 2025

🚧 Danger.js checks for MrDocs are experimental; expect some rough edges while we tune the rules.

⚠️ Warnings

Warning

Add a brief note about how this change was tested (or why tests are not needed).

Warning

Source changed but no tests or fixtures were updated. Add coverage or label with no-tests-needed / [skip danger tests] when appropriate.

✨ Highlights

  • None noted.

🧾 Changes by Scope

Scope Lines Δ Lines + Lines - Files Δ Files + Files ~ Files ↔ Files -
Source 887 592 295 49 2 47 - -
CI / Roadmap 50 50 - 1 - 1 - -
Third-party 28 28 - 2 2 - - -
Build / Toolchain 18 18 - 1 - 1 - -
Docs 8 8 - 1 - 1 - -
Total 991 696 295 54 4 50 - -

Legend: Files + (added), Files ~ (modified), Files ↔ (renamed), Files - (removed)

🔝 Top Files

  • include/mrdocs/Metadata/Symbol/SymbolDescribeMapper.hpp (Source): 174 lines Δ (+174 / -0)
  • include/mrdocs/Metadata/Symbol/Function.hpp (Source): 75 lines Δ (+34 / -41)
  • include/mrdocs/Metadata/Symbol/EnumToString.hpp (Source): 52 lines Δ (+52 / -0)

Generated by 🚫 dangerJS against 14342ee

#ifndef MRDOCS_API_METADATA_DOCCOMMENT_INLINE_IMAGEINLINE_HPP
#define MRDOCS_API_METADATA_DOCCOMMENT_INLINE_IMAGEINLINE_HPP

#include <boost/describe/class.hpp>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

includes should be ordered from most specific to most general. describe is general. std includes are most general

@gennaroprota gennaroprota force-pushed the develop branch 6 times, most recently from d8c7267 to f3274f4 Compare December 9, 2025 19:06
Copy link
Collaborator

@alandefreitas alandefreitas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job! 👏😀🎉

uses: alandefreitas/cpp-actions/[email protected]
with:
source-dir: ../third-party/boost_describe
git-repository: https://github.com/boostorg/describe
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the url is cheaper in this case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?

CMakeLists.txt Outdated
string(REGEX REPLACE " /W[0-4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

# Boost.Describe + Boost.Mp11 (header-only, fetched via bootstrap.py recipes)
set(BOOST_DESCRIBE_ROOT "${CMAKE_SOURCE_DIR}/build/third-party/source/boost_describe")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded paths are a no-no. 😅 You can write a patch for each that installs and exports them as Boost::describe and Boost::mp11. This way, you still don't depend on the Boost root project. Also, I thought there would be dependency on Boost::config here.

{
tag_invoke(t, io, I.asInfo(), domCorpus);
io.map("aliasedSymbol", I.AliasedSymbol);
mapWithDescribe(io, I, domCorpus);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't mapWithDescribe just iterate the base classes itself?

Copy link
Collaborator Author

@gennaroprota gennaroprota Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it always iterate all bases? I was afraid there was some special case somewhere for which only one base was mapped. If you confirm I can iterate all bases, always, I'll do that :-).

After writing the above comment, I found this:

struct ImageInline final
    : InlineCommonBase<InlineKind::Image>
    , InlineContainer
{
    /** Image source URL or path.
    */
    std::string src;
    /** Alternate text when the image cannot be shown.
    */
    std::string alt;

    /** Order images by source, alt text, and inline children.
    */
    auto operator<=>(ImageInline const&) const = default;
    /** Equality compares source, alt text, and contents.
    */
    bool operator==(ImageInline const&) const noexcept = default;
};

template <class IO>
void
tag_invoke(
    dom::LazyObjectMapTag t,
    IO& io,
    ImageInline const& I,
    DomCorpus const* domCorpus)
{
    tag_invoke(t, io, dynamic_cast<Inline const&>(I), domCorpus);
    tag_invoke(t, io, dynamic_cast<InlineContainer const&>(I), domCorpus);
    mapWithDescribe(io, I, domCorpus);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image?


namespace detail {

/** Helper to determine if a member should be mapped based on its value.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we have all the Boost.Describe related stuff in a single header? And will these headers always be public? But that would make mp11 and describe the first public dependencies of mrdocs, and cmakelists.txt and mrdocs.yml would need to be adapted accordingly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "all the Boost.Describe related stuff"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authors of plugins don't need the Describe data (or do they) so it would be nice not to require plugins to have Boost installed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "all the Boost.Describe related stuff"?

That there should be no #include <boost/whatever.hpp> in public files.

or do they

The members are already "described" for extensions. Authors of plugins are probably going to iterate the members of objects often, but this can be abstracted without exposing boost.

@alandefreitas alandefreitas changed the title refactor(metadata): integrate Boost.Describe to remove manual mapping boilerplate refactor(metadata): integrate Boost.Describe Dec 9, 2025
@alandefreitas
Copy link
Collaborator

@alandefreitas: Please have a look at normalizeMemberName() in SymbolDescribeMapper.hpp: Some names are special-cased there. If you prefer, I can remove the special cases and modify the Handlebars templates to use the canonical names.

Sorry. I forgot to answer this one. 😬

Yes. We're going to use canonical names for everything sooner or later. Since you already made the effort to split this into two tasks, we can do that later rather than sooner. Reflection will enable all kinds of simplifications in the code from now on.

I leave it up to you, though.

… boilerplate

This introduces Boost.Describe and Boost.Mp11 and applies them across
metadata types (symbols, enums, inline elements) to replace hand-written
io.map() calls with reflection-based code. This improves maintainability
without altering the public API or user-facing features.
@alandefreitas
Copy link
Collaborator

Sometimes we get conflicts if we don't rename things for Handlebars, as you notice with "class" and "functionClass", etc. This is because of how handlebars works with recursion, and it's very annoying. I don't know if it solves your problem, but one solution I was going to propose at some point is adding an "@meta" key to all objects to describe the class name, etc (this can also help with other problems we've been having). This way, we would have the proper information to make the distinction in handlebars.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants