Skip to content

fix: resolve SonarCloud reliability regression (A→B) from nullable-references PR - #656

Merged
rexm merged 4 commits into
masterfrom
fix/sonar-reliability-s3887
Aug 6, 2026
Merged

fix: resolve SonarCloud reliability regression (A→B) from nullable-references PR#656
rexm merged 4 commits into
masterfrom
fix/sonar-reliability-s3887

Conversation

@rexm

@rexm rexm commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary

SonarCloud's reliability rating dropped from A to B at the analysis of the PR #642 ("Nullable Reference Types") merge commit. The Quality Gate event was Red (was Green) / "Reliability Rating on New Code > 1".

Root cause: PR #642 added ? nullable annotations to two public readonly array field declarations without otherwise changing them. Touching those lines caused SonarCloud to (re-)surface a pre-existing mutable-array-exposure smell (csharpsquid:S3887, "Use an immutable collection or reduce the accessibility of the non-private readonly field") as fresh Bug-type issues:

  • source/Handlebars/Compiler/ClosureBuilder.cs:163Closure.A
  • source/Handlebars/PathStructure/PathInfo.cs:108PathInfo.Segments

Both fields already existed as public arrays before #642; only the reliability-rule bookkeeping was reset by that PR's diff.

Changes

  • Closure.A → made internal. Safe: Closure's constructor is already internal, so no external consumer can ever obtain an instance to read this field. Added InternalsVisibleTo("Handlebars.Test") (new source/Handlebars/Properties/AssemblyInfo.cs) since ClosureBuilderTests.cs reads it directly, and updated the one Type.GetField("A") reflection call in ClosureBuilder.cs to pass BindingFlags.NonPublic | BindingFlags.Instance (default GetField only resolves public members).
  • PathInfo.Segments → left public with a // NOSONAR suppression instead of changing accessibility. PathInfo instances flow through public surfaces (HelperOptions, PathExpression, etc.) and this field has been public since 2020 (pre-1.0), well before the current 2.3.0 release line — flipping it to internal would be a real breaking change for any consumer reflecting on or compiling against it directly.

Test plan

  • dotnet build Handlebars.sln -c Release — succeeds, no new warnings from this change
  • dotnet test --filter "FullyQualifiedName~ClosureBuilderTests|FullyQualifiedName~PathInfoTests" — 19/19 pass (exercises Closure.A and PathInfo.Segments directly)
  • dotnet test Handlebars.sln -c Release — full suite, 1867/1867 pass

rexm added 2 commits August 5, 2026 21:35
…es PR

PR #642 touched two public readonly array field declarations (adding `?`
annotations) without changing their design, which caused SonarCloud to
flag S3887 ("non-private readonly field exposes mutable array") as new
Bug-type issues on both lines, dropping the reliability rating from A to B.

- Closure.A: made internal, since Closure's constructor is already
  internal and the field is unreachable by external consumers. Added
  InternalsVisibleTo("Handlebars.Test") for the one test that reads it
  directly, and pass BindingFlags.NonPublic to the reflection GetField
  call that resolves this field for compiled closure expressions.
- PathInfo.Segments: left public with a NOSONAR suppression instead,
  since PathInfo instances do reach public surfaces (HelperOptions,
  PathExpression, etc.) and the field has been public since 2020 -
  flipping it to internal would be a real breaking change.
@rexm
rexm enabled auto-merge August 6, 2026 01:38
@rexm
rexm disabled auto-merge August 6, 2026 01:38
rexm added 2 commits August 5, 2026 21:41
Making Closure.A internal required BindingFlags.NonPublic on the reflection
GetField("A") lookup used to build compiled closure expressions. SonarCloud
flagged that explicit accessibility bypass as S3011 (MAJOR), which dropped
Maintainability Rating on New Code to C and failed the Quality Gate.

Closure's constructor is already internal, so A was never reachable by
external consumers anyway - reverting to public (with NOSONAR, matching
the treatment already given to PathInfo.Segments) removes the smell
without any real encapsulation loss, and drops the now-unnecessary
InternalsVisibleTo attribute.
@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

@rexm
rexm enabled auto-merge August 6, 2026 01:45
@rexm
rexm merged commit 00a587f into master Aug 6, 2026
7 checks passed
@rexm
rexm deleted the fix/sonar-reliability-s3887 branch August 6, 2026 01:52
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