Skip to content

Commit

Permalink
Disable ussage of List.Find in .NET 9
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou committed Sep 21, 2024
1 parent 3a304f4 commit 40008ca
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 16 deletions.
7 changes: 7 additions & 0 deletions src/Meziantou.Analyzer/Internals/CompilationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<INamedTypeSymbol> GetTypesByMetadataName(this Compilation compilation, string typeMetadataName)
{
Expand Down
34 changes: 19 additions & 15 deletions src/Meziantou.Analyzer/Rules/OptimizeLinqUsageAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,24 +287,28 @@ private void UseFindInsteadOfFirstOrDefault(OperationAnalysisContext context, II
if (firstArgumentType is null)
return;

if (firstArgumentType.OriginalDefinition.IsEqualTo(ListOfTSymbol))
{
ImmutableDictionary<string, string?> 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<string, string?> 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ private Task<Project> 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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ private static ProjectBuilder CreateProjectBuilder()
.WithCodeFixProvider<OptimizeLinqUsageFixer>();
}

[Fact]
public Task FirstOrDefaultAsync_Net9()
=> CreateProjectBuilder()
.WithTargetFramework(TargetFramework.Net9_0)
.WithSourceCode("""
using System.Linq;
class Test
{
public Test()
{
var enumerable = System.Linq.Enumerable.Empty<int>();
var list = new System.Collections.Generic.List<int>();
list.FirstOrDefault();
list.FirstOrDefault(x => x == 0);
enumerable.FirstOrDefault();
enumerable.FirstOrDefault(x => x == 0);
}
}
""")
.ValidateAsync();

[Fact]
public async Task FirstOrDefaultAsync()
{
Expand Down

0 comments on commit 40008ca

Please sign in to comment.