Skip to content

Commit d34d0fe

Browse files
authored
Re-fix #160 (#255)
+semver:fix
1 parent 83f2057 commit d34d0fe

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

src/DelegateDecompiler.Tests/EnumTests.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void TestEnumPropertyEqualsFooOrElseEnumPropertyEqualsBar()
5959
Test(expected1, expected2, compiled);
6060
}
6161

62-
[Test, Ignore("Not fixed yet")]
62+
[Test]
6363
public void TestEnumPropertyIsFooOrBar()
6464
{
6565
Expression<Func<TestEnum, bool>> expected = x => (int)x <= 1;
@@ -311,11 +311,11 @@ public void Issue98B()
311311
Test(expected, compiled);
312312
}
313313

314-
[Test, Ignore("Not fixed yet")]
314+
[Test]
315315
public void Issue160()
316316
{
317317
Expression<Func<int?, bool>> expected1 = x => (TestEnum?)x == TestEnum.Bar;
318-
Expression<Func<int?, bool>> expected2 = x => (x.HasValue ? (TestEnum?)(x ?? 0) : null) == TestEnum.Bar;
318+
Expression<Func<int?, bool>> expected2 = x => (int)((TestEnum?)x ?? TestEnum.Foo) == 1;
319319
Func<int?, bool> compiled = x => (TestEnum?)x == TestEnum.Bar;
320320
Test(expected1, expected2, compiled);
321321
}

src/DelegateDecompiler/OptimizeExpressionVisitor.cs

+24-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ protected override Expression VisitNew(NewExpression node)
1414
{
1515
return Expression.Convert(Visit(node.Arguments[0]), node.Type);
1616
}
17+
1718
return base.VisitNew(node);
1819
}
1920

@@ -45,10 +46,21 @@ protected override Expression VisitConditional(ConditionalExpression node)
4546
return boolValue ? ifTrue : ifFalse;
4647
}
4748

48-
if (IsCoalesce(test, ifTrue, out var expression))
49+
if (IsCoalesce(test, UnwrapConvertToNullable(ifTrue), out var expression))
4950
{
51+
if (IsNullConstant(ifFalse))
52+
{
53+
if (expression.Type != node.Type)
54+
{
55+
expression = Expression.Convert(expression, node.Type);
56+
}
57+
58+
return expression;
59+
}
60+
5061
return Expression.Coalesce(expression, ifFalse);
5162
}
63+
5264
var ifTrueBinary = UnwrapConvertToNullable(ifTrue) as BinaryExpression;
5365
if (ifTrueBinary != null)
5466
{
@@ -112,6 +124,11 @@ protected override Expression VisitConditional(ConditionalExpression node)
112124
return node.Update(test, ifTrue, ifFalse);
113125
}
114126

127+
static bool IsNullConstant(Expression expression)
128+
{
129+
return expression is ConstantExpression constant && constant.Value == null;
130+
}
131+
115132
private static bool TryConvert(ConstantExpression constant, BinaryExpression left, Expression right, out BinaryExpression result, bool isLeft)
116133
{
117134
if (constant?.Value is bool booleanValue)
@@ -237,11 +254,13 @@ static Expression ConvertToNullable(Expression expression)
237254

238255
static Expression UnwrapConvertToNullable(Expression expression)
239256
{
240-
var unary = expression as UnaryExpression;
241-
if (unary != null && expression.NodeType == ExpressionType.Convert && expression.Type.IsNullableType())
257+
if (expression is UnaryExpression unary &&
258+
expression.NodeType == ExpressionType.Convert &&
259+
expression.Type.IsNullableType())
242260
{
243261
return unary.Operand;
244262
}
263+
245264
return expression;
246265
}
247266

@@ -261,9 +280,8 @@ static bool ExtractNullableArgument(Expression hasValue, Expression getValueOrDe
261280

262281
static bool IsCoalesce(Expression hasValue, Expression getValueOrDefault, out Expression expression)
263282
{
264-
MemberExpression memberExpression;
265-
MethodCallExpression callExpression;
266-
if (IsHasValue(hasValue, out memberExpression) && IsGetValueOrDefault(getValueOrDefault, out callExpression))
283+
if (IsHasValue(hasValue, out var memberExpression) &&
284+
IsGetValueOrDefault(getValueOrDefault, out var callExpression))
267285
{
268286
expression = memberExpression.Expression;
269287
if (expression == callExpression.Object)

src/DelegateDecompiler/Processor.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ Expression Process()
397397
state.Instruction.OpCode == OpCodes.Bgt_Un_S)
398398
{
399399
var val1 = state.Stack.Pop();
400-
state.Instruction = ConditionalBranch(state, val => Expression.GreaterThan(val, val1));
400+
state.Instruction = ConditionalBranch(state, val => MakeBinaryExpression(val, val1, ExpressionType.GreaterThan));
401401
continue;
402402
}
403403
else if (state.Instruction.OpCode == OpCodes.Bge ||
@@ -406,7 +406,7 @@ Expression Process()
406406
state.Instruction.OpCode == OpCodes.Bge_Un_S)
407407
{
408408
var val1 = state.Stack.Pop();
409-
state.Instruction = ConditionalBranch(state, val => Expression.GreaterThanOrEqual(val, val1));
409+
state.Instruction = ConditionalBranch(state, val => MakeBinaryExpression(val, val1, ExpressionType.GreaterThanOrEqual));
410410
continue;
411411
}
412412
else if (state.Instruction.OpCode == OpCodes.Blt ||
@@ -415,7 +415,7 @@ Expression Process()
415415
state.Instruction.OpCode == OpCodes.Blt_Un_S)
416416
{
417417
var val1 = state.Stack.Pop();
418-
state.Instruction = ConditionalBranch(state, val => Expression.LessThan(val, val1));
418+
state.Instruction = ConditionalBranch(state, val => MakeBinaryExpression(val, val1, ExpressionType.LessThan));
419419
continue;
420420
}
421421
else if (state.Instruction.OpCode == OpCodes.Ble ||

0 commit comments

Comments
 (0)