Skip to content

Make ScopeAfterManualDispose actually dispose while a scope is active - #94

Merged
matt-edmondson merged 1 commit into
mainfrom
claude/github-issues-b0eba5
Sep 7, 2026
Merged

Make ScopeAfterManualDispose actually dispose while a scope is active#94
matt-edmondson merged 1 commit into
mainfrom
claude/github-issues-b0eba5

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Related to #88 — this is a finding produced by the local SonarCloud reproduction that issue asked for, and the first end-to-end confirmation that the setup surfaces real problems.

The defect

ScopeAfterManualDisposeOfCodeBlockerShouldThrowException was byte-identical in behaviour to ScopeWithDisposedCodeBlockerShouldThrowException — Sonar's S4144. Both disposed the CodeBlocker and then asserted that constructing a Scope throws.

That is not what the test's name says, and not what its own comment says:

// Act - Dispose the CodeBlocker while scope is still active
codeBlocker.Dispose();

No scope was ever active. The path the test claims to cover — a CodeBlocker disposed out from under a live scope — had no coverage at all.

It now opens a scope first, disposes the CodeBlocker, and asserts that closing the scope throws ObjectDisposedException, which is what happens when EndScope writes its brace to the disposed writer.

CA2000 is suppressed on that one line with a justification: disposing the scope is the act under test and it throws, so a using block would let the exception escape the assert instead of reaching it. Same pragma style as CodeBlocker.cs:180, and scoped to the single statement.

On #88 itself

The issue reads as outstanding, but its implementation landed on main in 233a1b7. Verifying it against the acceptance criteria:

  • A documented local command runs the Sonar analyzers over every project. .sonarlint/sonar-local.props + .globalconfig exist and work; the invocation is documented in CLAUDE.md.
  • Its output matches what SonarCloud reports for the same commit. Still unverified. sonarcloud.io is not reachable from the agent sandbox (CONNECT tunnel failed, response 403), so the one unidentified issue from Generalize CodeBlocker into a code-generation substrate #87 cannot be named, and the globalconfig cannot be calibrated against the real quality profile. Enabling every rule the analyzer ships would be a superset, not a match, so it would not satisfy this criterion either. This needs someone with dashboard access; I'd leave Add a local SonarCloud reproduction #88 open for it.
  • Nothing imports the config automatically. Confirmed — plain builds are unaffected.

What the run reports on main today, now recorded in CLAUDE.md as a calibration baseline: S4144 on ScopeTests.cs (fixed here) and five S2699 warnings for test methods that assert nothing. The S2699 ones are left alone — several look like deliberate "does not throw" tests, and deciding that is a judgement call rather than a defect fix.

Testing

  • dotnet test168 passed, 0 failed.
  • dotnet build -p:CustomAfterMicrosoftCommonProps=$PWD/.sonarlint/sonar-local.propsbuild succeeded; S4144 gone, five pre-existing S2699 warnings remain.

One caveat: the sandbox has .NET SDK 10.0.111 (Roslyn 5.0) and ktsu.Sdk.Analyzers requires Roslyn 5.9, so both runs above had that one analyzer package dropped (CSC : error CS9057 otherwise). The Sonar and .NET analyzers themselves ran normally — CA2000 firing on the first draft of this change is the evidence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01N1cVfacJWw1uM42DUmPfUg


Generated by Claude Code

…active [patch]

`ScopeAfterManualDisposeOfCodeBlockerShouldThrowException` was byte-identical to
`ScopeWithDisposedCodeBlockerShouldThrowException`: it disposed the CodeBlocker
and then asserted that *constructing* a Scope throws. Its name, and its own
"Dispose the CodeBlocker while scope is still active" comment, promise something
else — and that path was untested.

It now opens a scope first, disposes the CodeBlocker out from under it, and
asserts that closing the scope throws `ObjectDisposedException` when `EndScope`
writes its brace to the disposed writer.

CA2000 is suppressed on the one line, with justification: disposing the scope is
the act under test and it throws, so a `using` block would let the exception
escape the assert rather than reach it.

Found by the local SonarCloud reproduction added for #88 (`S4144`), which is
also the first end-to-end confirmation that the setup surfaces real findings.
CLAUDE.md records what the run reports on `main` as a calibration baseline. The
issue's remaining acceptance criterion still needs dashboard access.

Full suite: 168 passed. The Sonar run is now clean apart from five pre-existing
`S2699` warnings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N1cVfacJWw1uM42DUmPfUg
@sonarqubecloud

sonarqubecloud Bot commented Sep 7, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit f3d0764 into main Sep 7, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the claude/github-issues-b0eba5 branch September 7, 2026 02:03
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