From 659f10ac103ad6c666f2e2fca023b457fb759505 Mon Sep 17 00:00:00 2001 From: Koen Bekkenutte <2912652+kbekkenutte@users.noreply.github.com> Date: Fri, 2 Jul 2021 03:28:40 +0800 Subject: [PATCH] Fixed code gen issue for Projectable extension methods using other projectable extension methods --- .../ExpressionSyntaxRewriter.cs | 12 ++++- .../ExtensionsMethods/EntityExtensions.cs | 3 ++ ...ctProjectableExtensionMethod2.verified.txt | 2 + .../ExtensionsMethods/ExtensionMethodTests.cs | 11 ++++ ...s.ProjectableExtensionMethod3.verified.txt | 14 ++++++ ...s.ProjectableExtensionMethod4.verified.txt | 14 ++++++ .../ProjectionExpressionGeneratorTests.cs | 50 +++++++++++++++++++ 7 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod2.verified.txt create mode 100644 tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod3.verified.txt create mode 100644 tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod4.verified.txt diff --git a/src/EntityFrameworkCore.Projectables.Generator/ExpressionSyntaxRewriter.cs b/src/EntityFrameworkCore.Projectables.Generator/ExpressionSyntaxRewriter.cs index dc21510..311c62e 100644 --- a/src/EntityFrameworkCore.Projectables.Generator/ExpressionSyntaxRewriter.cs +++ b/src/EntityFrameworkCore.Projectables.Generator/ExpressionSyntaxRewriter.cs @@ -51,7 +51,17 @@ namespace EntityFrameworkCore.Projectables.Generator if (symbolInfo.Symbol is not null) { - if (symbolInfo.Symbol.Kind is SymbolKind.Property or SymbolKind.Method or SymbolKind.Field && SymbolEqualityComparer.Default.Equals(symbolInfo.Symbol.ContainingType, _targetTypeSymbol)) + if (symbolInfo.Symbol is IMethodSymbol methodSymbol && methodSymbol.IsExtensionMethod) + { + if (SymbolEqualityComparer.Default.Equals(symbolInfo.Symbol.ContainingType, _targetTypeSymbol)) + { + //return SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + // methodSymbol.ReducedFrom.Sym + //); + //throw new Exception("foo"); + } + } + else if (symbolInfo.Symbol.Kind is SymbolKind.Property or SymbolKind.Method or SymbolKind.Field && SymbolEqualityComparer.Default.Equals(symbolInfo.Symbol.ContainingType, _targetTypeSymbol)) { return SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("@this"), diff --git a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/EntityExtensions.cs b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/EntityExtensions.cs index 4b76d6c..60f29f3 100644 --- a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/EntityExtensions.cs +++ b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/EntityExtensions.cs @@ -11,6 +11,9 @@ namespace EntityFrameworkCore.Projectables.FunctionalTests.ExtensionMethods [Projectable] public static int Foo(this Entity entity) => entity.Id + 1; + [Projectable] + public static int Foo2(this Entity entity) => entity.Foo() + 1; + [Projectable] public static Entity? LeadingEntity(this Entity entity, DbContext dbContext) => dbContext.Set().Where(y => y.Id > entity.Id).FirstOrDefault(); diff --git a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod2.verified.txt b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod2.verified.txt new file mode 100644 index 0000000..a9241ac --- /dev/null +++ b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.SelectProjectableExtensionMethod2.verified.txt @@ -0,0 +1,2 @@ +SELECT ([e].[Id] + 1) + 1 +FROM [Entity] AS [e] \ No newline at end of file diff --git a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.cs b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.cs index cf84943..f525e85 100644 --- a/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.cs +++ b/tests/EntityFrameworkCore.Projectables.FunctionalTests/ExtensionsMethods/ExtensionMethodTests.cs @@ -38,6 +38,17 @@ namespace EntityFrameworkCore.Projectables.FunctionalTests.ExtensionMethods return Verifier.Verify(query.ToQueryString()); } + [Fact] + public Task SelectProjectableExtensionMethod2() + { + using var dbContext = new SampleDbContext(); + + var query = dbContext.Set() + .Select(x => x.Foo2()); + + return Verifier.Verify(query.ToQueryString()); + } + [Fact] public Task ExtensionMethodAcceptingDbContext() { diff --git a/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod3.verified.txt b/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod3.verified.txt new file mode 100644 index 0000000..c3d8de4 --- /dev/null +++ b/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod3.verified.txt @@ -0,0 +1,14 @@ +using System; +using System.Linq; +using EntityFrameworkCore.Projectables; +using Foo; + +namespace EntityFrameworkCore.Projectables.Generated +#nullable disable +{ + public static class Foo_C_Foo1 + { + public static System.Linq.Expressions.Expression> Expression => + (int i) => i; + } +} \ No newline at end of file diff --git a/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod4.verified.txt b/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod4.verified.txt new file mode 100644 index 0000000..d857b66 --- /dev/null +++ b/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.ProjectableExtensionMethod4.verified.txt @@ -0,0 +1,14 @@ +using System; +using System.Linq; +using EntityFrameworkCore.Projectables; +using Foo; + +namespace EntityFrameworkCore.Projectables.Generated +#nullable disable +{ + public static class Foo_C_Foo1 + { + public static System.Linq.Expressions.Expression> Expression => + (object i) => i.Foo1(); + } +} \ No newline at end of file diff --git a/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.cs b/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.cs index 198f3e3..bc87af0 100644 --- a/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.cs +++ b/tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.cs @@ -367,6 +367,56 @@ namespace Foo { return Verifier.Verify(result.GeneratedTrees[0].ToString()); } + + [Fact] + public Task ProjectableExtensionMethod3() + { + var compilation = CreateCompilation(@" +using System; +using System.Linq; +using EntityFrameworkCore.Projectables; +namespace Foo { + static class C { + [Projectable] + public static int Foo1(this int i) => i; + + [Projectable] + public static int Foo2(this int i) => i.Foo1(); + } +} +"); + + var result = RunGenerator(compilation); + + Assert.Empty(result.Diagnostics); + Assert.Equal(2, result.GeneratedTrees.Length); + + return Verifier.Verify(result.GeneratedTrees[0].ToString()); + } + + [Fact] + public Task ProjectableExtensionMethod4() + { + var compilation = CreateCompilation(@" +using System; +using System.Linq; +using EntityFrameworkCore.Projectables; +namespace Foo { + static class C { + [Projectable] + public static object Foo1(this object i) => i.Foo1(); + } +} +"); + + var result = RunGenerator(compilation); + + Assert.Empty(result.Diagnostics); + Assert.Single(result.GeneratedTrees); + + return Verifier.Verify(result.GeneratedTrees[0].ToString()); + } + [Fact] public void BlockBodiedMember_RaisesDiagnostics() {