Skip to content

Commit a25737e

Browse files
Copilotarika0093
andauthored
Fix nested SelectExpr inconsistency between playground and source generator (#221)
* Initial plan * Add shared IsNestedInsideAnotherSelectExpr helper and use in playground and source generator Co-authored-by: arika0093 <[email protected]> * Add comprehensive tests for nested SelectExpr consistency fix Co-authored-by: arika0093 <[email protected]> * Remove tests for nested SelectExpr type verification --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: arika0093 <[email protected]> Co-authored-by: Arika Ishinami <[email protected]>
1 parent dd2d380 commit a25737e

File tree

3 files changed

+39
-24
lines changed

3 files changed

+39
-24
lines changed

playground/Services/CodeGenerationService.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,17 @@ SemanticModel semanticModel
161161
private static bool IsSelectExprInvocation(InvocationExpressionSyntax invocation)
162162
{
163163
var expression = invocation.Expression;
164-
return SelectExprHelper.IsSelectExprInvocationSyntax(expression);
164+
if (!SelectExprHelper.IsSelectExprInvocationSyntax(expression))
165+
return false;
166+
167+
// Skip if this SelectExpr is nested inside another SelectExpr.
168+
// When SelectExpr is used inside another SelectExpr (nested SelectExpr),
169+
// only the outermost SelectExpr should generate an interceptor.
170+
// The inner SelectExpr will be converted to a regular Select call by the outer one.
171+
if (SelectExprHelper.IsNestedInsideAnotherSelectExpr(invocation))
172+
return false;
173+
174+
return true;
165175
}
166176

167177
private static SelectExprInfo? GetSelectExprInfo(

src/Linqraft.Core/SelectExprHelper.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,31 @@ SemanticModel semanticModel
8282
var symbolInfo = semanticModel.GetSymbolInfo(invocation);
8383
return IsSelectExprMethod(symbolInfo.Symbol);
8484
}
85+
86+
/// <summary>
87+
/// Checks if the given SelectExpr invocation is nested inside another SelectExpr invocation.
88+
/// When SelectExpr is used inside another SelectExpr (nested SelectExpr),
89+
/// only the outermost SelectExpr should generate an interceptor.
90+
/// The inner SelectExpr will be converted to a regular Select call by the outer one.
91+
/// </summary>
92+
/// <param name="invocation">The invocation expression to check</param>
93+
/// <returns>True if the invocation is nested inside another SelectExpr</returns>
94+
public static bool IsNestedInsideAnotherSelectExpr(InvocationExpressionSyntax invocation)
95+
{
96+
// Walk up the syntax tree to find any ancestor that is also a SelectExpr invocation
97+
var current = invocation.Parent;
98+
while (current is not null)
99+
{
100+
// If we find a parent InvocationExpression that is also a SelectExpr, we are nested
101+
if (current is InvocationExpressionSyntax parentInvocation)
102+
{
103+
if (IsSelectExprInvocationSyntax(parentInvocation.Expression))
104+
{
105+
return true;
106+
}
107+
}
108+
current = current.Parent;
109+
}
110+
return false;
111+
}
85112
}

src/Linqraft.SourceGenerator/SelectExprGenerator.cs

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -106,34 +106,12 @@ private static bool IsSelectExprInvocation(SyntaxNode node)
106106
// When SelectExpr is used inside another SelectExpr (nested SelectExpr),
107107
// only the outermost SelectExpr should generate an interceptor.
108108
// The inner SelectExpr will be converted to a regular Select call by the outer one.
109-
if (IsNestedInsideAnotherSelectExpr(invocation))
109+
if (SelectExprHelper.IsNestedInsideAnotherSelectExpr(invocation))
110110
return false;
111111

112112
return true;
113113
}
114114

115-
/// <summary>
116-
/// Checks if the given SelectExpr invocation is nested inside another SelectExpr invocation.
117-
/// </summary>
118-
private static bool IsNestedInsideAnotherSelectExpr(InvocationExpressionSyntax invocation)
119-
{
120-
// Walk up the syntax tree to find any ancestor that is also a SelectExpr invocation
121-
var current = invocation.Parent;
122-
while (current is not null)
123-
{
124-
// If we find a parent InvocationExpression that is also a SelectExpr, we are nested
125-
if (current is InvocationExpressionSyntax parentInvocation)
126-
{
127-
if (SelectExprHelper.IsSelectExprInvocationSyntax(parentInvocation.Expression))
128-
{
129-
return true;
130-
}
131-
}
132-
current = current.Parent;
133-
}
134-
return false;
135-
}
136-
137115
private static SelectExprInfo? GetSelectExprInfo(GeneratorSyntaxContext context)
138116
{
139117
var invocation = (InvocationExpressionSyntax)context.Node;

0 commit comments

Comments
 (0)