Skip to content

Commit 6b9aa2c

Browse files
authored
v4.1.1 (#132)
* Fixing static method access when showing captured value / Translating enum comparisons as enum constants re: #129 * Updating version number * v4.1.1 NuGet package --------- Co-authored-by: Steve Wilkes <[email protected]>
1 parent 8b3b4a0 commit 6b9aa2c

File tree

7 files changed

+99
-24
lines changed

7 files changed

+99
-24
lines changed
Binary file not shown.
Binary file not shown.

src/ReadableExpressions/Extensions/InternalExpressionExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public static bool IsCapturedValue(
9090

9191
case Call:
9292
var methodCall = (MethodCallExpression)expression;
93-
expression = methodCall.Object;
93+
expression = methodCall.GetSubject();
9494
capturedMemberAccesses.Add(methodCall.Method);
9595
continue;
9696

src/ReadableExpressions/ReadableExpressions.csproj

+6-11
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
<NetStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard1.0' ">1.6.1</NetStandardImplicitPackageVersion>
1515
<PackageTargetFallback Condition=" '$(TargetFramework)' == 'netstandard1.0' ">$(PackageTargetFallback);dnxcore50</PackageTargetFallback>
1616

17-
<AssemblyVersion>4.1.0.0</AssemblyVersion>
18-
<FileVersion>4.1.0.0</FileVersion>
19-
<VersionPrefix>4.1.0</VersionPrefix>
20-
<Version>4.1.0</Version>
17+
<AssemblyVersion>4.1.1.0</AssemblyVersion>
18+
<FileVersion>4.1.1.0</FileVersion>
19+
<VersionPrefix>4.1.1</VersionPrefix>
20+
<Version>4.1.1</Version>
2121

2222
<PackageId>AgileObjects.ReadableExpressions</PackageId>
2323
<Title>AgileObjects.ReadableExpressions</Title>
@@ -26,13 +26,8 @@
2626
<PackageIcon>./Icon.png</PackageIcon>
2727
<PackageTags>ExpressionTrees Debugging DebuggerVisualizers Linq DLR</PackageTags>
2828
<PackageProjectUrl>https://github.com/AgileObjects/ReadableExpressions</PackageProjectUrl>
29-
<PackageReleaseNotes>- Fixing Guid constant translation, re: #119
30-
- Fixing various string concatenation issues, re: #120, 123
31-
- Rendering string.Concat(Object) calls as method calls, not concatenation, re: #116
32-
- Fixing custom method conversion unary translation, re: #117
33-
- Including cast parentheses in cast index access subject, re: #122
34-
- Removing some redundant parentheses in chained binary operations
35-
- Adding setting to translate all string.Concat() calls as method calls, not concatenation
29+
<PackageReleaseNotes>- Fixing static method access when showing captured values re: #129
30+
- Translating enum comparisons as enum constants
3631
</PackageReleaseNotes>
3732
<PackageReadmeFile>README.md</PackageReadmeFile>
3833
<PackageOutputPath>../../NuGet</PackageOutputPath>

src/ReadableExpressions/Translations/BinaryTranslation.cs

+71-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
namespace AgileObjects.ReadableExpressions.Translations;
22

3+
using System;
34
#if NET35
45
using Microsoft.Scripting.Ast;
5-
using static Microsoft.Scripting.Ast.ExpressionType;
66
#else
77
using System.Linq.Expressions;
8+
#endif
9+
using Extensions;
10+
using NetStandardPolyfills;
11+
#if NET35
12+
using static Microsoft.Scripting.Ast.ExpressionType;
13+
#else
814
using static System.Linq.Expressions.ExpressionType;
915
#endif
1016

@@ -124,17 +130,75 @@ public static INodeTranslation For(
124130

125131
case Equal:
126132
case NotEqual:
127-
if (StandaloneEqualityComparisonTranslation.TryGetTranslation(binary, context, out var translation))
133+
if (BoolEqualityComparisonTranslation.TryGetTranslation(binary, context, out var boolComparison))
128134
{
129-
return translation;
135+
return boolComparison;
130136
}
131137

138+
goto default;
139+
140+
default:
141+
TryGetEnumComparisonExpression(ref binary);
132142
break;
133143
}
134144

135145
return new BinaryTranslation(binary, context);
136146
}
137147

148+
public static void TryGetEnumComparisonExpression(
149+
ref BinaryExpression comparison)
150+
{
151+
var leftOperandIsEnum =
152+
IsEnumType(comparison.Left, out var leftExpression);
153+
154+
var rightOperandIsEnum =
155+
IsEnumType(comparison.Right, out var rightExpression);
156+
157+
if (leftOperandIsEnum || rightOperandIsEnum)
158+
{
159+
var enumType = leftOperandIsEnum
160+
? leftExpression.Type : rightExpression.Type;
161+
162+
comparison = comparison.Update(
163+
GetEnumValue(leftExpression, enumType),
164+
comparison.Conversion,
165+
GetEnumValue(rightExpression, enumType));
166+
}
167+
}
168+
169+
private static bool IsEnumType(
170+
Expression expression,
171+
out Expression enumExpression)
172+
{
173+
if (expression.NodeType.IsCast())
174+
{
175+
expression = expression.GetUnaryOperand();
176+
}
177+
178+
if (expression.Type.GetNonNullableType().IsEnum())
179+
{
180+
enumExpression = expression;
181+
return true;
182+
}
183+
184+
enumExpression = expression;
185+
return false;
186+
}
187+
188+
private static Expression GetEnumValue(
189+
Expression expression,
190+
Type enumType)
191+
{
192+
if (expression.NodeType != Constant)
193+
{
194+
return expression;
195+
}
196+
197+
var value = ((ConstantExpression)expression).Value;
198+
var enumValue = Enum.Parse(enumType, value.ToString());
199+
return Expression.Constant(enumValue, enumType);
200+
}
201+
138202
#endregion
139203

140204
public static bool IsBinary(ExpressionType nodeType)
@@ -173,13 +237,13 @@ public void WriteTo(TranslationWriter writer)
173237
protected override bool IsMultiStatement()
174238
=> _leftOperandTranslation.IsMultiStatement() || _rightOperandTranslation.IsMultiStatement();
175239

176-
private class StandaloneEqualityComparisonTranslation : INodeTranslation
240+
private class BoolEqualityComparisonTranslation : INodeTranslation
177241
{
178242
private readonly ITranslationContext _context;
179243
private readonly StandaloneBoolean _standaloneBoolean;
180244
private readonly INodeTranslation _operandTranslation;
181245

182-
private StandaloneEqualityComparisonTranslation(
246+
private BoolEqualityComparisonTranslation(
183247
ExpressionType nodeType,
184248
Expression boolean,
185249
ExpressionType @operator,
@@ -199,7 +263,7 @@ public static bool TryGetTranslation(
199263
{
200264
if (IsBooleanConstant(comparison.Right))
201265
{
202-
translation = new StandaloneEqualityComparisonTranslation(
266+
translation = new BoolEqualityComparisonTranslation(
203267
comparison.NodeType,
204268
comparison.Left,
205269
comparison.NodeType,
@@ -211,7 +275,7 @@ public static bool TryGetTranslation(
211275

212276
if (IsBooleanConstant(comparison.Left))
213277
{
214-
translation = new StandaloneEqualityComparisonTranslation(
278+
translation = new BoolEqualityComparisonTranslation(
215279
comparison.NodeType,
216280
comparison.Right,
217281
comparison.NodeType,

src/Tests/ReadableExpressions.UnitTests/WhenTranslatingMemberAccesses.cs

+21-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
using Xunit;
1515
using static System.Linq.Expressions.Expression;
1616
#else
17-
using Microsoft.Scripting.Ast;
18-
using Fact = NUnit.Framework.TestAttribute;
19-
using static Microsoft.Scripting.Ast.Expression;
17+
using Microsoft.Scripting.Ast;
18+
using Fact = NUnit.Framework.TestAttribute;
19+
using static Microsoft.Scripting.Ast.Expression;
2020

21-
[NUnit.Framework.TestFixture]
21+
[NUnit.Framework.TestFixture]
2222
#endif
2323
public class WhenTranslatingMemberAccesses : TestClassBase
2424
{
@@ -350,7 +350,7 @@ public void ShouldTranslateMultiParameterCallParamsArrayArgument()
350350

351351
// string.Join(string, string[]) in .NET 3.5 doesn't take a params array:
352352
#if NET35
353-
const string EXPECTED = @"
353+
const string EXPECTED = @"
354354
string.Join(string.Empty, new[] { ""Value["", ""0"", ""]"" })";
355355
#else
356356
const string EXPECTED = @"
@@ -660,6 +660,20 @@ public void ShouldIncludeCapturedStaticPropertyValues()
660660
translated.ShouldBe("helper.PublicInstance == 456");
661661
}
662662

663+
// See https://github.com/agileobjects/ReadableExpressions/issues/129
664+
[Fact]
665+
public void ShouldHandleComplexTypeCollectionAccessWithCapturedValues()
666+
{
667+
var capturedLocalVariableLamda = CreateLambda(
668+
(IEnumerable<PropertiesHelper> helpers) =>
669+
helpers.First().PublicEnumInstance == OddNumber.One);
670+
671+
var translated = capturedLocalVariableLamda.Body
672+
.ToReadableString(stgs => stgs.ShowCapturedValues);
673+
674+
translated.ShouldBe("helpers.First().PublicEnumInstance == OddNumber.One");
675+
}
676+
663677
[Fact]
664678
public void ShouldIncludeOutParameterKeywords()
665679
{
@@ -996,6 +1010,8 @@ internal class PropertiesHelper
9961010

9971011
public int PublicInstance { get; set; }
9981012

1013+
public OddNumber PublicEnumInstance { get; set; }
1014+
9991015
internal static int NonPublicStatic { get; set; }
10001016

10011017
internal int NonPublicInstance { get; set; }
Binary file not shown.

0 commit comments

Comments
 (0)