Skip to content

Requirement links from Doxygen (2/6) - #5

Merged
tobiaskaestner merged 4 commits into
mainfrom
tkaestner/2-doxygen-requirement-links
Oct 2, 2026
Merged

tobiaskaestner merged 4 commits into
mainfrom
tkaestner/2-doxygen-requirement-links

Conversation

@tobiaskaestner

@tobiaskaestner tobiaskaestner commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Part 2 of 6 of a stacked series. It is based on #4 (tkaestner/1-registry-plumbing); review the commits below only.

  • Read Doxygen 1.16's native \verifies links into the test-case needs.
  • Stage 2 fails on a reference to a requirement that no requirement defines.
    The Doxygen XML cannot show this (a resolved and a dangling link are the same
    bytes), so the gate reads the warning log.
  • Symbol references in the prose of a test case become links.
  • Read @testid / @reqref values also when Doxygen autolinks them.

Commits

  • 5e199b6 feat: doxygen: read native \verifies requirement links
  • 94cba49 feat: doxygen: fail stage 2 on unknown requirement references
  • 85e8df9 fix: doxygen: link symbol references in test-case prose
  • 2a4fb8c fix: doxygen: read autolinked @testid/@reqref values

Testing

  • Unit suite (python3 -m pytest sphinx/_extensions/_tests -q) at the head of this PR: 187 passed.
  • The safety docset (about 15 documents, 5 Doxygen projects) builds clean on the top of the stack, with all its gates.
  • The acceptance steps for these changes are in zdocs-tests (one PR after this series). With the engine at the top of the stack, that suite passes 321 of 321.

The stack

  1. Registry and build plumbing (1/6) #4 Registry and build plumbing
  2. Requirement links from Doxygen (2/6) #5 Requirement links from Doxygen (this PR)
  3. Test report correctness (3/6) #6 Test report correctness
  4. Implementation layer and conditions (4/6) #7 Implementation layer and conditions
  5. Incremental rebuilds and see-also (5/6) #8 Incremental rebuilds and see-also
  6. Coverage adequacy (6/6) #9 Coverage adequacy

🤖 Generated with Claude Code

@tobiaskaestner
tobiaskaestner added this pull request to stack #10 October 1, 2026 18:47
@tobiaskaestner
tobiaskaestner force-pushed the tkaestner/2-doxygen-requirement-links branch from 2a4fb8c to 4e6451e Compare October 2, 2026 14:57
Base automatically changed from tkaestner/1-registry-plumbing to main October 2, 2026 15:05
tobiaskaestner and others added 4 commits October 2, 2026 17:05
Doxygen 1.16 writes \verifies as a <verifies> child of the memberdef, one
<requirement> per UID with the UID only in its refid. parse_memberdef read
requirement links from @reqref xrefsects alone, so test cases annotated
with the native command reached the needs with no verifies links.

Read memberdef/verifies/requirement beside the xrefsect path, keeping both
while sources migrate, and list a UID named by both once. The refid does
not prove the requirement exists: Doxygen synthesizes it from the UID
whether or not any \requirement defines it, so validation stays with
Doxygen's "unknown requirement" warning, as the new comment says.

Three new tests; against the unchanged code 2 fail, the third pins that
non-requirement children are ignored. Suite 164 -> 167. In the safety
docset 54 of 56 test cases now carry 77 verifies links, none dangling. The
acceptance suite (zdocs-tests) was not available and has not been run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tobias Kaestner <tobias.kaestner@inovex.de>
Doxygen synthesizes <requirement refid="requirement_<UID>"> from the UID
whether or not any \requirement defines it, so the XML cannot tell a real
\verifies or \satisfies link from a typo. Its "Reference to unknown
requirement" warning is the only signal, and nothing acted on it: a
build with a truncated UID passed.

Stage 2 now writes its warnings to <build>/<doc>.warnings.log, and a new
check_doxygen_warnings.cmake runs after it in the same target. It echoes
the log, so the console shows what it did before, and fails the target on
any line matching ZDOCS_DOXYGEN_WARN_FAIL_PATTERNS, naming each line.
The default pattern is the unknown-requirement warning; an empty list
gates nothing. Stage 1 is never gated: it clears TAGFILES, so its
cross-document warnings are false, and its overlay resets WARN_LOGFILE.

Five new tests run the script through cmake -P. Suite 167 -> 172. In the
safety docset a planted @verifies ZEP-SRS-20-99 fails the build at its
source line and passes once removed. The acceptance suite (zdocs-tests)
was not available and has not been run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tobias Kaestner <tobias.kaestner@inovex.de>
A symbol reference in a test case's or procedure's prose - brief, details,
test steps, Arrange/Act/Assert sections, parameters - became a :c:func:
role. Nothing in the test documents defines C objects, so it rendered as
code without a link, and without a warning, while the same symbol on the
see-also line linked into the Doxygen HTML through its refid.

One helper, ref_to_rst, now turns a <ref> into a link for both: a symbol
resolved through a tag file (external=) into the API document's Doxygen,
one documented in the parsed project itself, such as a shared test
procedure, into the test specification's. The prose helpers take it as an
optional links= argument; without it their output is unchanged. A
procedure's brief is its need title, which is not parsed, so it stays
unlinked.

para_text also joined its pieces with a space, which put one before the
punctuation after a reference ("k_fifo_put() ."); it now joins them as
written and only collapses whitespace.

Six new tests; against the unchanged code five fail, the sixth pins the
unlinked output. In the safety test specification every k_fifo_* and
k_queue_* reference now links; the 37 references left unlinked name
undocumented local helpers, which have no Doxygen page. The acceptance
suite (zdocs-tests) was not available and has not been run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tobias Kaestner <tobias.kaestner@inovex.de>
Once a tag file in TAGFILES declares a requirement of the same name (a
`doxygen_tag:` needs tag, say), Doxygen autolinks an identifier-shaped
UID such as DUTY_001 inside the xrefitem:
`<para><ref ...>DUTY_001</ref></para>`. The parser read `para.text`,
which is then empty, so the test case silently lost its requirement links
(or its test id). Read itertext() instead. Hyphenated UIDs are never
autolinked, which is why the Zephyr tree never showed it. Found by the
zdocs-tests step-30 fixture (test_28 regressions).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tobias Kaestner <tobias.kaestner@inovex.de>
@tobiaskaestner
tobiaskaestner force-pushed the tkaestner/2-doxygen-requirement-links branch from 4e6451e to 45a1140 Compare October 2, 2026 15:05
@tobiaskaestner
tobiaskaestner merged commit 487306f into main Oct 2, 2026
2 checks passed
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.

1 participant