Skip to content

Commit 7d35aa8

Browse files
committed
Ensuring auto-generated LINQ expression parameter names are valid / Removing redundant anonymous type member specifications in member to value assignments re: #97
1 parent 92f847c commit 7d35aa8

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

ReadableExpressions.UnitTests/Extensions/WhenGettingFriendlyTypeNames.cs

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
{
33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Linq.Expressions;
57
using Common;
68
using ReadableExpressions.Extensions;
79
#if !NET35
@@ -135,7 +137,7 @@ public void ShouldNameGenericGenericTypeArguments()
135137

136138
// See https://github.com/agileobjects/ReadableExpressions/issues/94
137139
[Fact]
138-
public void ShouldNamePartClosedGenericTypeArguments()
140+
public void ShouldNamePartClosedGenericTypeArrays()
139141
{
140142
var name = typeof(GenericTestHelper<>)
141143
.GetField("Keys").FieldType
@@ -144,6 +146,29 @@ public void ShouldNamePartClosedGenericTypeArguments()
144146
name.ShouldBe("KeyValuePair<T, int>[]");
145147
}
146148

149+
// See https://github.com/agileobjects/ReadableExpressions/issues/97
150+
[Fact]
151+
public void ShouldNameLinqExpressionVariables()
152+
{
153+
Expression<Func<IEnumerable<int>>> linqQuery = () =>
154+
from s in new[] { "1", "2", "3", "4", "5" }
155+
let n = int.Parse(s)
156+
where n > 3
157+
group s by s into result
158+
select result.Count();
159+
160+
const string EXPECTED = @"
161+
() => new[] { ""1"", ""2"", ""3"", ""4"", ""5"" }
162+
.Select(s => new { s, n = int.Parse(s) })
163+
.Where(_ => _.n > 3)
164+
.GroupBy(_ => _.s, _ => _.s)
165+
.Select(result => result.Count())";
166+
167+
var translated = linqQuery.ToReadableString();
168+
169+
translated.ShouldBe(EXPECTED.TrimStart());
170+
}
171+
147172
#region Helper Classes
148173

149174
// ReSharper disable once UnusedTypeParameter

ReadableExpressions/Translations/AnonymousTypeNewingTranslation.cs

+15-3
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,17 @@ public AnonymousTypeInitializerTranslation(
9797
ParameterInfo member,
9898
ITranslation value)
9999
{
100-
_memberName = member.Name;
101100
_value = value;
102101

102+
if (value is IParameterTranslation parameter &&
103+
parameter.Name == member.Name)
104+
{
105+
_memberName = string.Empty;
106+
TranslationSize = value.TranslationSize;
107+
return;
108+
}
109+
110+
_memberName = member.Name;
103111
TranslationSize = _memberName.Length + 3 + value.TranslationSize;
104112
}
105113

@@ -117,8 +125,12 @@ public AnonymousTypeInitializerTranslation(
117125

118126
public void WriteTo(TranslationWriter writer)
119127
{
120-
writer.WriteToTranslation(_memberName);
121-
writer.WriteToTranslation(" = ");
128+
if (_memberName != string.Empty)
129+
{
130+
writer.WriteToTranslation(_memberName);
131+
writer.WriteToTranslation(" = ");
132+
}
133+
122134
_value.WriteTo(writer);
123135
}
124136
}

ReadableExpressions/Translations/IParameterTranslation.cs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
{
33
internal interface IParameterTranslation : ITranslation
44
{
5+
string Name { get; }
6+
57
void WithTypeNames(ITranslationContext context);
68

79
void WithoutTypeNames(ITranslationContext context);

ReadableExpressions/Translations/ParameterTranslation.cs

+16-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Linq.Expressions;
88
#endif
99
using Extensions;
10+
using static System.StringComparison;
1011
using static Formatting.TokenType;
1112

1213
internal static class ParameterTranslation
@@ -18,13 +19,22 @@ public static ITranslation For(ParameterExpression parameter, ITranslationContex
1819
return new UnnamedParameterTranslation(parameter, context);
1920
}
2021

22+
if (parameter.Name.StartsWith("<>", Ordinal))
23+
{
24+
return new FixedValueTranslation(
25+
ExpressionType.Parameter,
26+
"_",
27+
parameter.Type,
28+
Variable,
29+
context);
30+
}
31+
2132
return new StandardParameterTranslation(parameter, context);
2233
}
2334

2435
private abstract class ParameterTranslationBase : IParameterTranslation
2536
{
2637
private readonly ParameterExpression _parameter;
27-
private readonly string _parameterName;
2838
private ITranslation _typeNameTranslation;
2939

3040
protected ParameterTranslationBase(
@@ -33,9 +43,9 @@ protected ParameterTranslationBase(
3343
ITranslationContext context)
3444
{
3545
_parameter = parameter;
36-
_parameterName = parameterName;
46+
Name = parameterName;
3747

38-
TranslationSize = _parameterName.Length;
48+
TranslationSize = Name.Length;
3949
FormattingSize = context.GetFormattingSize(Variable);
4050
}
4151

@@ -47,6 +57,8 @@ protected ParameterTranslationBase(
4757

4858
public int FormattingSize { get; private set; }
4959

60+
public string Name { get; }
61+
5062
public void WithTypeNames(ITranslationContext context)
5163
{
5264
_typeNameTranslation = context.GetTranslationFor(Type);
@@ -77,7 +89,7 @@ public void WriteTo(TranslationWriter writer)
7789
writer.WriteSpaceToTranslation();
7890
}
7991

80-
writer.WriteToTranslation(_parameterName, Variable);
92+
writer.WriteToTranslation(Name, Variable);
8193
}
8294
}
8395

0 commit comments

Comments
 (0)