Skip to content

Fix duplicate diagnostic counts and middleware cancellation - #366

Merged
davidkallesen merged 7 commits into
mainfrom
fix/dotnet-build-duplicate-diagnostic-counts
Jul 29, 2026
Merged

Fix duplicate diagnostic counts and middleware cancellation#366
davidkallesen merged 7 commits into
mainfrom
fix/dotnet-build-duplicate-diagnostic-counts

Conversation

@davidkallesen

Copy link
Copy Markdown
Collaborator

Summary

  • Count each build diagnostic once instead of twice
  • Forward request cancellation in Atc.Rest middleware
  • Add GetSystemVersion overload for SemVer-style output
  • Update NuGet packages and suppress noisy analyzer rules

Changes

✨ Features

  • Add GetSystemVersion(int fieldCount) on AssemblyHelper
  • Validate the field count is between 1 and 4
  • Lets callers request Major.Minor.Patch directly

🐛 Fixes

  • Count each build diagnostic once in ParseBuildOutputHelper
  • MSBuild prints every diagnostic twice, doubling every count
  • Neither -clp:NoSummary nor -tl:off removes the recap copy
  • Key de-duplication on the whole line, not the matched fragment
  • Strip a leading MSBuild node id so both copies normalise alike
  • Pass context.RequestAborted in KeepAliveMiddleware
  • Pass CancellationToken.None in the request/response logger

📦 Dependencies

  • Update NuGet packages across src, test and samples

🔧 Configuration

  • Suppress S5766 in the custom .editorconfig section
  • Suppress S4036 in InternetBrowserHelper
  • Suppress S1313 twice in NetworkInformationHelper

🎨 Styling

  • Pass StringComparer.Ordinal to Assert.Contains on strings

📝 Documentation

  • Regenerate System.md for the IsHostName RFC 1123 remarks
  • Regenerate CodeDoc for the new GetSystemVersion overload

Notes

  • The logger middleware opts out of cancellation deliberately
  • Those calls run after the response has been produced
  • Cancelling there truncates the response and the log entry
  • A code comment records this so it is not "corrected" later
  • Consumers of the diagnostic counts should expect halved values
  • atc-coding-rules-updater reported 7 real sites as 14 before
  • That repo needs a release of this package to pick the fix up
  • AppDomainExtensionsTests.GetAssemblyInformations fails
  • It is pre-existing and unrelated, verified at origin/main
  • The test recounts loaded assemblies after calling the helper
  • The first call loads one more, so the baseline is always +1

AssemblyHelper.GetSystemVersion() returns the full four-part assembly version. The
fourth component is the build height added by tools such as
Nerdbank.GitVersioning, which is not something a caller wants when presenting a
package version.

The overload takes the number of components to include and validates it is between
1 and 4, so callers can ask for SemVer-style "Major.Minor.Patch" directly instead
of trimming the string themselves.

Includes tests and the regenerated CodeDoc.
Picks up the remarks for the all-numeric top-level label rejection added in
5d45738, which noted that it also disambiguates host names from IPv4 addresses.
The generated CodeDoc was not regenerated in that commit.
- InternetBrowserHelper: S4036 "use an absolute path". Launching the user's
  default browser goes through the shell, so resolving an absolute path is not
  applicable.
- NetworkInformationHelper: S1313 "magic numbers should not be used", twice. The
  literals are well-known network constants and are clearer inline than named.
Assert.Contains over a string sequence without a comparer uses the default
equality comparer, which the analyzers flag as culture-dependent. Passing
StringComparer.Ordinal states the intent and keeps the assertions culture-neutral.

No behavioural change: every one of these compares C# syntax tokens, header names
or literal test data, all of which are ordinal by nature.
MSBuild reports every diagnostic twice: inline while the target runs, and again in
the end-of-build recap under "(CoreCompile target) ->". Neither -clp:NoSummary nor
-tl:off removes the recap, and ParseBuildOutputHelper incremented a counter per
regex match, so every occurrence count was exactly doubled.

Consumers see this directly. atc-coding-rules-updater generates temporary
suppressions annotated with an occurrence count, and a solution with 7 real
violation sites was reported as 14.

Parsing is now per line and identical diagnostics are counted once. The key is the
whole normalised line, not the matched fragment: the patterns start at ": error " /
": warning " and therefore exclude the file and position, so keying on the fragment
would collapse two genuine occurrences of the same rule at different positions.
Normalisation also strips a leading MSBuild node id ("1>"), because at higher
verbosity the inline copy carries one while the recap copy is indented.

Adds six tests: three duplicate shapes, two guarding that legitimate duplicates
still count separately (same code at different positions, same message from
different projects), and one over the real captured output of a two-project
solution asserting 14 lines yield 7 occurrences.
…g out where wrong

S8949 flagged four call sites that dropped the request's cancellation token. They
need two different answers, not one.

KeepAliveMiddleware writes the response body for a health ping, so it now passes
context.RequestAborted: if the caller has hung up there is nothing to gain by
writing it.

RequestResponseLoggerMiddleware passes CancellationToken.None, explicitly. Those
three call sites run after the response has been produced - they rewind the
buffered swap stream, copy it back into the real response body and restore
httpContext.Response.Body. Honouring the request's cancellation there would abort
the copy part-way on a client disconnect, leaving a truncated response, an
unrestored Body (the assignment follows the await) and an incomplete log entry,
which is the one thing that middleware exists to produce. A comment records that
this is deliberate, since the analyzer will keep suggesting RequestAborted.
@davidkallesen
davidkallesen merged commit 97ed090 into main Jul 29, 2026
4 checks passed
@davidkallesen
davidkallesen deleted the fix/dotnet-build-duplicate-diagnostic-counts branch July 29, 2026 12:49
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