Skip to content

Commit 6d468fa

Browse files
committed
fixed nested-lambda variable collission
1 parent a1d0138 commit 6d468fa

6 files changed

Lines changed: 64 additions & 19 deletions

src/ExpressiveSharp.Generator/Emitter/ExpressionTreeEmitter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,7 @@ private string EmitNestedLambda(IAnonymousFunctionOperation lambda)
14361436
foreach (var param in lambdaParams)
14371437
{
14381438
var paramTypeFqn = param.Type.ToDisplayString(_fqnFormat);
1439-
var varName = $"p_{SanitizeIdentifier(param.Name)}_{_varCounter++}";
1439+
var varName = $"{_varPrefix}p_{SanitizeIdentifier(param.Name)}_{_varCounter++}";
14401440
_symbolToVar[param] = varName;
14411441
paramVarNames.Add(varName);
14421442
AppendLine($"var {varName} = {Expr}.Parameter(typeof({paramTypeFqn}), \"{param.Name}\");");

tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdateAsync_GeneratesInterceptor.verified.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ namespace ExpressiveSharp.Generated.Interceptors
1313
{
1414
// Source: s => s.SetProperty(o => o.Tag, "updated")
1515
var i361d58c24_p_s = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>), "s");
16-
var p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
17-
var i361d58c24_expr_2 = global::System.Linq.Expressions.Expression.Property(p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
18-
var i361d58c24_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d58c24_expr_2, p_o_1);
16+
var i361d58c24_p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
17+
var i361d58c24_expr_2 = global::System.Linq.Expressions.Expression.Property(i361d58c24_p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
18+
var i361d58c24_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d58c24_expr_2, i361d58c24_p_o_1);
1919
var i361d58c24_expr_4 = global::System.Linq.Expressions.Expression.Constant("updated", typeof(string)); // "updated"
2020
var i361d58c24_expr_0 = global::System.Linq.Expressions.Expression.Call(i361d58c24_p_s, global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance), m => m.Name == "SetProperty" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericParameter && !m.GetParameters()[1].ParameterType.IsGenericType)).MakeGenericMethod(typeof(string)), new global::System.Linq.Expressions.Expression[] { i361d58c24_expr_3, i361d58c24_expr_4 });
2121
var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.SetPropertyCalls<global::TestNs.Order>, global::TestNs.SetPropertyCalls<global::TestNs.Order>>>(i361d58c24_expr_0, i361d58c24_p_s);

tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdate_SetProperty_ConstantValue.verified.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ namespace ExpressiveSharp.Generated.Interceptors
1212
{
1313
// Source: s => s.SetProperty(o => o.Tag, "updated")
1414
var i361d58c18_p_s = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>), "s");
15-
var p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
16-
var i361d58c18_expr_2 = global::System.Linq.Expressions.Expression.Property(p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
17-
var i361d58c18_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d58c18_expr_2, p_o_1);
15+
var i361d58c18_p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
16+
var i361d58c18_expr_2 = global::System.Linq.Expressions.Expression.Property(i361d58c18_p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
17+
var i361d58c18_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d58c18_expr_2, i361d58c18_p_o_1);
1818
var i361d58c18_expr_4 = global::System.Linq.Expressions.Expression.Constant("updated", typeof(string)); // "updated"
1919
var i361d58c18_expr_0 = global::System.Linq.Expressions.Expression.Call(i361d58c18_p_s, global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance), m => m.Name == "SetProperty" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericParameter && !m.GetParameters()[1].ParameterType.IsGenericType)).MakeGenericMethod(typeof(string)), new global::System.Linq.Expressions.Expression[] { i361d58c18_expr_3, i361d58c18_expr_4 });
2020
var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.SetPropertyCalls<global::TestNs.Order>, global::TestNs.SetPropertyCalls<global::TestNs.Order>>>(i361d58c18_expr_0, i361d58c18_p_s);

tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdate_SetProperty_WithNullConditional.verified.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,19 @@ namespace ExpressiveSharp.Generated.Interceptors
1212
{
1313
// Source: s => s.SetProperty(o => o.Tag, o => o.Customer?.Name ?? "none")
1414
var i361d63c18_p_s = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>), "s");
15-
var p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
16-
var i361d63c18_expr_2 = global::System.Linq.Expressions.Expression.Property(p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
17-
var i361d63c18_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d63c18_expr_2, p_o_1);
18-
var p_o_4 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Customer?.Name ?? "none"
19-
var i361d63c18_expr_6 = global::System.Linq.Expressions.Expression.Property(p_o_4, typeof(global::TestNs.Order).GetProperty("Customer", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Customer
15+
var i361d63c18_p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
16+
var i361d63c18_expr_2 = global::System.Linq.Expressions.Expression.Property(i361d63c18_p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
17+
var i361d63c18_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d63c18_expr_2, i361d63c18_p_o_1);
18+
var i361d63c18_p_o_4 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Customer?.Name ?? "none"
19+
var i361d63c18_expr_6 = global::System.Linq.Expressions.Expression.Property(i361d63c18_p_o_4, typeof(global::TestNs.Order).GetProperty("Customer", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Customer
2020
var i361d63c18_expr_7 = global::System.Linq.Expressions.Expression.Property(i361d63c18_expr_6, typeof(global::TestNs.Customer).GetProperty("Name", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // .Name
2121
var i361d63c18_expr_9 = global::System.Linq.Expressions.Expression.Constant(null, typeof(global::TestNs.Customer));
2222
var i361d63c18_expr_10 = global::System.Linq.Expressions.Expression.NotEqual(i361d63c18_expr_6, i361d63c18_expr_9);
2323
var i361d63c18_expr_11 = global::System.Linq.Expressions.Expression.Default(typeof(string));
2424
var i361d63c18_expr_8 = global::System.Linq.Expressions.Expression.Condition(i361d63c18_expr_10, i361d63c18_expr_7, i361d63c18_expr_11, typeof(string));
2525
var i361d63c18_expr_12 = global::System.Linq.Expressions.Expression.Constant("none", typeof(string)); // "none"
2626
var i361d63c18_expr_5 = global::System.Linq.Expressions.Expression.Coalesce(i361d63c18_expr_8, i361d63c18_expr_12);
27-
var i361d63c18_expr_13 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d63c18_expr_5, p_o_4);
27+
var i361d63c18_expr_13 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d63c18_expr_5, i361d63c18_p_o_4);
2828
var i361d63c18_expr_0 = global::System.Linq.Expressions.Expression.Call(i361d63c18_p_s, global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance), m => m.Name == "SetProperty" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericType && !m.GetParameters()[1].ParameterType.IsGenericParameter)).MakeGenericMethod(typeof(string)), new global::System.Linq.Expressions.Expression[] { i361d63c18_expr_3, i361d63c18_expr_13 });
2929
var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.SetPropertyCalls<global::TestNs.Order>, global::TestNs.SetPropertyCalls<global::TestNs.Order>>>(i361d63c18_expr_0, i361d63c18_p_s);
3030
return global::TestNs.MockRelationalExtensions.ExecuteUpdate(

tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/ExecuteUpdateTests.ExecuteUpdate_SetProperty_WithSwitchExpression.verified.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ namespace ExpressiveSharp.Generated.Interceptors
1212
{
1313
// Source: s => s.SetProperty(o => o.Tag, o => o.Amount switch { > 100 => "high", > 50 => "medium", _ => "low" })
1414
var i361d62c18_p_s = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>), "s");
15-
var p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
16-
var i361d62c18_expr_2 = global::System.Linq.Expressions.Expression.Property(p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
17-
var i361d62c18_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d62c18_expr_2, p_o_1);
18-
var p_o_4 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Amount switch { ...
19-
var i361d62c18_expr_5 = global::System.Linq.Expressions.Expression.Property(p_o_4, typeof(global::TestNs.Order).GetProperty("Amount", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Amount
15+
var i361d62c18_p_o_1 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Tag
16+
var i361d62c18_expr_2 = global::System.Linq.Expressions.Expression.Property(i361d62c18_p_o_1, typeof(global::TestNs.Order).GetProperty("Tag", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Tag
17+
var i361d62c18_expr_3 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d62c18_expr_2, i361d62c18_p_o_1);
18+
var i361d62c18_p_o_4 = global::System.Linq.Expressions.Expression.Parameter(typeof(global::TestNs.Order), "o"); // o => o.Amount switch { ...
19+
var i361d62c18_expr_5 = global::System.Linq.Expressions.Expression.Property(i361d62c18_p_o_4, typeof(global::TestNs.Order).GetProperty("Amount", global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance)); // o.Amount
2020
var i361d62c18_expr_6 = global::System.Linq.Expressions.Expression.Constant("low", typeof(string)); // "low"
2121
var i361d62c18_expr_8 = global::System.Linq.Expressions.Expression.Constant(50, typeof(int)); // 50
2222
var i361d62c18_expr_7 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, i361d62c18_expr_5, i361d62c18_expr_8);
@@ -26,7 +26,7 @@ namespace ExpressiveSharp.Generated.Interceptors
2626
var i361d62c18_expr_11 = global::System.Linq.Expressions.Expression.MakeBinary(global::System.Linq.Expressions.ExpressionType.GreaterThan, i361d62c18_expr_5, i361d62c18_expr_12);
2727
var i361d62c18_expr_13 = global::System.Linq.Expressions.Expression.Constant("high", typeof(string)); // "high"
2828
var i361d62c18_expr_14 = global::System.Linq.Expressions.Expression.Condition(i361d62c18_expr_11, i361d62c18_expr_13, i361d62c18_expr_10, typeof(string));
29-
var i361d62c18_expr_15 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d62c18_expr_14, p_o_4);
29+
var i361d62c18_expr_15 = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.Order, string>>(i361d62c18_expr_14, i361d62c18_p_o_4);
3030
var i361d62c18_expr_0 = global::System.Linq.Expressions.Expression.Call(i361d62c18_p_s, global::System.Linq.Enumerable.First(global::System.Linq.Enumerable.Where(typeof(global::TestNs.SetPropertyCalls<global::TestNs.Order>).GetMethods(global::System.Reflection.BindingFlags.Public | global::System.Reflection.BindingFlags.NonPublic | global::System.Reflection.BindingFlags.Instance), m => m.Name == "SetProperty" && m.IsGenericMethodDefinition && m.GetGenericArguments().Length == 1 && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType.IsGenericType && !m.GetParameters()[0].ParameterType.IsGenericParameter && m.GetParameters()[1].ParameterType.IsGenericType && !m.GetParameters()[1].ParameterType.IsGenericParameter)).MakeGenericMethod(typeof(string)), new global::System.Linq.Expressions.Expression[] { i361d62c18_expr_3, i361d62c18_expr_15 });
3131
var __lambda = global::System.Linq.Expressions.Expression.Lambda<global::System.Func<global::TestNs.SetPropertyCalls<global::TestNs.Order>, global::TestNs.SetPropertyCalls<global::TestNs.Order>>>(i361d62c18_expr_0, i361d62c18_p_s);
3232
return global::TestNs.MockRelationalExtensions.ExecuteUpdate(

tests/ExpressiveSharp.Generator.Tests/PolyfillInterceptorGenerator/JoinTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,49 @@ public void Run(System.Linq.IQueryable<Order> orders, System.Collections.Generic
179179

180180
Assert.AreEqual(0, errors.Count, string.Join("\n", errors.Select(d => d.ToString())));
181181
}
182+
183+
// Regression: two sibling key-selector lambdas in a multi-lambda interceptor each contain a
184+
// nested lambda with the same parameter name. The nested-lambda ParameterExpression variable
185+
// must carry the per-lambda _varPrefix; without it, both emitters declare the same local
186+
// (p_t_<n>) in the shared interceptor body → CS0128 duplicate-variable compile error.
187+
[TestMethod]
188+
public void Join_SiblingKeySelectorsWithNestedLambdas_GeneratedInterceptorCompiles()
189+
{
190+
var source =
191+
"""
192+
using ExpressiveSharp;
193+
194+
namespace TestNs
195+
{
196+
class Order { public int CustomerId { get; set; } public System.Collections.Generic.List<string> Tags { get; set; } }
197+
class Customer { public int Id { get; set; } public System.Collections.Generic.List<string> Labels { get; set; } }
198+
class TestClass
199+
{
200+
public void Run(System.Linq.IQueryable<Order> orders, System.Collections.Generic.IEnumerable<Customer> customers)
201+
{
202+
orders.AsExpressive()
203+
.Join(customers,
204+
o => o.Tags.Count(t => t.Length > 0),
205+
c => c.Labels.Count(t => t.Length > 0),
206+
(o, c) => o.CustomerId)
207+
.ToList();
208+
}
209+
}
210+
}
211+
""";
212+
213+
var compilation = CreateCompilation(source);
214+
var subject = new global::ExpressiveSharp.Generator.PolyfillInterceptorGenerator();
215+
GeneratorDriver driver = CSharpGeneratorDriver
216+
.Create(subject)
217+
.WithUpdatedParseOptions((CSharpParseOptions)compilation.SyntaxTrees.First().Options)
218+
.RunGeneratorsAndUpdateCompilation(compilation, out var outputCompilation, out _);
219+
220+
var errors = outputCompilation.GetDiagnostics()
221+
.Where(d => d.Severity == DiagnosticSeverity.Error)
222+
.Where(d => d.Id != "CS9137")
223+
.ToList();
224+
225+
Assert.AreEqual(0, errors.Count, string.Join("\n", errors.Select(d => d.ToString())));
226+
}
182227
}

0 commit comments

Comments
 (0)