Skip to content

Fix nested-type links, list rendering, cref member context, and remarks-only placeholder - #52

Merged
Malcolmnixon merged 3 commits into
mainfrom
fix/nested-links-list-rendering-cref-remarks
Oct 7, 2026
Merged

Malcolmnixon merged 3 commits into
mainfrom
fix/nested-links-list-rendering-cref-remarks

Conversation

@Malcolmnixon

@Malcolmnixon Malcolmnixon commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Fixes four rendering bugs reported against ApiMark 0.5.4, found while building DemaConsulting.Bicameral.Core (ApiMarkVisibility=All):

  1. Broken nested-type links (47 links) — links to a nested type from any page other than its parent's nested-types table pointed to <docs root>/<NestedName>.md instead of .../Parent/NestedName.md. Caused by nested types reporting an empty Namespace in Mono.Cecil metadata; TypeLinkResolver now falls back to the declaring type's namespace.
  2. <list type="number"/"bullet"/"table"> rendered as one inline paragraph — XmlDocReader now renders real multi-line Markdown lists on member/type pages, and a new GetSummaryMarkdown API produces a single-line, list-aware summary for table cells (including the <listheader> labels, which are preserved rather than dropped in this compact form).
  3. <see cref="Type.Member"/> lost its type context — rendered as the bare member name. FormatMemberReference now renders Type.Member as display text (XmlDocReader has no page-resolution context, so this does not add a hyperlink).
  4. "No description provided." shown above generator remarks — summary-less members with <remarks> (e.g. [GeneratedRegex] methods) now suppress the placeholder whenever remarks are present, consistently at type and member level in both the gradual-disclosure and single-file emitters.

Testing

  • New fixtures: NestedTypeConsumerClass, TwoLevelNestedClass, SummaryListDocClass.
  • New/updated tests cover nested-type links from various reference kinds (parameter, return, field, generic argument) and depths (two-level nesting), numbered-list rendering on member pages, inline <listheader> preservation in compact summaries, cref Type.Member display text, and remarks-only placeholder suppression at both type and member level.
  • Full solution build: 0 warnings/errors.
  • ApiMark.DotNet.Tests: 381/381 passing across net8.0/net9.0/net10.0.
  • fix.ps1 / lint.ps1: clean (exit 0).
  • Code-review and formal-reviews for all four affected review-sets (ApiMark-DotNet-TypeLinkResolver, ApiMark-DotNet-XmlDocReader, ApiMark-DotNet-DotNetEmitterGradualDisclosure, ApiMark-DotNet-DotNetEmitterSingleFile) passed/approved.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

…ks-only placeholder

Four rendering bugs reported against ApiMark 0.5.4:

1. Links to nested types resolved to the docs root instead of the
   parent type's folder, because nested types report an empty
   Namespace in Mono.Cecil metadata. TypeLinkResolver now falls back
   to the declaring type's namespace when resolving a nested type's
   page path, matching the nested-types table's link construction.

2. <list type="number"/"bullet"/"table"> XML-doc content was always
   flattened to a single inline paragraph. XmlDocReader now renders
   lists as real multi-line Markdown on member/type pages (with a
   blank line before the list and following text as a new paragraph),
   while table cells still receive a single-line, list-aware summary
   via the new GetSummaryMarkdown API.

3. <see cref="Type.Member"/> inside text rendered as the bare member
   name, losing which type it belonged to. FormatMemberReference now
   renders "Type.Member" and links to the member's page when it
   exists.

4. Summary-less members with generated <remarks> (e.g. [GeneratedRegex]
   methods) showed a "No description provided." placeholder above the
   remarks. The placeholder is now suppressed whenever remarks content
   is present, consistently at both type and member level across the
   gradual-disclosure and single-file emitters.

