#2190: count <summary> openings per doc run, not closing-tag pairs - #2192
Conversation
NoMemberCarriesTwoStackedSummaryBlocks keyed off a </summary> immediately followed by a reopening, so it saw a stacked pair only when the FIRST block was closed. Two instances sat on dev unseen, and the mixed form (a single-line summary followed by a multi-line one) is invisible to a closing-tag matcher entirely. The rule now counts <summary> openings inside each contiguous run of /// lines. A run documents exactly one member, so two openings means two summaries, closed or not, single-line or spread over many. Both live instances fixed: - DarlingManagedPostgres.ApplyProcessEnvironment carried a duplicated opening tag; the stray line is deleted. - QueryStoreSliceRepairService had a doc block that bb1f48c split, stranding its unclosed head above PromoteRewrittenFileAsync. Deleted rather than moved back onto FlushExternalFileCacheAsync: that same commit re-documented that member in place with a superset of the stranded sentence, so moving it would have recreated the duplicate this rule forbids. The detector gains a self-test pinning the five stacked shapes it must catch and the four legitimate ones it must leave alone, since this was a blind spot in the detector rather than in anyone's reading of the tree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review: PR #2192Scope is narrow and self-contained: Correctness of the new detector — traced
Only edge case I found and didn't see covered: a self-closing The two production doc-comment fixes:
Lite/Darling parity — the two fixes touch one app each (Darling service, Lite service) for unrelated pre-existing bugs; this isn't a shared-feature change, so no parity drift concern. The detector itself lives in No correctness, security, or performance issues found. Nothing to flag as blocking. |
|
CI green, PR clean and not merged. Local gates on the fixed tree, rebuilt DLLs: full Leaving the merge and #2190's closure to you. The one thing worth your eye before merging is the instance 2 call: I deleted the stranded doc head in |
Fixes #2190.
DocCommentHygieneTests.NoMemberCarriesTwoStackedSummaryBlocksmatched</summary>immediately followed by a reopening, so it only ever saw a stacked pair when the FIRST block was closed. The rule now counts<summary>OPENINGS inside each contiguous run of///lines: a run documents exactly one member, so two openings means two summaries, closed or not, single-line or spread over many.Watched red, then green
The widened detection was written and run against the UNFIXED tree first. It failed on exactly the two live instances the issue names, with all 8 self-test cases (at that point) passing. Verbatim, against
Darling.Tests.dllrebuilt from source:The pre-#2190 rule passes on that same tree, which is the defect.
The two live instances
1.
DarlingManagedPostgres.cs:2368- a duplicated opening tag onApplyProcessEnvironment, two openings and one closing. The stray line is deleted, exactly as the issue describes.2.
Lite/Services/QueryStoreSliceRepairService.cs:576- fixed by deletion, NOT by moving the block. This deviates from the issue and needs your eye.The issue says not to delete it, on the basis that
FlushExternalFileCacheAsync"is left undocumented". It is not.git blamegives the full mechanism:8829e101wroteFlushExternalFileCacheAsync's original doc block: the opening tag, the sentence "Drops DuckDB's cached view of every external file, by toggling the cache off and back on.", then two<para>blocks carrying the WHY (the instance-scoped path cache; the off/on toggle being the only eviction that works).bb1f48c0("move the cache eviction inside the swap helper, correct-by-construction") then insertedPromoteRewrittenFileAsyncbetween that block's opening and its closing tag. It moved the WHY paragraphs up onto the new helper, where they live today, and gaveFlushExternalFileCacheAsynca NEW summary in place at what is now lines 629-631: "Evicts DuckDB's cached view of every external file, by toggling the cache off and back on. The WHY is on<see cref="PromoteRewrittenFileAsync"/>, which is the only thing that should ever need this."So what sits at 576-578 is not a whole displaced block, it is the stranded HEAD of one: an opening tag plus a single sentence. That sentence survives on the correct member at line 630, improved (
EvictsforDrops) and paired with a pointer to the WHY. Deleting it loses nothing, and moving it back would either stack a second summary onFlushExternalFileCacheAsync(the exact defect this rule forbids) or duplicate a sentence already there.I checked this sentence by sentence rather than taking the issue's word for it, and the guard's own failure message now carries the same triage step so the next person hitting a split block checks whether the source member was re-documented before moving anything.
False-positive triage
The widened detection ran across the WHOLE tree, which is what the test does by construction (every
*.csunder the repo root,bin/objexcluded). It flags exactly the two instances above and nothing else - no legitimate pattern was caught, so no tightening was needed. Escaped mentions in prose (<summary>, which this very test file is full of) are not openings and never matched. There are no delimited/** */doc comments anywhere in the tree, so the///run model has no gap.Self-test
The detector now pins its own behavior, because #2190 was a blind spot in the DETECTOR rather than in anyone's reading of the tree, and a synthetic case is what exposed it. Five shapes it must catch (closed-then-reopened; a duplicated opening tag; an insertion-split block; a single-line summary followed by a multi-line one, which is the mixed form a closing-tag matcher cannot see at all; and a stacked run reaching EOF, which pins the scan's one-past-the-end step) and four it must leave alone (summary plus
<param>/<returns>; summary carrying several<para>blocks; two adjacent members with one summary each; escaped mentions in prose).Gates
Darling.Testssuite, rebuilt DLLs:Failed: 0, Passed: 4234, Skipped: 236, Total: 4470. The skips are the live-Postgres-gated families.DocCommentHygieneTestson the fixed tree:Failed: 0, Passed: 10, Total: 10.Darling.TestsandPerformanceMonitorLiteboth build with 0 errors; the warnings they do emit (CA2022 inNpgsqlRootCertificateValidationTests.cs, CA1068 inPerformanceMonitor.Common/AbandonableStep.cs, CS0628 inLite/Services/LocalDataService) are all pre-existing on dev in files outside this diff. I left them alone deliberately - CA1068 is a signature reorder on a primitive both apps call, and none of the three sit in a file this PR touches - and filed them as [BUG] Pre-existing analyzer warnings on dev make a zero-warning build gate unreadable (CA1068, CA2022, CS0628) #2193 rather than leaving them untracked.[Unreleased]/Fixedwith a[#2190]link-ref.One note for whoever edits
CHANGELOG.mdnext: it carries 6 bareCRbytes as line terminators among its 2674 CRLFs. A normal editor pass silently rewrites them and turns a two-line addition into a 5350-line diff. This entry was inserted byte-precisely with the CR count asserted unchanged, so the diff here is the 2 lines it should be.Not merging, and leaving #2190 open for you to close.
Generated with Claude Code