From 24691d1f022afd4199efcf41ca8e67e01a722697 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Sep 2024 12:01:25 -0700 Subject: [PATCH 1/3] Support converting to collection expression when overloads would not change --- .../UseCollectionExpressionHelpers.cs | 2 +- ...CollectionInitializerDiagnosticAnalyzer.cs | 12 ++++- ...onInitializerTests_CollectionExpression.cs | 54 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs index bedba7efb662a..9a71e050c576b 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs @@ -26,7 +26,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseCollectionExpression; internal static class UseCollectionExpressionHelpers { - private static readonly CollectionExpressionSyntax s_emptyCollectionExpression = CollectionExpression(); + public static readonly CollectionExpressionSyntax s_emptyCollectionExpression = CollectionExpression(); private static readonly SymbolEquivalenceComparer s_tupleNamesCanDifferComparer = SymbolEquivalenceComparer.Create( // Not relevant. We are not comparing method signatures. diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs index 9a7530ed1625c..d26f89dbb7f89 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.LanguageService; @@ -14,6 +15,8 @@ namespace Microsoft.CodeAnalysis.CSharp.UseCollectionInitializer; +using static SyntaxFactory; + [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class CSharpUseCollectionInitializerDiagnosticAnalyzer : AbstractUseCollectionInitializerDiagnosticAnalyzer< @@ -41,5 +44,12 @@ protected override bool AreCollectionExpressionsSupported(Compilation compilatio => compilation.LanguageVersion().SupportsCollectionExpressions(); protected override bool CanUseCollectionExpression(SemanticModel semanticModel, BaseObjectCreationExpressionSyntax objectCreationExpression, INamedTypeSymbol? expressionType, bool allowSemanticsChange, CancellationToken cancellationToken, out bool changesSemantics) - => UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression(semanticModel, objectCreationExpression, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics); + { + // Synthesize the final collection expression we would replace this object-creation with. That will allow us to + // determine if we end up calling the right overload in cases of overloaded methods. + var replacement = UseCollectionExpressionHelpers.CreateReplacementCollectionExpressionForAnalysis(objectCreationExpression.Initializer); + + return UseCollectionExpressionHelpers.CanReplaceWithCollectionExpression( + semanticModel, objectCreationExpression, replacement, expressionType, isSingletonInstance: false, allowSemanticsChange, skipVerificationForReplacedNode: true, cancellationToken, out changesSemantics); + } } diff --git a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs index 4a89e0458efa5..9941e97311d4c 100644 --- a/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs +++ b/src/Analyzers/CSharp/Tests/UseCollectionInitializer/UseCollectionInitializerTests_CollectionExpression.cs @@ -5719,4 +5719,58 @@ void M() ReferenceAssemblies = ReferenceAssemblies.Net.Net80, }.RunAsync(); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/73362")] + public async Task TestWithOverloadResolution1() + { + await new VerifyCS.Test + { + TestCode = """ + using System.Collections.Generic; + + class C + { + public void Test(Class1 param1, Class1 param2) + { + MethodTakingEnumerable([|new|] List { param1, param2 }); + } + + public void MethodTakingEnumerable(IEnumerable param) + { + } + + public void MethodTakingEnumerable(IEnumerable param) + { + } + + public class Class1 { } + public class Class2 { } + } + """, + FixedCode = """ + using System.Collections.Generic; + + class C + { + public void Test(Class1 param1, Class1 param2) + { + MethodTakingEnumerable([param1, param2]); + } + + public void MethodTakingEnumerable(IEnumerable param) + { + } + + public void MethodTakingEnumerable(IEnumerable param) + { + } + + public class Class1 { } + public class Class2 { } + } + """, + LanguageVersion = LanguageVersion.CSharp12, + ReferenceAssemblies = ReferenceAssemblies.Net.Net80, + }.RunAsync(); + } } From a38dc2c16ccefada4ae65cae903c260e49e6e151 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Sep 2024 12:01:58 -0700 Subject: [PATCH 2/3] Update src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs --- .../UseCollectionExpression/UseCollectionExpressionHelpers.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs index 9a71e050c576b..bedba7efb662a 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionExpression/UseCollectionExpressionHelpers.cs @@ -26,7 +26,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UseCollectionExpression; internal static class UseCollectionExpressionHelpers { - public static readonly CollectionExpressionSyntax s_emptyCollectionExpression = CollectionExpression(); + private static readonly CollectionExpressionSyntax s_emptyCollectionExpression = CollectionExpression(); private static readonly SymbolEquivalenceComparer s_tupleNamesCanDifferComparer = SymbolEquivalenceComparer.Create( // Not relevant. We are not comparing method signatures. From 75c9dfffbb3c749212a480cac96dd0958b26c407 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 26 Sep 2024 12:02:20 -0700 Subject: [PATCH 3/3] Revert --- .../CSharpUseCollectionInitializerDiagnosticAnalyzer.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs index d26f89dbb7f89..69b943c5b43f5 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.CSharp.Extensions; using Microsoft.CodeAnalysis.CSharp.LanguageService; @@ -15,8 +14,6 @@ namespace Microsoft.CodeAnalysis.CSharp.UseCollectionInitializer; -using static SyntaxFactory; - [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class CSharpUseCollectionInitializerDiagnosticAnalyzer : AbstractUseCollectionInitializerDiagnosticAnalyzer<