Adds fixtures (NestedTypeConsumerClass, TwoLevelNestedClass,
SummaryListDocClass) and tests covering nested-type links from various
reference kinds/depths, numbered-list rendering, cref member links,
and remarks-only placeholder suppression. Updates design, reqstream,
and verification docs for the four affected units: TypeLinkResolver,
XmlDocReader, DotNetEmitterGradualDisclosure, DotNetEmitterSingleFile.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings October 7, 2026 14:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Compact table headers are dropped, and the stated cref member-page linking is not implemented.

Review effort: Lite
Findings: 1 Medium severity · 1 Low severity

Open (2)
What changed in this PR

Fixes .NET documentation rendering for nested-type links, XML lists, cref member formatting, and remarks-only descriptions.

Changes:

  • Correct nested-type page paths, including deep nesting.
  • Add multi-line and compact list rendering.
  • Improve cref member display.
  • Suppress redundant placeholders when remarks exist.
  • Expand regression tests and documentation.

[Moderate] Compact table summaries currently drop <listheader> labels.
[Nit] Claimed cref member-page linking is not implemented; align the implementation or description.

File Description
test/​ApiMark.DotNet.Tests/​XmlDocReaderTests.cs Tests list and cref rendering.
test/​ApiMark.DotNet.Tests/​TypeLinkResolverTests.cs Tests nested-type link resolution.
test/​ApiMark.DotNet.Tests/​DotNetGeneratorTests.cs Tests generated links.
test/​ApiMark.DotNet.Tests/​DotNetEmitterSingleFileTests.cs Tests single-file output.
test/​ApiMark.DotNet.Tests/​DotNetEmitterGradualDisclosureTests.cs Tests gradual-disclosure output.
test/​ApiMark.DotNet.Fixtures/​TwoLevelNestedClass.cs Adds deep nesting fixture.
test/​ApiMark.DotNet.Fixtures/​SummaryListDocClass.cs Adds list-rendering fixture.
test/​ApiMark.DotNet.Fixtures/​NestedTypeConsumerClass.cs Adds nested-type reference fixture.
src/​ApiMark.DotNet/​XmlDocReader.cs Adds summary rendering and cref formatting.
src/​ApiMark.DotNet/​TypeLinkResolver.cs Resolves nested-type paths.
src/​ApiMark.DotNet/​DotNetEmitterSingleFile.cs Updates rendering and placeholders.
src/​ApiMark.DotNet/​DotNetEmitterGradualDisclosure.cs Updates rendering and placeholders.
docs/​verification/​api-mark-dot-net/​xml-doc-reader.md Documents verification scenarios.
docs/​verification/​api-mark-dot-net/​type-link-resolver.md Documents verification scenarios.
docs/​verification/​api-mark-dot-net/​dot-net-emitter-single-file.md Documents verification scenarios.
docs/​verification/​api-mark-dot-net/​dot-net-emitter-gradual-disclosure.md Documents verification scenarios.
docs/​reqstream/​api-mark-dot-net/​xml-doc-reader.yaml Adds requirement traceability.
docs/​reqstream/​api-mark-dot-net/​type-link-resolver.yaml Adds requirement traceability.
docs/​reqstream/​api-mark-dot-net/​dot-net-emitter-single-file.yaml Adds requirement traceability.
docs/​reqstream/​api-mark-dot-net/​dot-net-emitter-gradual-disclosure.yaml Adds requirement traceability.
docs/​reqstream/​api-mark-dot-net.yaml Registers requirements.
docs/​design/​api-mark-dot-net/​xml-doc-reader.md Documents rendering design.
docs/​design/​api-mark-dot-net/​type-link-resolver.md Documents link-resolution design.
docs/​design/​api-mark-dot-net/​dot-net-emitter-single-file.md Documents emitter design.
docs/​design/​api-mark-dot-net/​dot-net-emitter-gradual-disclosure.md Documents emitter design.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ApiMark.DotNet/XmlDocReader.cs
Comment thread src/ApiMark.DotNet/XmlDocReader.cs
Address PR #52 review: AppendInlineMarkerList only read <item>
elements, so a <list type="table">'s <listheader> column labels were
silently dropped in single-line summary/table-cell contexts (unlike
the multi-line AppendTableList path, which keeps them). The header is
now rendered first (bolded), matching the multi-line AppendMarkerList
behavior. Extends the existing inline-table-list test to assert the
header text is preserved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings October 7, 2026 15:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Fix malformed compact list-header Markdown and add the missing gradual-disclosure regression coverage.

