Skip to content

Computed properties via reflection (MRDOCS_DESCRIBE_COMPUTED_PROPERTIES) #1215

@gennaroprota

Description

@gennaroprota

Discussed on #1199. Many of the values templates read off a symbol are not stored corpus fields but derived from stored ones; e.g.: isRegular, isSeeBelow, isImplementationDefined, isDependency, class. Today, these reach the DOM through custom tag_invoke io.map(...) overloads (for example in SymbolBase.hpp) or through member functions, with no uniform, reflection-visible registration. A new derived value gets added either as another custom overload or, worse, as a stored is* field on the corpus purely so a template can read it (see isListedOnPrimary on #1199).

Goal

A MRDOCS_DESCRIBE_COMPUTED_PROPERTIES mechanism that registers, per type, a list of named computed properties, each backed by a free-function getter. It mirrors MRDOCS_DESCRIBE_KINDS: one registration line per type, the getters live as free functions next to the type, and reflection discovers the list via ADL.

Sketch:

// next to the type
bool computedIsRegular(Symbol const& s) { return s.Extraction == ExtractionMode::Regular; }
// ... other getters ...

MRDOCS_DESCRIBE_COMPUTED_PROPERTIES(Symbol,
    (isRegular, computedIsRegular),
    (isSeeBelow, computedIsSeeBelow))

mrdocs_computed_properties_fn(T**) returns the list of {name, getter} descriptors; the DOM materializer iterates it and calls each getter when building the lazy object.

Why this, and not only predicate-passing (#1213)

Two reasons, and the second is the important one:

  1. Separation and schema. Computed properties are derived, so the XML writer skips them (no schema growth, no golden churn), while the Handlebars/DOM schema includes them. The documentation can mark the distinction. Stored fields stay authoritative; derived values are clearly derived.
  2. Performance. A computed property is a compiled C++ call. A Handlebars predicate (Predicate-passing in Handlebars filter helpers (ad-hoc filtering) #1213) is interpreted per element at render time. For the default templates, which run over every symbol, the computed-property path is materially faster. So the is* family belongs here, not behind interpreted predicates. Predicate-passing in Handlebars filter helpers (ad-hoc filtering) #1213's predicate-passing is the right tool only for genuinely ad-hoc, author-time filters where defining a named property would be overkill.

What this replaces and unlocks

  • The custom tag_invoke io.map(...) computed fields in SymbolBase.hpp (and similar) become described computed properties. This continues the direction of the recent refactor that replaced most per-type tag_invoke overloads with a generic template.
  • isListedOnPrimary (the corpus field added on feat: move template specializations and deduction guides off parent scope page #1199) becomes a computed property, and the stored field is removed. That is the first concrete migration target.
  • Future derived values get a uniform home that is fast, reflection-visible, and schema-correct, instead of either a custom overload or a stored is* field.

Open questions

  • Getter signature. Some computed properties are pure functions of the symbol (isRegular). Others need the corpus (isListedOnPrimary depends on the primary's extraction status). The signature is likely (T const&) with an optional (T const&, DomCorpus const*) form; settle how the two coexist.
  • Caching. Whether getters are memoized per symbol per render or recomputed. Most are trivial; some (polymorphic-kind lookups) are not.
  • Name collisions. A computed property name must not shadow a described member; this needs a compile-time or load-time check.
  • Schema emission. How computed properties are tagged in the Handlebars schema and omitted from the XML/RNC schema.
  • Lazy-DOM interplay. Should compose with the lazy-DOM-from-reflection work (Build DOM objects lazily directly from reflection descriptors #1211).

Sequencing

Reuses the MRDOCS_DESCRIBE_KINDS ADL infrastructure (DescribeKinds.hpp), which lands with #1196, so it is cleanest to build once that is on develop. The first migration (isListedOnPrimary) sits on #1199.

Relationship to #1213

Complementary. This issue covers the stable, hot-path derived values (compiled getters). #1213 covers ad-hoc, author-time predicate filtering (interpreted). Computed properties are the preferred tool for anything on a hot path or in the default templates.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions