diff --git a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs index 036f8392254..86233899504 100644 --- a/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs +++ b/analyzers/src/SonarAnalyzer.Common/Helpers/KnownType.cs @@ -83,7 +83,6 @@ public sealed partial class KnownType public static readonly KnownType Microsoft_Azure_WebJobs_FunctionNameAttribute = new("Microsoft.Azure.WebJobs.FunctionNameAttribute"); public static readonly KnownType Microsoft_Data_Sqlite_SqliteCommand = new("Microsoft.Data.Sqlite.SqliteCommand"); public static readonly KnownType Microsoft_EntityFrameworkCore_DbContextOptionsBuilder = new("Microsoft.EntityFrameworkCore.DbContextOptionsBuilder"); - public static readonly KnownType Microsoft_EntityFrameworkCore_DbSet_TEntity = new("Microsoft.EntityFrameworkCore.DbSet", "TEntity"); public static readonly KnownType Microsoft_EntityFrameworkCore_Migrations_Migration = new("Microsoft.EntityFrameworkCore.Migrations.Migration"); public static readonly KnownType Microsoft_EntityFrameworkCore_MySQLDbContextOptionsExtensions = new("Microsoft.EntityFrameworkCore.MySQLDbContextOptionsExtensions"); public static readonly KnownType Microsoft_EntityFrameworkCore_NpgsqlDbContextOptionsExtensions = new("Microsoft.EntityFrameworkCore.NpgsqlDbContextOptionsExtensions"); @@ -328,6 +327,7 @@ public sealed partial class KnownType public static readonly KnownType System_Linq_Expressions_Expression = new("System.Linq.Expressions.Expression"); public static readonly KnownType System_Linq_Expressions_Expression_T = new("System.Linq.Expressions.Expression", "TDelegate"); public static readonly KnownType System_Linq_ImmutableArrayExtensions = new("System.Linq.ImmutableArrayExtensions"); + public static readonly KnownType System_Linq_IQueryable = new("System.Linq.IQueryable", "T"); public static readonly KnownType System_Linq_Queryable = new("System.Linq.Queryable"); public static readonly KnownType System_MarshalByRefObject = new("System.MarshalByRefObject"); public static readonly KnownType System_MTAThreadAttribute = new("System.MTAThreadAttribute"); diff --git a/analyzers/src/SonarAnalyzer.Common/Rules/InsteadOfAnyBase.cs b/analyzers/src/SonarAnalyzer.Common/Rules/InsteadOfAnyBase.cs index f6dce5dc16d..7886c4eeca1 100644 --- a/analyzers/src/SonarAnalyzer.Common/Rules/InsteadOfAnyBase.cs +++ b/analyzers/src/SonarAnalyzer.Common/Rules/InsteadOfAnyBase.cs @@ -39,10 +39,6 @@ public abstract class InsteadOfAnyBase : Son KnownType.System_Collections_Generic_HashSet_T, KnownType.System_Collections_Generic_SortedSet_T); - protected static readonly ImmutableArray DbSetTypes = ImmutableArray.Create( - KnownType.System_Data_Entity_DbSet_TEntity, - KnownType.Microsoft_EntityFrameworkCore_DbSet_TEntity); - protected abstract ILanguageFacade Language { get; } protected abstract HashSet ExitParentKinds { get; } @@ -140,7 +136,7 @@ private bool IsUsedByEntityFramework(SyntaxNode node, SemanticModel model) if (Language.Syntax.IsKind(node, Language.SyntaxKind.InvocationExpression) && Language.Syntax.TryGetOperands(node, out var left, out var _) - && model.GetTypeInfo(left).Type.DerivesFromAny(DbSetTypes)) + && model.GetTypeInfo(left).Type.DerivesOrImplements(KnownType.System_Linq_IQueryable)) { return true; } diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.cs index a7c32094281..923a80d0c66 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.cs @@ -30,6 +30,9 @@ public void GetEntities(FirstContext dbContext, List ids) _ = dbContext.MyEntities.Where(e => ids.Any(i => e.Id is i)); // Error [CS0150] _ = dbContext.MyEntities.Where(e => ids.Any(i => e.Id is 2)); // Error [CS8122] + + var iqueryable = dbContext.MyEntities.OrderBy(e => e.Id); + _ = iqueryable.Where(e => ids.Any(i => e.Id == i)); // Compliant } public async Task GetEntitiesAsync(SecondContext secondContext, List ids) diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.vb b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.vb index 05a0cbc91cb..fec2edc82b4 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.vb +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Core.vb @@ -17,6 +17,10 @@ Public Class EntityFrameworkTestcases __ = dbContext.MyEntities.Where(Function(e) ids.Any(Function(i) e.Equals(i))) ' Compliant __ = dbContext.MyEntities.Where(Function(e) ids.Any(Function(i) e.Id > i)) ' Compliant __ = dbContext.MyEntities.Where(Function(e) ids.Any(Function(i) TypeOf e.Id Is i)) ' Error [BC30002] + + Dim iqueryable = dbContext.MyEntities.OrderBy(Function(e) e.Id) + __ = iqueryable.Where(Function(e) ids.Any(Function(i) e.Id = i)) ' Compliant + End Sub End Class End Class diff --git a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Framework.cs b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Framework.cs index 252c4e3cdce..50a5a59efe5 100644 --- a/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Framework.cs +++ b/analyzers/tests/SonarAnalyzer.UnitTest/TestCases/InsteadOfAny.EntityFramework.Framework.cs @@ -28,6 +28,9 @@ public void GetEntities(FirstContext dbContext, List ids) _ = dbContext.MyEntities.Where(e => ids.Any(i => e.Id == i)); // Compliant _ = dbContext.MyEntities.Where(e => ids.Any(i => e.Equals(i))); // Compliant _ = dbContext.MyEntities.Where(e => ids.Any(i => e.Id > i)); // Compliant + + var iqueryable = dbContext.MyEntities.OrderBy(e => e.Id); + _ = iqueryable.Where(e => ids.Any(i => e.Id == i)); // Compliant } public async Task GetEntitiesAsync(SecondContext secondContext, List ids)