Skip to content

Commit 0ae30ec

Browse files
committed
refactor: drop Symbol's isXxx booleans
`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 #1178.
1 parent 2171549 commit 0ae30ec

11 files changed

Lines changed: 125 additions & 71 deletions

File tree

include/mrdocs/Metadata/Symbol/SymbolBase.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,15 @@ MRDOCS_DESCRIBE_STRUCT(
180180
Extraction, IsCopyFromInherited, Parent, doc)
181181
)
182182

183-
/** Map a Symbol to a dom::Object with computed extraction properties.
183+
/** Map a Symbol to a dom::Object plus a `class` discriminator.
184+
185+
The `class` field is the only synthesized member here: templates
186+
that consume a mixed array of DOM objects use it to tell Symbol
187+
entries apart from Type or Name entries. Everything else comes
188+
from reflection over the described struct, including the
189+
`extraction` enum that templates compare with `(eq extraction
190+
"regular")` etc.
191+
184192
@param io The IO object to map into.
185193
@param I The Symbol to map.
186194
@param domCorpus The DomCorpus context.
@@ -196,10 +204,6 @@ tag_invoke(
196204
MRDOCS_ASSERT(domCorpus);
197205
mapReflectedType<false>(io, I, domCorpus);
198206
io.map("class", std::string("symbol"));
199-
io.map("isRegular", I.Extraction == ExtractionMode::Regular);
200-
io.map("isSeeBelow", I.Extraction == ExtractionMode::SeeBelow);
201-
io.map("isImplementationDefined", I.Extraction == ExtractionMode::ImplementationDefined);
202-
io.map("isDependency", I.Extraction == ExtractionMode::Dependency);
203207
}
204208

205209
//------------------------------------------------

share/mrdocs/addons/generator/adoc/partials/symbol.adoc.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@
249249
{{! Recursive index for multipage global namespace }}
250250
{{#if (and (eq symbol.kind "namespace") @root.config.multipage @root.config.global-namespace-index (eq @root.symbol.kind "namespace") (not @root.symbol.name) (not @root.symbol.parent)) }}
251251
{{#each symbol.members.namespaces}}
252-
{{#if isRegular}}
252+
{{#if (eq extraction "regular")}}
253253
{{#> markup/dynamic-level-h id=null }}{{> symbol/qualified-name . }} namespace{{/markup/dynamic-level-h~}}
254254
{{> symbol symbol=. id=null traversing-global-namespace=true }}
255255
{{/if}}

share/mrdocs/addons/generator/common/partials/symbol/detail/members-table-impl.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
{{> symbol/detail/members-table-row . includeBrief=false isName=true}}
1111
{{/each}}
1212
{{ else }}
13-
{{#each (filter_by members "isRegular" "isSeeBelow")}}
13+
{{#each (filter_by_eq members "extraction" "regular" "see-below")}}
1414
{{> symbol/detail/members-table-row . includeBrief=../includeBrief isName=false}}
1515
{{/each}}
1616
{{/if}}

share/mrdocs/addons/generator/common/partials/symbol/members-table.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
See: https://mrdocs.com/docs/mrdocs/develop/generators.html#dom_reference
1616
--}}
1717
{{#if members}}
18-
{{#if (or (eq members.[0].$meta.type "Name") (any_of_by members "isRegular" "isSeeBelow"))}}
18+
{{#if (or (eq members.[0].$meta.type "Name") (any_of_by_eq members "extraction" "regular" "see-below"))}}
1919
{{#>markup/h level=(select @root.config.multipage (select traversing-global-namespace 2 1) 2)}}{{title}}{{/markup/h}}
2020
{{~>symbol/detail/members-table-impl members=members isName=(eq members.[0].$meta.type "Name") includeBrief=(select (any_of_by members "doc.brief") true false) title=title}}
2121

share/mrdocs/addons/generator/common/partials/symbol/signature/record.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@
2424
final;` is ill-formed (`final` can't be used on a non-defining
2525
declaration). Similarly, don't show a semicolon if there are base
2626
classes. --}}
27-
{{~#isSeeBelow}} { /* see-below */ }{{/isSeeBelow~}}
28-
{{#if (or isSeeBelow (and (not isFinal) (eq (len bases) 0)))}};{{/if}}
27+
{{~#if (eq extraction "see-below")}} { /* see-below */ }{{/if~}}
28+
{{#if (or (eq extraction "see-below") (and (not isFinal) (eq (len bases) 0)))}};{{/if}}

share/mrdocs/addons/generator/common/partials/type/name-infos.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
1313
See: https://mrdocs.com/docs/mrdocs/develop/generators.html#dom_reference
1414
--}}
15-
{{#if id.isImplementationDefined~}}
15+
{{#if (eq id.extraction "implementation-defined")~}}
1616
{{! The name refers to a symbol that's implementation defined. These are special names that should not be linked. ~}}
1717
{{ str '/* '}}implementation-defined{{ str ' */'~}}
1818
{{else~}}

share/mrdocs/addons/generator/html/partials/symbol.html.hbs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@
348348
{{! Recursive index for multipage global namespace }}
349349
{{#if (and (eq symbol.kind "namespace") @root.config.multipage @root.config.global-namespace-index (eq @root.symbol.kind "namespace") (not @root.symbol.name) (not @root.symbol.parent)) }}
350350
{{#each symbol.members.namespaces}}
351-
{{#if isRegular}}
351+
{{#if (eq extraction "regular")}}
352352
{{#> markup/dynamic-level-h id=null }}{{> symbol/qualified-name . }} namespace{{/markup/dynamic-level-h~}}
353353
{{> symbol symbol=. id=null traversing-global-namespace=true }}
354354
{{/if}}

src/lib/Schemas/DomDescriptions.hpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
automatically by reflection, but the *meaning* of each field
2323
cannot be inferred from the C++ types alone (e.g. the C++ doc
2424
comment describes the C++ class, not the DOM projection;
25-
synthesized fields like `class` or `isSeeBelow` have no C++
26-
counterpart at all).
25+
the synthesized `class` field has no C++ counterpart at all).
2726
2827
This header carries a small lookup table indexed by
2928
`(typeName, memberName)`. The schema writer consults it when
@@ -109,18 +108,6 @@ inline constexpr DomDescription kDomDescriptions[] = {
109108
"Tag set to the literal `\"symbol\"`. Lets templates "
110109
"discriminate symbol DOM objects from auxiliary types "
111110
"(`type`, `name`, etc.) without inspecting `kind`."},
112-
{"Symbol", "isRegular",
113-
"Convenience boolean equivalent to "
114-
"`extraction === \"regular\"`."},
115-
{"Symbol", "isSeeBelow",
116-
"Convenience boolean equivalent to "
117-
"`extraction === \"see-below\"`."},
118-
{"Symbol", "isImplementationDefined",
119-
"Convenience boolean equivalent to "
120-
"`extraction === \"implementation-defined\"`."},
121-
{"Symbol", "isDependency",
122-
"Convenience boolean equivalent to "
123-
"`extraction === \"dependency\"`."},
124111

125112
// ----- FunctionSymbol ------------------------------------------
126113
{"FunctionSymbol", "",

src/lib/Schemas/DomSchemaWriter.hpp

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -276,45 +276,22 @@ objectSchema()
276276
});
277277
}
278278

279-
// Custom tag_invoke extensions for Symbol (see SymbolBase.hpp).
280-
// These fields are added by the Symbol tag_invoke overload
281-
// beyond what reflection provides. Descriptions live on the
282-
// base `Symbol` entry in DomDescriptions.hpp.
279+
// `class` is the only field Symbol's tag_invoke adds beyond
280+
// what reflection provides; see SymbolBase.hpp. It acts as a
281+
// discriminator so templates can tell Symbol DOM entries apart
282+
// from Type or Name entries in mixed arrays.
283283
if constexpr (std::is_base_of_v<Symbol, T>)
284284
{
285-
auto withDesc =
286-
[](dom::Object schema, std::string_view const member)
287-
{
288-
if (auto const desc =
289-
findDomDescription("Symbol", member);
290-
!desc.empty())
291-
{
292-
schema.set("description", std::string(desc));
293-
}
294-
return schema;
295-
};
296-
297285
dom::Object classSchema;
298286
classSchema.set("type", "string");
299287
classSchema.set("const", "symbol");
300-
properties.set("class", withDesc(std::move(classSchema), "class"));
301-
302-
dom::Object boolSchema;
303-
boolSchema.set("type", "boolean");
304-
properties.set("isRegular",
305-
withDesc(boolSchema, "isRegular"));
306-
properties.set("isSeeBelow",
307-
withDesc(boolSchema, "isSeeBelow"));
308-
properties.set("isImplementationDefined",
309-
withDesc(boolSchema, "isImplementationDefined"));
310-
properties.set("isDependency",
311-
withDesc(boolSchema, "isDependency"));
312-
288+
if (auto const desc = findDomDescription("Symbol", "class");
289+
!desc.empty())
290+
{
291+
classSchema.set("description", std::string(desc));
292+
}
293+
properties.set("class", std::move(classSchema));
313294
required.push_back("class");
314-
required.push_back("isRegular");
315-
required.push_back("isSeeBelow");
316-
required.push_back("isImplementationDefined");
317-
required.push_back("isDependency");
318295
}
319296

320297
// $meta object (added by addMetaObject in MapReflectedType.hpp).

src/lib/Support/Handlebars.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6535,6 +6535,98 @@ registerContainerHelpers(Handlebars& hbs)
65356535

65366536
hbs.registerHelper("any_of_by", any_of_by_fn);
65376537

6538+
static auto filter_by_eq_fn = dom::makeVariadicInvocable([](
6539+
dom::Array const& arguments) -> dom::Value
6540+
{
6541+
// (filter_by_eq container key value1 value2 ...)
6542+
//
6543+
// Filter elements of `container` keeping those whose value
6544+
// at `key` equals any of the listed values. The terminal
6545+
// argument is the Handlebars options object and is dropped.
6546+
if (arguments.size() < 4)
6547+
{
6548+
return arguments.at(0);
6549+
}
6550+
dom::Value container = arguments.at(0);
6551+
dom::Value key = arguments.at(1);
6552+
std::vector<dom::Value> values;
6553+
for (std::size_t i = 2; i < arguments.size() - 1; ++i)
6554+
{
6555+
values.push_back(arguments.at(i));
6556+
}
6557+
6558+
if (!container.isArray())
6559+
{
6560+
return container;
6561+
}
6562+
dom::Array const& arr = container.getArray();
6563+
6564+
std::vector<dom::Value> res;
6565+
std::size_t const n = arr.size();
6566+
for (std::size_t i = 0; i < n; ++i)
6567+
{
6568+
dom::Value el = arr.at(i);
6569+
if (!el.isObject())
6570+
{
6571+
continue;
6572+
}
6573+
dom::Value const fieldValue = el.lookup(key.getString());
6574+
auto const matchIt = std::ranges::find(values, fieldValue);
6575+
if (matchIt == values.end())
6576+
{
6577+
continue;
6578+
}
6579+
res.emplace_back(el);
6580+
}
6581+
return dom::Array(res);
6582+
});
6583+
6584+
hbs.registerHelper("filter_by_eq", filter_by_eq_fn);
6585+
6586+
static auto any_of_by_eq_fn = dom::makeVariadicInvocable([](
6587+
dom::Array const& arguments) -> dom::Value
6588+
{
6589+
// (any_of_by_eq container key value1 value2 ...)
6590+
//
6591+
// True if any element of `container` has its value at `key`
6592+
// equal to any of the listed values.
6593+
if (arguments.size() < 4)
6594+
{
6595+
return false;
6596+
}
6597+
dom::Value container = arguments.at(0);
6598+
dom::Value key = arguments.at(1);
6599+
std::vector<dom::Value> values;
6600+
for (std::size_t i = 2; i < arguments.size() - 1; ++i)
6601+
{
6602+
values.push_back(arguments.at(i));
6603+
}
6604+
6605+
if (!container.isArray())
6606+
{
6607+
return false;
6608+
}
6609+
dom::Array const& arr = container.getArray();
6610+
6611+
std::size_t const n = arr.size();
6612+
for (std::size_t i = 0; i < n; ++i)
6613+
{
6614+
dom::Value el = arr.at(i);
6615+
if (!el.isObject())
6616+
{
6617+
continue;
6618+
}
6619+
dom::Value const fieldValue = el.lookup(key.getString());
6620+
if (std::ranges::find(values, fieldValue) != values.end())
6621+
{
6622+
return true;
6623+
}
6624+
}
6625+
return false;
6626+
});
6627+
6628+
hbs.registerHelper("any_of_by_eq", any_of_by_eq_fn);
6629+
65386630
hbs.registerHelper("at", dom::makeInvocable(at_fn));
65396631

65406632
static auto fill_fn = dom::makeInvocable([](

0 commit comments

Comments
 (0)