Skip to content

Do not report MA0005 for the params array synthesized by a collection expression - #1531

Merged
meziantou merged 3 commits into
mainfrom
feature/meziantou-analyzer-1530-0062fc
Sep 18, 2026
Merged

meziantou merged 3 commits into
mainfrom
feature/meziantou-analyzer-1530-0062fc

Conversation

@meziantou

@meziantou meziantou commented Sep 18, 2026 •

Copy link
Copy Markdown
Owner

Fixes #1530

What changed

MA0005 (Use Array.Empty<T>()) no longer reports the empty array that the compiler synthesizes for a collection expression.

public static TheoryData<string> Data => ["foo", "bar"]; // MA0005 was reported here

Why

A collection expression calls the collection type's constructor with no arguments, then Add for each element. When that constructor takes a params T[] parameter, as in the TheoryData<T> of the issue, the compiler creates an empty array for it. The user cannot replace that array with Array.Empty<T>(), so the diagnostic was a false positive. MA0005 already skipped these synthesized arrays for method calls, constructor calls and indexers, but not for collection expressions.

Notes for reviewers

  • The analyzer now skips any IArrayCreationOperation where IsImplicit is true, since the user did not write that array and cannot replace it. The exception is an array initializer without new (int[] a = { };): Roslyn marks it as implicit, but the user wrote it, so it is still reported.
  • This replaces IsCompilerGeneratedParamsArray, which matched the synthesized array against the last argument of the parent method, constructor or indexer call and did not handle collection expressions. The existing tests for those cases and for implicit params arrays in attributes still pass.
  • IsInAttribute is kept for an explicit new int[0] inside an attribute, where Array.Empty<T>() is not allowed.
  • Added CollectionExpression_ParamsConstructor_ShouldNotReportError, which failed before the fix, and tests for array initializers (local and field), an explicit empty array passed to params, a generic element type, and a non-constant length. The UseArrayEmptyAnalyzerTests pass on Roslyn 4.8, 4.14, 5.0, 5.6 and 5.9.

…ection expression

A collection expression calls the constructor of the collection type without arguments,
so the compiler synthesizes an empty array when that constructor has a params parameter
(e.g. xUnit's TheoryData<T>). Users cannot replace it with Array.Empty<T>().

Fixes #1530
The arrays the compiler creates for a params parameter (method, constructor,
indexer, attribute, or the constructor called by a collection expression) are
implicit operations, so there is no need to match them against the arguments
of the parent operation.
The array created by an array initializer (int[] a = { }) is an implicit
operation, but it is written by the user, so it must still be reported.
Add tests for array initializers, explicit arrays passed to params,
generic element types, and non-constant lengths.
@meziantou
meziantou enabled auto-merge (squash) September 18, 2026 21:14
@meziantou
meziantou merged commit 419737e into main Sep 18, 2026
13 checks passed
@meziantou
meziantou deleted the feature/meziantou-analyzer-1530-0062fc branch September 18, 2026 21:18
This was referenced Sep 18, 2026
This was referenced Sep 26, 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.

MA0005 shouldn't be reported

1 participant