Skip to content

Commit cc90113

Browse files
committed
feat: render long noexcept specifications as noexcept(see-below)
MrDocs used to render the full `noexcept` operand inline, so a declaration like void swap(reference, reference) noexcept( std::is_nothrow_move_constructible<value_t>::value && std::is_nothrow_move_assignable<value_t>::value && std::is_nothrow_move_constructible<json_value>::value && std::is_nothrow_move_assignable<json_value>::value); buried the `noexcept` condition in a mostly-unreadable slop. This replaces operands longer than 40 characters with an italic "see-below" placeholder in the declaration, and moves the actual condition to a dedicated "noexcept Specification" section of the exposition: void swap(reference, reference) noexcept(see-below); === noexcept Specification noexcept when `...long condition...`. The section is intentionally separate from the existing "Exceptions" section, which continues to cover `@throws` documentation. Closes issue #1103.
1 parent a3366b0 commit cc90113

37 files changed

Lines changed: 1288 additions & 105 deletions

include/mrdocs/Metadata/Specifiers/ExplicitInfo.hpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <mrdocs/Platform.hpp>
1616
#include <mrdocs/Metadata/Specifiers/ExplicitKind.hpp>
17+
#include <mrdocs/Support/Describe.hpp>
1718
#include <string>
1819

1920
namespace mrdocs {
@@ -27,7 +28,7 @@ struct ExplicitInfo
2728
{
2829
/** Whether an explicit-specifier was user-written.
2930
*/
30-
bool Implicit = true;
31+
bool IsUserWritten = false;
3132

3233
/** The evaluated exception specification.
3334
*/
@@ -42,6 +43,11 @@ struct ExplicitInfo
4243
auto operator<=>(ExplicitInfo const&) const = default;
4344
};
4445

46+
MRDOCS_DESCRIBE_STRUCT(
47+
ExplicitInfo,
48+
(),
49+
(IsUserWritten, Kind, Operand))
50+
4551
/** Convert ExplicitInfo to a string.
4652
4753
@param info The explicit-specifier information.
@@ -57,21 +63,6 @@ toString(
5763
bool resolved = false,
5864
bool implicit = false);
5965

60-
/** Return the ExplicitInfo as a @ref dom::Value string.
61-
62-
@param v The output parameter to receive the dom::Value.
63-
@param I The ExplicitInfo to convert.
64-
*/
65-
inline
66-
void
67-
tag_invoke(
68-
dom::ValueFromTag,
69-
dom::Value& v,
70-
ExplicitInfo const& I)
71-
{
72-
v = toString(I);
73-
}
74-
7566
} // mrdocs
7667

7768
#endif

include/mrdocs/Metadata/Specifiers/ExplicitKind.hpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
#define MRDOCS_API_METADATA_SPECIFIERS_EXPLICITKIND_HPP
1414

1515
#include <mrdocs/Platform.hpp>
16-
#include <mrdocs/Dom/String.hpp>
17-
#include <string>
16+
#include <mrdocs/Support/Describe.hpp>
1817

1918
namespace mrdocs {
2019

@@ -33,11 +32,7 @@ enum class ExplicitKind
3332
Dependent
3433
};
3534

36-
/** Convert an explicit kind to its string form.
37-
*/
38-
MRDOCS_DECL
39-
dom::String
40-
toString(ExplicitKind kind) noexcept;
35+
MRDOCS_DESCRIBE_ENUM(ExplicitKind, False, True, Dependent)
4136

4237
} // mrdocs
4338

include/mrdocs/Metadata/Specifiers/NoexceptInfo.hpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <mrdocs/Metadata/Specifiers/ExplicitInfo.hpp>
1919
#include <mrdocs/Metadata/Specifiers/ExplicitKind.hpp>
2020
#include <mrdocs/Metadata/Specifiers/NoexceptKind.hpp>
21+
#include <mrdocs/Support/Describe.hpp>
2122
#include <string>
2223

