From 40008ca9441275cf8a3d5b790215ffc5046f6eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Barr=C3=A9?= Date: Sat, 21 Sep 2024 15:30:40 -0400 Subject: [PATCH] Disable ussage of List.Find in .NET 9 --- .../Internals/CompilationExtensions.cs | 7 ++++ .../Rules/OptimizeLinqUsageAnalyzer.cs | 34 +++++++++++-------- .../Helpers/ProjectBuilder.Validation.cs | 2 +- ...eLinqUsageAnalyzerUseDirectMethodsTests.cs | 21 ++++++++++++ 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/Meziantou.Analyzer/Internals/CompilationExtensions.cs b/src/Meziantou.Analyzer/Internals/CompilationExtensions.cs index 145092577..45165810a 100644 --- a/src/Meziantou.Analyzer/Internals/CompilationExtensions.cs +++ b/src/Meziantou.Analyzer/Internals/CompilationExtensions.cs @@ -8,6 +8,13 @@ namespace Meziantou.Analyzer; internal static class CompilationExtensions { + public static bool IsNet9OrGreater(this Compilation compilation) + { + var type = compilation.GetSpecialType(SpecialType.System_Object); + var version = type.ContainingAssembly.Identity.Version; + return version.Major >= 9; + } + #if ROSLYN_3_8 public static ImmutableArray GetTypesByMetadataName(this Compilation compilation, string typeMetadataName) { diff --git a/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs b/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs index 280eee770..abd0ded3f 100755 --- a/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs +++ b/src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs @@ -287,24 +287,28 @@ private void UseFindInsteadOfFirstOrDefault(OperationAnalysisContext context, II if (firstArgumentType is null) return; - if (firstArgumentType.OriginalDefinition.IsEqualTo(ListOfTSymbol)) - { - ImmutableDictionary properties; - var predicateArgument = operation.Arguments[1].Value; - if (predicateArgument is IDelegateCreationOperation) - { - properties = CreateProperties(OptimizeLinqUsageData.UseFindMethod); - } - else - { - if (!context.Options.GetConfigurationValue(operation, ListMethodsRule.Id + ".report_when_conversion_needed", defaultValue: false)) - return; + if (!firstArgumentType.OriginalDefinition.IsEqualTo(ListOfTSymbol)) + return; - properties = CreateProperties(OptimizeLinqUsageData.UseFindMethodWithConversion); - } + // https://github.com/dotnet/runtime/issues/108064 + if (context.Compilation.IsNet9OrGreater()) + return; + + ImmutableDictionary properties; + var predicateArgument = operation.Arguments[1].Value; + if (predicateArgument is IDelegateCreationOperation) + { + properties = CreateProperties(OptimizeLinqUsageData.UseFindMethod); + } + else + { + if (!context.Options.GetConfigurationValue(operation, ListMethodsRule.Id + ".report_when_conversion_needed", defaultValue: false)) + return; - context.ReportDiagnostic(ListMethodsRule, properties, operation, DiagnosticInvocationReportOptions.ReportOnMember, "Find()", operation.TargetMethod.Name); + properties = CreateProperties(OptimizeLinqUsageData.UseFindMethodWithConversion); } + + context.ReportDiagnostic(ListMethodsRule, properties, operation, DiagnosticInvocationReportOptions.ReportOnMember, "Find()", operation.TargetMethod.Name); } private void UseTrueForAllInsteadOfAll(OperationAnalysisContext context, IInvocationOperation operation) diff --git a/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs b/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs index df94c623d..967be2f17 100755 --- a/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs +++ b/tests/Meziantou.Analyzer.Test/Helpers/ProjectBuilder.Validation.cs @@ -191,7 +191,7 @@ private Task CreateProject() break; case TargetFramework.Net9_0: - AddNuGetReference("Microsoft.NETCore.App.Ref", "9.0.0-preview.4.24266.19", "ref/net9.0/"); + AddNuGetReference("Microsoft.NETCore.App.Ref", "9.0.0-rc.1.24431.7", "ref/net9.0/"); break; case TargetFramework.AspNetCore5_0: diff --git a/tests/Meziantou.Analyzer.Test/Rules/OptimizeLinqUsageAnalyzerUseDirectMethodsTests.cs b/tests/Meziantou.Analyzer.Test/Rules/OptimizeLinqUsageAnalyzerUseDirectMethodsTests.cs index 4e3f36156..0bc713fc9 100755 --- a/tests/Meziantou.Analyzer.Test/Rules/OptimizeLinqUsageAnalyzerUseDirectMethodsTests.cs +++ b/tests/Meziantou.Analyzer.Test/Rules/OptimizeLinqUsageAnalyzerUseDirectMethodsTests.cs @@ -14,6 +14,27 @@ private static ProjectBuilder CreateProjectBuilder() .WithCodeFixProvider(); } + [Fact] + public Task FirstOrDefaultAsync_Net9() + => CreateProjectBuilder() + .WithTargetFramework(TargetFramework.Net9_0) + .WithSourceCode(""" + using System.Linq; + class Test + { + public Test() + { + var enumerable = System.Linq.Enumerable.Empty(); + var list = new System.Collections.Generic.List(); + list.FirstOrDefault(); + list.FirstOrDefault(x => x == 0); + enumerable.FirstOrDefault(); + enumerable.FirstOrDefault(x => x == 0); + } + } + """) + .ValidateAsync(); + [Fact] public async Task FirstOrDefaultAsync() {