Skip to content

fix: anchors are never Windows device names - #1366

Open
gennaroprota wants to merge 2 commits into
cppalliance:developfrom
gennaroprota:fix/anchors_are_never_windows_device_names
Open

gennaroprota wants to merge 2 commits into
cppalliance:developfrom
gennaroprota:fix/anchors_are_never_windows_device_names

Conversation

@gennaroprota

Copy link
Copy Markdown
Collaborator

This PR is stacked on #1365, whose commit it shows until that PR lands; only the last commit, "fix: anchors are never Windows device names", belongs to it.

In multipage output, a symbol's page, and the directory of its members, are named after its anchor. A symbol named like a Windows device (aux, nul, com1, in any case) therefore got paths such as aux.html and aux/reset.html, which Git for Windows refuses to check out, and which before Windows 11 designate the device rather than a file. The name is not far-fetched: Boost.MPL, Boost.Log and Boost.Parameter all have a namespace aux.

Such an anchor now adds the word of its symbol's kind (aux-namespace, Nul-class, com1-2function), as an anchor already does when a symbol of another kind keeps the plain name. The word is a keyword or starts with a digit, so it can never be the name of a member. The names avoided are CON, PRN, AUX, NUL, CONIN$, CONOUT$, COM0 to COM9 and LPT0 to LPT9, ignoring case.

Changes

  • Source: src/mrdocs/Metadata/Finalizers/AnchorFinalizer.cpp adds the kind word to every anchor that is a device name, once the members of a scope are named and before anchors that still coincide are separated.
  • Golden tests: The config/legible-names/disambiguation fixture gains a namespace aux with a member, a struct Nul and a function com1.
  • Breaking changes: The anchor of a symbol named like a device changes, in single-page output too, so that the symbol has the same anchor in both, and links to it break once.

Testing

The disambiguation fixture pins the anchors of a namespace, a class and a function named like devices, in different cases, and of a member of that namespace.

Documentation

configuration/output.adoc says, in its description of how anchors are told apart, that a device name adds the word of its kind.

Fixes #1363.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

✨ Highlights

  • 🧪 Existing golden tests changed (behavior likely shifted)

🧾 Changes by Scope

Scope Lines Δ% Lines Δ Lines + Lines - Files Δ Files + Files ~ Files ↔ Files -
🥇 Golden Tests 86% 6619 5839 780 128 12 116 - -
🛠️ Source 14% 1073 877 196 1 - 1 - -
📄 Docs <1% 21 21 - 1 - 1 - -
Total 100% 7713 6737 976 130 12 118 - -

Legend: Files + (added), Files ~ (modified), Files ↔ (renamed), Files - (removed)

🔝 Top Files

  • tests/golden/fixtures/config/legible-names/disambiguation.xml (Golden Tests): 2570 lines Δ (+2570 / -0)
  • tests/golden/fixtures/config/legible-names/disambiguation.adoc (Golden Tests): 1097 lines Δ (+1097 / -0)
  • src/mrdocs/Metadata/Finalizers/AnchorFinalizer.cpp (Source): 1073 lines Δ (+877 / -196)

Generated by 🚫 dangerJS against 2d6d421

@codecov

codecov Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.21%. Comparing base (9faf2d7) to head (2d6d421).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #1366   +/-   ##
========================================
  Coverage    83.21%   83.21%           
========================================
  Files           35       35           
  Lines         3670     3670           
  Branches       845      845           
========================================
  Hits          3054     3054           
  Misses         410      410           
  Partials       206      206           
Flag Coverage Δ
bootstrap 83.21% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cppalliance-bot

cppalliance-bot commented Oct 28, 2026 •

Copy link
Copy Markdown

An automated preview of the documentation is available at https://1366.mrdocs.prtest2.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-10-28 09:47:05 UTC

With `legible-names`, symbols of one scope that share a name, ignoring
case, were told apart by a suffix taken from their symbol IDs: an
overload set of `abs` and its two functions got `abs-043`, `abs-04b` and
`abs-01`. The suffix meant nothing to a reader. It changed whenever the
IDs did, as they can on a Clang upgrade or with an unrelated
configuration change, and it appeared, or grew longer, when one more
symbol of that name joined the scope, so links into the documentation
broke although nothing they pointed to had changed.

We now give the plain name to the overload set, the most accessible one
when a class splits them by access, to the primary template, or, between
symbols of different kinds, to the kind that comes first, such as a
class next to a concept. Each of the others adds the words that tell it
apart: its kind (`Quantity-concept`), the number of its parameters or
template arguments (`resize-1`), then their types and the qualifiers
(`resize-2-double-int`, `at-1-int-const`). The other overload sets add
their access and `static`, and using-declarations add `using` and the
class they name the member in. A conversion function is named after the
type it converts to (`2conversion-int`), so only conversions to one type
share a name. A new symbol thus changes only the anchors of the symbols
it has to be told apart from.

Each suffix starts with a keyword or a digit, so it can never be the
name of a member, whose anchor follows its parent's after a `-` in a
single-page fragment. The symbol ID remains the suffix of last resort,
for symbols that nothing else tells apart, such as overloads that differ
only in their constraints, or classes whose names differ only in case.

Note that anchors change, and with them the file names of multipage
output, for every symbol that shares its name with another and for every
conversion function, so existing links to those pages break once.

Fixes cppalliance#1288.
Fixes cppalliance#1308.
In multipage output, a symbol's page and the directory of its members
are named after its anchor, so a symbol named like a Windows device
(`aux`, `nul`, `com1`, in any case) got paths such as aux.html and
aux/reset.html. Git for Windows refuses to check them out, and before
Windows 11 such a name designates the device rather than a file. Note
that Boost.MPL, Boost.Log and Boost.Parameter all have a namespace
`aux`.

We now add the word of the symbol's kind to such an anchor
(`aux-namespace`, `com1-2function`), as we already do for a symbol that
leaves its plain name to one of another kind. The word is a keyword or
starts with a digit, so it is never the name of a member. We do it in
single-page output too, so that a symbol has the same anchor in both.

Fixes cppalliance#1363.
@gennaroprota
gennaroprota force-pushed the fix/anchors_are_never_windows_device_names branch from d7ad2d4 to 2d6d421 Compare October 28, 2026 09:32

This branch has not been deployed

No deployments
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.

Multipage output may use Windows reserved device names as file and directory names

2 participants