diff --git a/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs new file mode 100644 index 00000000..1d924bb6 --- /dev/null +++ b/src/DelegateDecompiler.Tests/NestedExpressionsTests.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; + +namespace DelegateDecompiler.Tests +{ + public class NestedExpressionsTests : DecompilerTestsBase + { + readonly int f1 = 0; + static readonly int f2 = 0; + int p1 => 0; + static int p2 => 0; + int M1() => 0; + static int M2() => 0; + + [Test] + public void TestNestedExpression() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == 0), + ints => ints.SingleOrDefault(i => i == 0) + ); + } + + [Test, Ignore("Not supported yet")] + public void TestExpressionWithClosure() + { + var v = 0; + Test, int>>( + ints => ints.SingleOrDefault(i => i == v), + ints => ints.SingleOrDefault(i => i == v) + ); + } + + [Test, Ignore("Not supported yet")] + public void TestExpressionWithFieldClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == f1), + ints => ints.SingleOrDefault(i => i == f1) + ); + } + + [Test] + public void TestExpressionWithStaticFieldClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == f2), + ints => ints.SingleOrDefault(i => i == f2) + ); + } + + [Test, Ignore("Not supported yet")] + public void TestExpressionWithPropertyClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == p1), + ints => ints.SingleOrDefault(i => i == p1) + ); + } + + [Test] + public void TestExpressionWithStaticPropertyClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == p2), + ints => ints.SingleOrDefault(i => i == p2) + ); + } + + [Test, Ignore("Not supported yet")] + public void TestExpressionWithMethodClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == M1()), + ints => ints.SingleOrDefault(i => i == M1()) + ); + } + + [Test] + public void TestExpressionWithStaticMethodClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == M2()), + ints => ints.SingleOrDefault(i => i == M2()) + ); + } + + [Test] + public void TestNestedFunc() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == 0), + ints => ints.SingleOrDefault(i => i == 0) + ); + } + + [Test] + public void TestFuncWithClosure() + { + var v = 0; + Test, int>>( + ints => ints.SingleOrDefault(i => i == v), + ints => ints.SingleOrDefault(i => i == v) + ); + } + + [Test] + public void TestFuncWithFieldClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == f1), + ints => ints.SingleOrDefault(i => i == f1) + ); + } + + [Test] + public void TestFuncWithStaticFieldClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == f2), + ints => ints.SingleOrDefault(i => i == f2) + ); + } + + [Test] + public void TestFuncWithPropertyClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == p1), + ints => ints.SingleOrDefault(i => i == p1) + ); + } + + [Test] + public void TestFuncWithStaticPropertyClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == p2), + ints => ints.SingleOrDefault(i => i == p2) + ); + } + + [Test] + public void TestFuncWithMethodClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == M1()), + ints => ints.SingleOrDefault(i => i == M1()) + ); + } + + [Test] + public void TestFuncWithStaticMethodClosure() + { + Test, int>>( + ints => ints.SingleOrDefault(i => i == M2()), + ints => ints.SingleOrDefault(i => i == M2()) + ); + } + } +} diff --git a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs index 7ce0434a..11fc3222 100644 --- a/src/DelegateDecompiler/OptimizeExpressionVisitor.cs +++ b/src/DelegateDecompiler/OptimizeExpressionVisitor.cs @@ -334,6 +334,23 @@ node.Operand is BinaryExpression binary && return base.VisitUnary(node); } + protected override Expression VisitMethodCall(MethodCallExpression node) + { + if (node.Method.DeclaringType == typeof(Expression)) + { + // Execute nested lambda expression methods + var fun = Expression.Lambda>(node).Compile(); + var value = fun(); + if (value is LambdaExpression expression) + { + return Expression.Quote(expression); + } + + return Expression.Constant(value); + } + + return base.VisitMethodCall(node); + } static bool Invert(ref BinaryExpression expression) {