2324
namespace mrdocs {
@@ -28,7 +29,13 @@ struct NoexceptInfo
2829
{
2930
/** Whether a noexcept-specifier was user-written.
3031
*/
31-
bool Implicit = true;
32+
bool IsUserWritten = false;
33+
34+
/** Whether the operand is long enough to warrant rendering as
35+
`noexcept(see-below)` plus a separate specification section,
36+
instead of inline in the signature.
37+
*/
38+
bool OperandIsLong = false;
3239

3340
/** The evaluated exception specification.
3441
*/
@@ -43,6 +50,11 @@ struct NoexceptInfo
4350
auto operator<=>(NoexceptInfo const&) const = default;
4451
};
4552

53+
MRDOCS_DESCRIBE_STRUCT(
54+
NoexceptInfo,
55+
(),
56+
(IsUserWritten, OperandIsLong, Kind, Operand))
57+
4658
/** Convert NoexceptInfo to a string.
4759
4860
@param info The noexcept-specifier information.
@@ -62,18 +74,6 @@ toString(
6274
bool resolved = false,
6375
bool implicit = false);
6476

65-
/** Convert a NoexceptInfo to a DOM value.
66-
*/
67-
inline
68-
void
69-
tag_invoke(
70-
dom::ValueFromTag tag,
71-
dom::Value& v,
72-
NoexceptInfo const& info)
73-
{
74-
v = toString(info, false, false);
75-
}
76-
7777
} // mrdocs
7878

7979
#endif

include/mrdocs/Metadata/Specifiers/NoexceptKind.hpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
#define MRDOCS_API_METADATA_SPECIFIERS_NOEXCEPTKIND_HPP
1414

1515
#include <mrdocs/Platform.hpp>
16-
#include <mrdocs/Dom/String.hpp>
17-
#include <string>
16+
#include <mrdocs/Support/Describe.hpp>
1817

1918
namespace mrdocs {
2019

@@ -33,11 +32,7 @@ enum class NoexceptKind
3332
Dependent
3433
};
3534

36-
/** Convert a noexcept kind to its string form.
37-
*/
38-
MRDOCS_DECL
39-
dom::String
40-
toString(NoexceptKind kind) noexcept;
35+
MRDOCS_DESCRIBE_ENUM(NoexceptKind, False, True, Dependent)
4136

4237
} // mrdocs
4338

include/mrdocs/Support/MergeReflectedType.hpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,12 @@ isPlaceholderType(Polymorphic<Type> const& t);
9595
4. `Polymorphic<Type>` — take if placeholder (AutoType or blank
9696
NamedType)
9797
5. `Polymorphic<Name>` — take if Identifier is empty
98-
6. `.Implicit` types — take if dst is implicit
99-
7. `Optional<T>` — take if disengaged; recursive merge
98+
6. `Optional<T>` — take if disengaged; recursive merge
10099
if both engaged and T has `merge()`
101-
8. `enum` — take if zero-initialized
102-
9. `string` — take if empty
103-
10. `vector<T>` with `==` — dedup-append
104-
11. `vector<T>` fallback — take if dst is empty
100+
7. `enum` — take if zero-initialized
101+
8. `string` — take if empty
102+
9. `vector<T>` with `==` — dedup-append
103+
10. `vector<T>` fallback — take if dst is empty
105104
106105
Returns `false` only for types none of the above handles.
107106
*/
@@ -152,16 +151,6 @@ mergeByType(T& dst, T&& src)
152151
}
153152
return true;
154153
}
155-
// Types with .Implicit flag (NoexceptInfo, ExplicitInfo):
156-
// take src if dst is still implicit (compiler-generated).
157-
else if constexpr (requires(T const& t) { { t.Implicit } -> std::convertible_to<bool>; })
158-
{
159-
if (dst.Implicit)
160-
{
161-
dst = std::move(src);
162-
}
163-
return true;
164-
}
165154
// Optional<T>: take if disengaged; recursive merge if both
166155
// engaged and the value type has a merge() function.
167156
else if constexpr (is_optional_v<T>)

mrdocs.rnc

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,42 @@ grammar
9595

9696
TableAlignmentKind = "left" | "center" | "right"
9797

98+
NoexceptKind = "false" | "true" | "dependent"
99+
100+
ExplicitKind = "false" | "true" | "dependent"
101+
102+
#---------------------------------------------
103+
# noexcept specification
104+
#
105+
# Emitted only when a noexcept-specifier is user-written
106+
# (implicit specifications are skipped). The operand holds
107+
# the expression as written, when present.
108+
#---------------------------------------------
109+
110+
NoexceptSpec =
111+
element noexcept
112+
{
113+
element is-user-written { Bool },
114+
element operand-is-long { Bool }?,
115+
element kind { NoexceptKind }?,
116+
element operand { text }?
117+
}
118+
119+
#---------------------------------------------
120+
# explicit specification
121+
#
122+
# Emitted only when an explicit-specifier is user-written.
123+
# The operand holds the expression as written, when present.
124+
#---------------------------------------------
125+
126+
ExplicitSpec =
127+
element explicit
128+
{
129+
element is-user-written { Bool },
130+
element kind { ExplicitKind }?,
131+
element operand { text }?
132+
}
133+
98134
#---------------------------------------------
99135
# Name (used inside types, not for symbol names)
100136
#---------------------------------------------
@@ -187,7 +223,7 @@ grammar
187223
TypeBase,
188224
AnyType*,
189225
element ref-qualifier { text }?,
190-
element exception-spec { text }?,
226+
NoexceptSpec?,
191227
element is-variadic { Bool }?
192228
}
193229

