From ce5c62d04a48555267d44774024fc6f774e7e719 Mon Sep 17 00:00:00 2001 From: Sebastien Lebreton Date: Tue, 2 Jun 2026 08:33:06 +0200 Subject: [PATCH] Fixes #471: CacheYieldInstructionAnalyzer threw AD0001 (InvalidOperationException) --- .../CacheYieldInstructionAnalyzerTests.cs | 25 +++++++++++++++++++ .../CacheYieldInstructionAnalyzer.cs | 6 ++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.Unity.Analyzers.Tests/CacheYieldInstructionAnalyzerTests.cs b/src/Microsoft.Unity.Analyzers.Tests/CacheYieldInstructionAnalyzerTests.cs index 5cff1c44..03671f60 100644 --- a/src/Microsoft.Unity.Analyzers.Tests/CacheYieldInstructionAnalyzerTests.cs +++ b/src/Microsoft.Unity.Analyzers.Tests/CacheYieldInstructionAnalyzerTests.cs @@ -226,6 +226,31 @@ IEnumerator Coroutine2() await VerifyCSharpFixAsync(test, fixedTest); } + [Fact] + public async Task NonUnityTypeWithMultipleLiteralArguments() + { + // See https://github.com/microsoft/Microsoft.Unity.Analyzers/issues/471 + // The analyzer used to throw AD0001 (InvalidOperationException: Sequence contains more than one matching element) + // when a yield return expression created an object with more than one literal argument. + const string test = @" +using System.Collections.Generic; + +public struct A +{ + public A(int a, int b) + { + } + + public static IEnumerable GetObjs() + { + yield return new A(23, 23); + } +} +"; + + await VerifyCSharpDiagnosticAsync(test); + } + [Fact] public async Task WaitForSecondsAndRealtime() { diff --git a/src/Microsoft.Unity.Analyzers/CacheYieldInstructionAnalyzer.cs b/src/Microsoft.Unity.Analyzers/CacheYieldInstructionAnalyzer.cs index b52171f2..1cdbfca6 100644 --- a/src/Microsoft.Unity.Analyzers/CacheYieldInstructionAnalyzer.cs +++ b/src/Microsoft.Unity.Analyzers/CacheYieldInstructionAnalyzer.cs @@ -56,7 +56,11 @@ private static void AnalyzeYieldReturn(SyntaxNodeAnalysisContext context) if (yieldStatement.Expression is not ObjectCreationExpressionSyntax objectCreation) return; - if (objectCreation.ArgumentList?.Arguments.SingleOrDefault(arg => arg.Expression is LiteralExpressionSyntax) == null) + // The code fix only supports caching when there's exactly one literal argument (see issue #471). + if (objectCreation.ArgumentList?.Arguments is not { Count: 1 } arguments) + return; + + if (arguments[0].Expression is not LiteralExpressionSyntax) return; var typeSymbol = context.SemanticModel.GetTypeInfo(objectCreation).Type;