Skip to content

Commit 2075d4c

Browse files
authored
Merge pull request #119 from PhenX/bugfix/115-string-interpolation
Add parenthesis inside string interpolations (Fixes #115)
2 parents fe695d1 + 020facf commit 2075d4c

6 files changed

+115
-2
lines changed

src/EntityFrameworkCore.Projectables.Generator/ExpressionSyntaxRewriter.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,23 @@ public ExpressionSyntaxRewriter(INamedTypeSymbol targetTypeSymbol, NullCondition
7777
return base.VisitInvocationExpression(node);
7878
}
7979

80+
public override SyntaxNode? VisitInterpolation(InterpolationSyntax node)
81+
{
82+
// Visit the expression first
83+
var targetExpression = (ExpressionSyntax)Visit(node.Expression);
84+
85+
// Check if the expression already has parentheses
86+
if (targetExpression is ParenthesizedExpressionSyntax)
87+
{
88+
return node.WithExpression(targetExpression);
89+
}
90+
91+
// Create a new expression wrapped in parentheses
92+
var newExpression = SyntaxFactory.ParenthesizedExpression(targetExpression);
93+
94+
return node.WithExpression(newExpression);
95+
}
96+
8097
public override SyntaxNode? VisitConditionalAccessExpression(ConditionalAccessExpressionSyntax node)
8198
{
8299
var targetExpression = (ExpressionSyntax)Visit(node.Expression);

tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericClassesWithContraints_AreRewritten.verified.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace EntityFrameworkCore.Projectables.Generated
1414
{
1515
static global::System.Linq.Expressions.Expression<global::System.Func<global::Foo.Entity<T, TEnum>, string>> Expression()
1616
{
17-
return (global::Foo.Entity<T, TEnum> @this) => $"{@this.FirstName} {@this.LastName} {@this.SomeSubobject.SomeProp}";
17+
return (global::Foo.Entity<T, TEnum> @this) => $"{(@this.FirstName)} {(@this.LastName)} {(@this.SomeSubobject.SomeProp)}";
1818
}
1919
}
2020
}

tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.GenericClassesWithTypeContraints_AreRewritten.verified.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace EntityFrameworkCore.Projectables.Generated
1313
{
1414
static global::System.Linq.Expressions.Expression<global::System.Func<global::Foo.Entity<T>, string>> Expression()
1515
{
16-
return (global::Foo.Entity<T> @this) => $"{@this.FirstName} {@this.LastName} {@this.SomeSubobject}";
16+
return (global::Foo.Entity<T> @this) => $"{(@this.FirstName)} {(@this.LastName)} {(@this.SomeSubobject)}";
1717
}
1818
}
1919
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// <auto-generated/>
2+
#nullable disable
3+
using System;
4+
using System.Linq;
5+
using EntityFrameworkCore.Projectables;
6+
using Foo;
7+
8+
namespace EntityFrameworkCore.Projectables.Generated
9+
{
10+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
11+
static class Foo_C_Status
12+
{
13+
static global::System.Linq.Expressions.Expression<global::System.Func<global::Foo.C, string>> Expression()
14+
{
15+
return (global::Foo.C @this) => @this.ValidationDate != null ? $"Validation date : ({(global::Foo.MyExtensions.ToDateString(@this.ValidationDate.Value))})" : "";
16+
}
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// <auto-generated/>
2+
#nullable disable
3+
using System;
4+
using System.Linq;
5+
using EntityFrameworkCore.Projectables;
6+
using Foo;
7+
8+
namespace EntityFrameworkCore.Projectables.Generated
9+
{
10+
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
11+
static class Foo_C_Status
12+
{
13+
static global::System.Linq.Expressions.Expression<global::System.Func<global::Foo.C, string>> Expression()
14+
{
15+
return (global::Foo.C @this) => @this.ValidationDate != null ? $"Validation date : ({(global::Foo.MyExtensions.ToDateString(@this.ValidationDate.Value))})" : "";
16+
}
17+
}
18+
}

tests/EntityFrameworkCore.Projectables.Generator.Tests/ProjectionExpressionGeneratorTests.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,66 @@ static class C {
778778

779779
return Verifier.Verify(result.GeneratedTrees[0].ToString());
780780
}
781+
782+
[Fact]
783+
public Task StringInterpolationWithStaticCall_IsBeingRewritten()
784+
{
785+
var compilation = CreateCompilation(@"
786+
using System;
787+
using System.Linq;
788+
using EntityFrameworkCore.Projectables;
789+
790+
namespace Foo {
791+
static class MyExtensions {
792+
public static string ToDateString(this DateTime date) => date.ToString(""dd/MM/yyyy"");
793+
}
794+
795+
class C {
796+
public DateTime? ValidationDate { get; set; }
797+
798+
[Projectable]
799+
public string Status => ValidationDate != null ? $""Validation date : ({ValidationDate.Value.ToDateString()})"" : """";
800+
}
801+
}
802+
");
803+
804+
var result = RunGenerator(compilation);
805+
806+
Assert.Empty(result.Diagnostics);
807+
Assert.Single(result.GeneratedTrees);
808+
809+
return Verifier.Verify(result.GeneratedTrees[0].ToString());
810+
}
811+
812+
[Fact]
813+
public Task StringInterpolationWithParenthesis_NoParenthesisAdded()
814+
{
815+
var compilation = CreateCompilation(@"
816+
using System;
817+
using System.Linq;
818+
using EntityFrameworkCore.Projectables;
819+
820+
namespace Foo {
821+
static class MyExtensions {
822+
public static string ToDateString(this DateTime date) => date.ToString(""dd/MM/yyyy"");
823+
}
824+
825+
class C {
826+
public DateTime? ValidationDate { get; set; }
827+
828+
[Projectable]
829+
public string Status => ValidationDate != null ? $""Validation date : ({(ValidationDate.Value.ToDateString())})"" : """";
830+
}
831+
}
832+
");
833+
834+
var result = RunGenerator(compilation);
835+
836+
Assert.Empty(result.Diagnostics);
837+
Assert.Single(result.GeneratedTrees);
838+
839+
return Verifier.Verify(result.GeneratedTrees[0].ToString());
840+
}
781841

782842
[Fact]
783843
public Task NullableSimpleElementBinding_WithRewriteSupport_IsBeingRewritten()

0 commit comments

Comments
 (0)