1 open finding
2 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Add gradual-disclosure test for remarks-only type pages

src/​ApiMark.DotNet/​DotNetEmitterGradualDisclosure.cs:369

The new type-level placeholder branch in WriteTypeHeaderSections is not covered by the gradual-disclosure tests: the added remarks-only regression exercises a member, while the type-level case is tested only in the separate single-file emitter. Please add a synthetic remarks-only type case here and assert that its gradual-disclosure type page contains the remarks and omits the placeholder, so this changed path cannot regress independently.

🧠 Review effort: Lite

Comment thread src/ApiMark.DotNet/XmlDocReader.cs Outdated
Malcolmnixon pushed a commit that referenced this pull request Oct 7, 2026
…evel remarks-only test

Address two review findings on PR #52:

1. The compact (single-line) list-header rendering added for
   "Inline table lists drop listheader labels" wrapped the already
   partially-bolded FormatTermDescription output in another "**...**"
   pair, producing malformed Markdown such as "****Name** — Detail**"
   whenever a <listheader> had both a term and a description. Added a
   dedicated FormatListHeaderText helper that bolds the full header
   label itself (both parts individually, e.g. "**Name** — **Detail**")
   without double-wrapping, used by both AppendMarkerList (multi-line
   bullet/number lists) and AppendInlineMarkerList (compact form) so
   neither path double-bolds. Extended the existing inline table-list
   test with an exact-output assertion to guard against regressing
   this.

2. Added the missing gradual-disclosure regression test for the
   type-level placeholder-suppression branch in
   WriteTypeHeaderSections: the prior remarks-only coverage only
   exercised a member page (GeneratedRegexClass.DigitsRegex); this adds
   a synthetic remarks-only override for SampleClass and asserts its
   own type page shows the remarks and omits the placeholder, so this
   changed path cannot regress independently of the member-level path.

Updates reqstream requirements and verification docs for XmlDocReader
and DotNetEmitterGradualDisclosure accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…evel remarks-only test

Address two review findings on PR #52:

1. The compact (single-line) list-header rendering added for
   "Inline table lists drop listheader labels" wrapped the already
   partially-bolded FormatTermDescription output in another "**...**"
   pair, producing malformed Markdown such as "****Name** — Detail**"
   whenever a <listheader> had both a term and a description. Added a
   dedicated FormatListHeaderText helper that bolds the full header
   label itself (both parts individually, e.g. "**Name** — **Detail**")
   without double-wrapping, used by both AppendMarkerList (multi-line
   bullet/number lists) and AppendInlineMarkerList (compact form) so
   neither path double-bolds. Extended the existing inline table-list
   test with an exact-output assertion to guard against regressing
   this.

2. Added the missing gradual-disclosure regression test for the
   type-level placeholder-suppression branch in
   WriteTypeHeaderSections: the prior remarks-only coverage only
   exercised a member page (GeneratedRegexClass.DigitsRegex); this adds
   a synthetic remarks-only override for SampleClass and asserts its
   own type page shows the remarks and omits the placeholder, so this
   changed path cannot regress independently of the member-level path.

Updates reqstream requirements and verification docs for XmlDocReader
and DotNetEmitterGradualDisclosure accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings October 7, 2026 15:39
@Malcolmnixon
Malcolmnixon force-pushed the fix/nested-links-list-rendering-cref-remarks branch from 924aabf to a72acfa Compare October 7, 2026 15:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Correct the parent-page path test setup and update the XML reader design documentation.

0 open findings

1 resolved since last review

🧠 Review effort: Lite

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.

2 participants