feat: schema generation#1178
Conversation
✨ Highlights
🧾 Changes by Scope
🔝 Top Files
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1178 +/- ##
===========================================
- Coverage 82.12% 82.03% -0.09%
===========================================
Files 33 32 -1
Lines 3149 3090 -59
Branches 734 714 -20
===========================================
- Hits 2586 2535 -51
+ Misses 387 385 -2
+ Partials 176 170 -6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
An automated preview of the documentation is available at https://1178.mrdocs.prtest2.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-05-14 07:44:08 UTC |
cdda298 to
b9fac7c
Compare
|
Path coverage is OK, isn't it? I added the PR description. |
alandefreitas
left a comment
There was a problem hiding this comment.
What about documentation? How do I use the feature? What about the schema in the documentation? Do we have no schema files in the repository? How do we check if the files are up to date in CI? Some of the changes in the golden files are also kind of weird (like ids changing and things like that and some groups are just empty, which could probably be removed in the schema - I'm not sure).
The PR is great though. The only reason I left many comment is because the PR is huge. 😅
| // ------------------------------------------------------- | ||
| // Header | ||
| // ------------------------------------------------------- | ||
| line("#"); |
There was a problem hiding this comment.
This main function is kind of hard for a human to read. Is this one of these cases where instead of using reflection to improve the schema, we make the function very complex to match the bad pattern we used to have before?
There was a problem hiding this comment.
Indeed. The function is long because the schema is currently describing what XMLWriter happens to emit. That's bad.
There was a problem hiding this comment.
So has this one been resolved?
There was a problem hiding this comment.
RncSchemaWriter.hpp no longer exists, because we emit RNG directly now. RngSchemaWriter.cpp should be relatively easy to read.
73561af to
f9d5f63
Compare
f9d5f63 to
fb9c795
Compare
`Symbol`'s `tag_invoke` overload added four convenience booleans --
`isRegular`, `isSeeBelow`, `isImplementationDefined`, `isDependency` --
outside the described struct. Because reflection couldn't see them, the
JSON schema writer had to mirror the same hardcoded list.
This removes those booleans and lets templates compare the described
enum directly; e.g.:
{{#if isRegular}} -> {{#if (eq extraction "regular")}}
For the two `filter_by` / `any_of_by` sites that previously keyed on the
booleans, the helper family gains variadic siblings `filter_by_eq` and
`any_of_by_eq` -- signature `(container, key, value1, value2, ...)`.
This addresses review feedback on PR cppalliance#1178.
fb9c795 to
0ae30ec
Compare
`Symbol`'s `tag_invoke` overload added four convenience booleans --
`isRegular`, `isSeeBelow`, `isImplementationDefined`, `isDependency` --
outside the described struct. Because reflection couldn't see them, the
JSON schema writer had to mirror the same hardcoded list.
This removes those booleans and lets templates compare the described
enum directly; e.g.:
{{#if isRegular}} -> {{#if (eq extraction "regular")}}
For the two `filter_by` / `any_of_by` sites that previously keyed on the
booleans, the helper family gains variadic siblings `filter_by_eq` and
`any_of_by_eq` -- signature `(container, key, value1, value2, ...)`.
This addresses review feedback on PR cppalliance#1178.
0ae30ec to
903033b
Compare
Add a --schemas[=<dir>] option that writes a JSON Schema file (mrdocs-dom-schema.json) describing every object and field available to Handlebars templates. The schema is derived from the same compile-time reflection metadata used by MapReflectedType.hpp, so it stays in sync with the code automatically. The option requires no config file or source files — it writes the schema and exits immediately.
OperatorKind was the only enum serialized as a raw integer. All other enums serialize as human-readable strings. Change tag_invoke to use getOperatorName, consistent with the rest.
--schemas now writes both mrdocs-dom-schema.json (Handlebars DOM) and mrdocs.rnc (XML output). The XML schema mirrors XMLWriter.cpp's serialization.
…ClassKind
Replace manual toString and tag_invoke overloads with
MRDOCS_DESCRIBE_ENUM for four enums whose kebab-case names match the
existing string representations.
The XML writer now emits these fields (e.g. <access>public</access>,
<constexpr>constexpr</constexpr>) where they were previously silently
skipped. None/none sentinel values are suppressed via a generic
has_none_enumerator check.
TypeKind stays manual because toKebabCase("LValueReference") produces
"l-value-reference", not the established "lvalue-reference".
… --schemas This guarantees the RELAX NG schema stays in sync with the C++ type definitions. Every CI run now validates all golden test XML files against a schema derived from the same reflection metadata that produces the XML.
This adds a small lookup table keyed by (typeName, memberName) carrying hand-written descriptions for the DOM seen by Handlebars templates which become "description" fields in the JSON schema.
The newly-added JsonEmitter.hpp duplicated functionality already provided by `dom::JSON::stringify`. This drops the new header and uses the existing `stringify`.
The new function name is more descriptive. Contextually, this expands the doc-comment to spell out what the function returns.
The schema headers are only used by ToolMain and the unit tests. They don't need to live under include/mrdocs/.
output XMLWriter silently dropped three kinds of data: - `SpecializationName::TemplateArgs`: `Polymorphic<Name>` fell into `writePolymorphic`'s generic branch with `T` deduced to the base Name (`Polymorphic::operator*` returns a base reference), so only `Name`'s own described members were emitted. Template specializations rendered as `<name>SmallVector</name>` rather than `<specialization-name>SmallVector<...></specialization-name>`. - `NoexceptInfo`: no `MRDOCS_DESCRIBE_STRUCT` - it serializes to a string via `tag_invoke`, which `writeElement` had no path for. Functions with noexcept-specifications produced no `<noexcept>` element. - `ExplicitInfo`: same pattern. explicit constructors and conversion operators produced no `<explicit>` element. This adds a `NameKind` branch in `writePolymorphic` (using a "-name" suffix on the kind tag to disambiguate from the `Name::Identifier` field), and adds a `NoexceptInfo`/`ExplicitInfo` branch in `writeElement` that emits the `toString()` value as text, skipping the empty case. Also update `RncSchemaWriter` to match: `Polymorphic<Name>` -> `AnyName`, drop `NoexceptInfo`/`ExplicitInfo` from the omit list. Most XML golden fixtures regenerate to include the now-emitted elements.
The XMLTags helper in src/lib/Gen/Xml/ contained two pieces of machinery that aren't specific to XML doc generation: an XML escaper (xmlEscape) and a tag/indent stream emitter. A RELAX NG schema writer, which will be introduced with the next commit, also needs them. So, we factored them out.
The --schemas option now writes a RELAX NG XML document directly. This gets rid of the trang RNC->RNG conversion step. Which, in turn, means we no longer need Java. The bootstrap script dependency on Java will be removed with the next commit.
The bootstrap script checked for Java because the build needed it to run trang.jar, which converted the RNC schema to RNG. But trang.jar is no longer used (the --schemas option directly emits a .rng), so Java is no longer needed.
The schema writer emits a `description` field for every type and every described member it touches, looking it up from DomDescriptions.hpp. When the lookup failed, it silently returned an empty string, so forgetting a description caused an undocumented `$defs` entry to be silently emitted. This adds an assert that fires when the lookup of a type or a member finds no entry. This allowed finding many missing entries, which have been added. Any future described type added to the schema trips the assert at build time until descriptions for it and its members are provided.
…ation targets Both schema files are now committed under docs/, parallel to the existing docs/mrdocs.schema.json (the YAML config schema) and are exposed to the Antora docs site as downloadable attachments. Two new CTest targets, `rng-schema-check` and `dom-schema-check`, run `cmake -E compare_files` between the freshly-generated schemas in the build tree and the checked-in copies; drift fails the test. The schemas custom_command is lifted out of the LibXml2 conditional so the freshness checks run independently of whether libxml2 is available. .gitattributes pins the two schema files to LF line endings, because --schemas emits LF line endings and we do a byte-for-byte comparison.
This replaces the hand-written DOM reference with one generated from mrdocs-dom-schema.json. A new Antora extension walks the file's `$defs` in source order and emits one section per type.
`Symbol`'s `tag_invoke` overload added four convenience booleans --
`isRegular`, `isSeeBelow`, `isImplementationDefined`, `isDependency` --
outside the described struct. Because reflection couldn't see them, the
JSON schema writer had to mirror the same hardcoded list.
This removes those booleans and lets templates compare the described
enum directly; e.g.:
{{#if isRegular}} -> {{#if (eq extraction "regular")}}
For the two `filter_by` / `any_of_by` sites that previously keyed on the
booleans, the helper family gains variadic siblings `filter_by_eq` and
`any_of_by_eq` -- signature `(container, key, value1, value2, ...)`.
This addresses review feedback on PR cppalliance#1178.
903033b to
019d019
Compare
|
Thanks, removing the Is there a way to let reflection drive the missing parts that are manually written right now? If that's not possible right now, could we open an issue to track it? This is exactly what reflection was meant to solve. Separately, as I mentioned in the previous comment, a few of the golden XML changes still looked odd to me. |


This adds a
--schemas[=<dir>]option that emits two schemas derived from the reflection metadata in the source tree: mrdocs-dom-schema.json, which describes the Handlebars DOM produced by the generator, and mrdocs.rng (RelaxNG), which describes the XML output. The hand-written mrdocs.rnc is removed and replaced by the generated .rng everywhere CI used it, eliminating drift between the schema and the actual output.The schemas are produced by walking the reflection types and member descriptions in the source tree, so they stay in sync with the code automatically as new metadata types are added. The DOM reference documentation is switched from a hand-maintained page to one generated by an Antora extension that reads the JSON schema.
A generic XML emitter is factored out of the existing
XMLTags/XMLWritercode into src/lib/Support/Xml.{cpp,hpp}, and several reflection types (AccessKind,ConstexprKind,OperatorKind,StorageClassKind,ParamDirection,TypeKind) are made describable through newMapReflectedType/MergeReflectedType/TypeTraitsheaders in include/mrdocs/Support/. Three small fixes ride along:OperatorKindis serialized as a string in the DOM (not the underlying enum), the XML emitter no longer drops template args /noexcept/explicitspecifiers, andasserts fire when a reflection type or member lacks a description.Changes
--schemaswired through tool/ToolArgs.{cpp,hpp} and tool/ToolMain.cpp. Several specifier headers in include/mrdocs/Metadata/ refactored alongside newMapReflectedType,MergeReflectedType, andTypeTraitsheaders in include/mrdocs/Support/. Schema-writer headers live in src/lib/Schemas/ (deliberately kept out of the public API).noexcept,explicit) that the old XML writer was silently dropping. These are intentional output corrections.--schemas. docs/extensions/dom-reference.js renders the DOM reference page from the JSON schema; the corresponding hand-written section was removed from generators.adoc. mrdocs-dom-schema.json and mrdocs.rng are also linked as downloadable attachments.CMakeLists.txtupdated so mrdocs.rng and mrdocs-dom-schema.json are emitted and verified during the build. The Java prerequisite (previously needed to process mrdocs.rnc) is removed.noexcept, andexplicitattributes that were silently omitted before; consumers parsing the XML and not expecting those attributes may need to adjust.Testing
noexcept/explicitwill cause the golden tests to fail.assertfires when a reflection type or member lacks a description, so any future addition to the reflection metadata that ships without schema metadata trips immediately in CI rather than silently producing an under-specified schema.Documentation
Two pieces:
--schemasoption.