Skip to content

Commit 67fc48d

Browse files
authored
Merge pull request #75 from koenbeuk/issue-73
Don't throw when out of accessible expressions
2 parents 7ef4e64 + 80740fc commit 67fc48d

File tree

2 files changed

+84
-18
lines changed

2 files changed

+84
-18
lines changed

src/EntityFrameworkCore.Projectables.Generator/ExpressionSyntaxRewriter.cs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ public ExpressionSyntaxRewriter(INamedTypeSymbol targetTypeSymbol, NullCondition
7272
{
7373
var diagnostic = Diagnostic.Create(Diagnostics.NullConditionalRewriteUnsupported, node.GetLocation(), node);
7474
_context.ReportDiagnostic(diagnostic);
75+
76+
// Return the original node, do not attempt further rewrites
77+
return node;
7578
}
7679

7780
else if (_nullConditionalRewriteSupport is NullConditionalRewriteSupport.Ignore)
@@ -112,34 +115,34 @@ public ExpressionSyntaxRewriter(INamedTypeSymbol targetTypeSymbol, NullCondition
112115

113116
public override SyntaxNode? VisitMemberBindingExpression(MemberBindingExpressionSyntax node)
114117
{
115-
if (_conditionalAccessExpressionsStack.Count == 0)
118+
if (_conditionalAccessExpressionsStack.Count > 0)
116119
{
117-
throw new InvalidOperationException("Expected at least one conditional expression on the stack");
118-
}
120+
var targetExpression = _conditionalAccessExpressionsStack.Pop();
119121

120-
var targetExpression = _conditionalAccessExpressionsStack.Pop();
122+
return _nullConditionalRewriteSupport switch {
123+
NullConditionalRewriteSupport.Ignore => SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, targetExpression, node.Name),
124+
NullConditionalRewriteSupport.Rewrite => SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, targetExpression, node.Name),
125+
_ => node
126+
};
127+
}
121128

122-
return _nullConditionalRewriteSupport switch {
123-
NullConditionalRewriteSupport.Ignore => SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, targetExpression, node.Name),
124-
NullConditionalRewriteSupport.Rewrite => SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, targetExpression, node.Name),
125-
_ => node
126-
};
129+
return base.VisitMemberBindingExpression(node);
127130
}
128131

129132
public override SyntaxNode? VisitElementBindingExpression(ElementBindingExpressionSyntax node)
130133
{
131-
if (_conditionalAccessExpressionsStack.Count == 0)
134+
if (_conditionalAccessExpressionsStack.Count > 0)
132135
{
133-
throw new InvalidOperationException("Expected at least one conditional expression on the stack");
134-
}
136+
var targetExpression = _conditionalAccessExpressionsStack.Pop();
135137

136-
var targetExpression = _conditionalAccessExpressionsStack.Pop();
138+
return _nullConditionalRewriteSupport switch {
139+
NullConditionalRewriteSupport.Ignore => SyntaxFactory.ElementAccessExpression(targetExpression, node.ArgumentList),
140+
NullConditionalRewriteSupport.Rewrite => SyntaxFactory.ElementAccessExpression(targetExpression, node.ArgumentList),
141+
_ => Visit(node)
142+
};
143+
}
137144

138-
return _nullConditionalRewriteSupport switch {
139-
NullConditionalRewriteSupport.Ignore => SyntaxFactory.ElementAccessExpression(targetExpression, node.ArgumentList),
140-
NullConditionalRewriteSupport.Rewrite => SyntaxFactory.ElementAccessExpression(targetExpression, node.ArgumentList),
141-
_ => Visit(node)
142-
};
145+
return base.VisitElementBindingExpression(node);
143146
}
144147

145148
public override SyntaxNode? VisitThisExpression(ThisExpressionSyntax node)

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,69 @@ static class C {
644644
Assert.Equal("EFP0002", diagnostic.Id);
645645
}
646646

647+
[Fact]
648+
public void NullableMemberBinding_UndefinedSupport_IsBeingReported()
649+
{
650+
var compilation = CreateCompilation(@"
651+
using System;
652+
using System.Linq;
653+
using EntityFrameworkCore.Projectables;
654+
655+
namespace Foo {
656+
static class C {
657+
[Projectable]
658+
public static int? GetLength(this string input) => input?.Length;
659+
}
660+
}
661+
");
662+
var result = RunGenerator(compilation);
663+
664+
var diagnostic = Assert.Single(result.Diagnostics);
665+
Assert.Equal("EFP0002", diagnostic.Id);
666+
}
667+
668+
669+
[Fact]
670+
public void MultiLevelNullableMemberBinding_UndefinedSupport_IsBeingReported()
671+
{
672+
var compilation = CreateCompilation(@"
673+
using System;
674+
using System.Linq;
675+
using EntityFrameworkCore.Projectables;
676+
677+
namespace Foo {
678+
public record Address
679+
{
680+
public int Id { get; set; }
681+
public string? Country { get; set; }
682+
}
683+
684+
public record Party
685+
{
686+
public int Id { get; set; }
687+
688+
public Address? Address { get; set; }
689+
}
690+
691+
public record Entity
692+
{
693+
public int Id { get; set; }
694+
695+
public Party? Left { get; set; }
696+
public Party? Right { get; set; }
697+
698+
[Projectable]
699+
public bool IsSameCountry => Left?.Address?.Country == Right?.Address?.Country;
700+
}
701+
}
702+
");
703+
var result = RunGenerator(compilation);
704+
705+
Assert.All(result.Diagnostics, diagnostic => {
706+
Assert.Equal("EFP0002", diagnostic.Id);
707+
});
708+
}
709+
647710
[Fact]
648711
public Task NullableMemberBinding_WithIgnoreSupport_IsBeingRewritten()
649712
{

0 commit comments

Comments
 (0)