Skip to content

Fix MA0002 false positive on interpolated string handlers and invalid code fix on named arguments - #1289

Merged
meziantou merged 2 commits into
mainfrom
feature/meziantou-analyzer-1249-6ca153
Aug 17, 2026
Merged

Fix MA0002 false positive on interpolated string handlers and invalid code fix on named arguments#1289
meziantou merged 2 commits into
mainfrom
feature/meziantou-analyzer-1249-6ca153

Conversation

@meziantou

Copy link
Copy Markdown
Owner

Follow-up investigation of #1249.

The originally reported case is already fixed

I could not reproduce the case from the issue comment on 3.0.159. Built against the real MSTest.TestFramework package, Assert.AreEqual("id", fields[0], "First field should be the ID") correctly produces:

Assert.AreEqual("id", fields[0], System.StringComparer.Ordinal, "First field should be the ID");

Verified across MSTest 3.0.4 / 3.6.4 / 3.9.3 / 4.0.3 / 4.3.3, Roslyn 4.8 / 4.14 / 5.0, C# 9 / 10 / 13, and both #nullable enable and #nullable disable. #1252 shipped in 3.0.136, so 3.0.159 contains it — the report is most likely a stale analyzer in the IDE's analyzer host.

This PR adds regression tests locking that behavior in, plus fixes for two genuine bugs found while investigating.

MA0002 false positive on interpolated string handlers

Assert.AreEqual(a, b, $"msg {x}") binds to MSTest's AssertAreEqualInterpolatedStringHandler<T> overload. The analyzer reported a second diagnostic on the compiler-generated handler construction (located on the $"msg {x}" expression itself), because that handler's constructor also has an overload taking an IEqualityComparer<T>.

That diagnostic is not actionable — there is no argument list in the source code where a comparer could be added — and the code fix registered for it mangles the call. AnalyzeConstructor now skips implicit object creations.

Code fix generated code that doesn't compile with named arguments

Given:

AreEqual(actual: "b", expected: "a");

the fix produced:

AreEqual(actual: "b", expected: "a", System.StringComparer.Ordinal);

which fails with CS8323: Named argument 'actual' is used out-of-position but is followed by an unnamed argument.

The comparer is now emitted as a named argument whenever the argument list already contains named arguments, and the fix is no longer registered when the parameter name could not be determined (per the "validate before registering" guidance in AGENTS.md). The three duplicated insert/append blocks in the fixer were collapsed into a single helper.

Tests

Three tests added to UseStringComparerAnalyzerTests; two of them reference the real MSTest 4.3.3 package:

  • CodeFix_MSTestAreEqualWithMessage_Issue1249
  • CodeFix_MSTestAreEqualWithInterpolatedMessage_Issue1249
  • CodeFix_UseNamedArgumentWhenArgumentsAreNamed

The test harness compiles the fixed code, so the CS8323 case fails loudly without the fixer change.

Verification

  • Full suite green on Roslyn 5.0 (3609 tests), 4.14 (3546), and 4.8 (3512) — 0 failures.
  • dotnet run --project src/DocumentationGenerator exits 0 with no markdown changes.

)

MA0002 reported a diagnostic on compiler-generated interpolated string
handler creations (e.g. MSTest's AssertAreEqualInterpolatedStringHandler<T>
when calling Assert.AreEqual(a, b, $"msg")). There is no argument list in
the source code where a comparer could be added, so the diagnostic is not
actionable. Implicit object creations are now skipped.

The code fix also generated code that doesn't compile when the invocation
already used named arguments: AreEqual(actual: b, expected: a) became
AreEqual(actual: b, expected: a, StringComparer.Ordinal) which reports
CS8323. The comparer is now added as a named argument in that case, and
the fix is not registered when the parameter name is unknown.

Add regression tests using the real MSTest.TestFramework package for the
scenario reported in #1249.
@meziantou
meziantou merged commit 343ae05 into main Aug 17, 2026
12 checks passed
@meziantou
meziantou deleted the feature/meziantou-analyzer-1249-6ca153 branch August 17, 2026 20:43
This was referenced Aug 17, 2026
This was referenced Aug 18, 2026
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