@@ -420,7 +456,7 @@ grammar
420456
Param*,
421457
TemplateInfo?,
422458
element func-class { FunctionClass }?,
423-
element noexcept { text }?,
459+
NoexceptSpec?,
424460
element requires { text }?,
425461
element is-variadic { Bool }?,
426462
element is-defaulted { Bool }?,
@@ -443,7 +479,7 @@ grammar
443479
element is-volatile { Bool }?,
444480
element is-final { Bool }?,
445481
element ref-qualifier { text }?,
446-
element explicit { text }?,
482+
ExplicitSpec?,
447483
element attributes { text }*,
448484
element function-object-impl { SymbolID }?
449485
}
@@ -457,7 +493,7 @@ grammar
457493
AnyType?,
458494
TemplateInfo?,
459495
Param*,
460-
element explicit { text }?
496+
ExplicitSpec?
461497
}
462498

463499
#---------------------------------------------
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pass:q[_see-below_]

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@
168168
{{/each}}
169169
|===
170170
{{/if}}
171+
{{/if}}
172+
{{! noexcept specification — only when the operand is long enough to
173+
be rendered as noexcept(see-below) in the signature. Short
174+
operands are shown inline and need no separate section. }}
175+
{{#if symbol.noexcept.operandIsLong}}
176+
{{#> markup/dynamic-level-h }}noexcept Specification{{/markup/dynamic-level-h~}}
177+
`noexcept` when `{{symbol.noexcept.operand}}`.
178+
171179
{{/if}}
172180
{{! Exceptions }}
173181
{{#if symbol.doc.exceptions}}

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
{{/if~}}
1111
{{#if isVirtual}}virtual
1212
{{/if~}}
13-
{{#if explicit}}{{explicit}}
13+
{{#if explicit.isUserWritten}}
14+
{{~#if explicit.operand}}explicit({{explicit.operand}}){{else if (eq explicit.kind "true")}}explicit{{/if}}
1415
{{/if~}}
1516
{{#if (eq funcClass "normal")}}{{>type/declarator-prefix returnType}}
1617
{{/if~}}
@@ -31,7 +32,9 @@
3132
{{~#if isConst}} const{{/if~}}
3233
{{#if isVolatile}} volatile{{/if~}}
3334
{{#if refQualifier}} {{refQualifier}}{{/if~}}
34-
{{#if noexcept}} {{noexcept}}{{/if~}}
35+
{{~#if noexcept.isUserWritten~}}
36+
{{~#if noexcept.operandIsLong}} noexcept({{> markup/see-below }}){{else if noexcept.operand}} noexcept({{noexcept.operand}}){{else if (eq noexcept.kind "true")}} noexcept{{/if~}}
37+
{{~/if~}}
3538
{{#if (eq funcClass "normal")}}{{>type/declarator-suffix returnType}}{{/if~}}
3639
{{#if requires}}
3740

share/mrdocs/addons/generator/common/partials/type/declarator-suffix.hbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,10 @@
3737
{{~#if cv-qualifiers}} {{cv-qualifiers}}{{/if~}}
3838
{{! Refqualifiers as "&" or "&&" ~}}
3939
{{#if (eq refQualifier "lvalue")}} &{{else if (eq refQualifier "rvalue")}} &&{{/if~}}
40-
{{! Exception spec as literal string ~}}
41-
{{#if exceptionSpec}} {{exceptionSpec}}{{/if~}}
40+
{{! noexcept specification with "see-below" placeholder for long operands ~}}
41+
{{~#if exceptionSpec.isUserWritten~}}
42+
{{~#if exceptionSpec.operandIsLong}} noexcept({{> markup/see-below }}){{else if exceptionSpec.operand}} noexcept({{exceptionSpec.operand}}){{else if (eq exceptionSpec.kind "true")}} noexcept{{/if~}}
43+
{{~/if~}}
4244
{{! Declarator suffix of the return type ~}}
4345
{{~>type/declarator-suffix returnType link-components-impl=link-components-impl~}}
4446
{{/if}}

0 commit comments

Comments
 (0)