Skip to content

Commit 8067958

Browse files
author
chaowlert
committed
support else if
1 parent 83d1f3a commit 8067958

File tree

5 files changed

+76
-23
lines changed

5 files changed

+76
-23
lines changed

ConsoleApp1/Program.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ static void Main(string[] args)
1212
var p2 = Expression.Parameter(typeof(int));
1313
var body = Expression.Add(p1, p2);
1414
var lambda = Expression.Lambda<Func<int, int, int>>(body, p1, p2);
15-
var filename = "test.cs";
16-
var fun = lambda.Compile(filename);
15+
var fun = lambda.CompileWithDebugInfo();
1716
var result = fun(1, 2);
1817
Console.WriteLine(3);
1918
}

ExpressionDebugger.Test/DebugInfoInjectorTest.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,35 @@ public void TestConditional_Block()
8383
, str);
8484
}
8585

86+
[TestMethod]
87+
public void TestConditional_Block_Chain()
88+
{
89+
var exp = Expression.Condition(
90+
Expression.Equal(Expression.Constant(1), Expression.Constant(2)),
91+
Expression.Constant(4),
92+
Expression.Condition(
93+
Expression.Equal(Expression.Constant(5), Expression.Constant(6)),
94+
Expression.Constant(3),
95+
Expression.Constant(2),
96+
typeof(void)),
97+
typeof(void));
98+
var str = exp.ToScript();
99+
Assert.AreEqual(@"
100+
if (1 == 2)
101+
{
102+
4;
103+
}
104+
else if (5 == 6)
105+
{
106+
3;
107+
}
108+
else
109+
{
110+
2;
111+
}"
112+
, str);
113+
}
114+
86115
[TestMethod]
87116
public void TestConstant()
88117
{

ExpressionDebugger/DebugInfoInjector.cs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -590,38 +590,50 @@ protected override CatchBlock VisitCatchBlock(CatchBlock node)
590590

591591
Expression VisitConditional(ConditionalExpression node, bool shouldReturn)
592592
{
593-
Expression test, ifTrue, ifFalse;
594593
if (IsInline(node))
595594
{
596-
test = VisitGroup(node.Test, node.NodeType);
595+
Expression test = VisitGroup(node.Test, node.NodeType);
597596
Write(" ? ");
598-
ifTrue = VisitGroup(node.IfTrue, node.NodeType);
597+
Expression ifTrue = VisitGroup(node.IfTrue, node.NodeType);
599598
Write(" : ");
600-
ifFalse = VisitGroup(node.IfFalse, node.NodeType);
599+
Expression ifFalse = VisitGroup(node.IfFalse, node.NodeType);
601600
return node.Update(test, ifTrue, ifFalse);
602601
}
603602
else
604603
{
604+
return VisitConditionalBlock(node, shouldReturn);
605+
}
606+
}
607+
608+
Expression VisitConditionalBlock(ConditionalExpression node, bool shouldReturn, bool chain = false)
609+
{
610+
if (chain)
611+
WriteNextLine("else if (");
612+
else
605613
WriteNextLine("if (");
606-
var position = GetPosition();
607-
test = Visit(node.Test);
608-
var debug = CreateDebugInfo(position);
609-
Write(")");
610-
Indent();
611-
ifTrue = VisitBody(node.IfTrue, shouldReturn);
612-
Outdent();
613-
ifFalse = node.IfFalse;
614-
if (node.Type == typeof(void) && node.IfFalse.NodeType != ExpressionType.Default)
614+
var position = GetPosition();
615+
Expression test = Visit(node.Test);
616+
var debug = CreateDebugInfo(position);
617+
Write(")");
618+
Indent();
619+
Expression ifTrue = VisitBody(node.IfTrue, shouldReturn);
620+
Outdent();
621+
Expression ifFalse = node.IfFalse;
622+
if (node.Type == typeof(void) && node.IfFalse.NodeType != ExpressionType.Default)
623+
{
624+
if (node.IfFalse.NodeType == ExpressionType.Conditional)
625+
ifFalse = VisitConditionalBlock((ConditionalExpression)node.IfFalse, shouldReturn, true);
626+
else
615627
{
616628
WriteNextLine("else");
617629
Indent();
618630
ifFalse = VisitBody(node.IfFalse, shouldReturn);
619631
Outdent();
620632
}
621-
return Expression.Block(
622-
debug,
623-
Expression.Condition(test, ifTrue, ifFalse));
624633
}
634+
return Expression.Block(
635+
debug,
636+
Expression.Condition(test, ifTrue, ifFalse));
625637
}
626638

627639
protected override Expression VisitConditional(ConditionalExpression node)

ExpressionDebugger/ExpressionDebugger.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFrameworks>net40;net45;netstandard1.3</TargetFrameworks>
55
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
66
<Authors>Chaowlert Chaisrichalermpol</Authors>
7-
<Description>Step through debugging and generate readable script from linq expressions</Description>
7+
<Description>Step into debugging and generate readable script from linq expressions</Description>
88
<PackageProjectUrl>https://github.com/chaowlert/ExpressionDebugger</PackageProjectUrl>
99
<RepositoryUrl>https://github.com/chaowlert/ExpressionDebugger</RepositoryUrl>
1010
<PackageTags>expression;linq;debug</PackageTags>

ExpressionDebugger/ExpressionExtensions.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,40 @@
1-
using System;
1+
using ExpressionDebugger;
22
using System.Diagnostics;
33
using System.IO;
4-
using System.Linq.Expressions;
54
using System.Reflection;
65
using System.Reflection.Emit;
76
using System.Runtime.CompilerServices;
87

9-
namespace ExpressionDebugger
8+
namespace System.Linq.Expressions
109
{
1110
public static class ExpressionExtensions
1211
{
12+
/// <summary>
13+
/// Generate script text
14+
/// </summary>
15+
/// <param name="node">Expression</param>
16+
/// <returns>Script text</returns>
1317
public static string ToScript(this Expression node)
1418
{
1519
var writer = new StringWriter();
1620
new DebugInfoInjector(writer).Inject(node);
1721
return writer.ToString();
1822
}
1923

20-
public static T Compile<T>(this Expression<T> node, string filename)
24+
/// <summary>
25+
/// Compile with debugging info injected
26+
/// </summary>
27+
/// <typeparam name="T">Type of lambda expression</typeparam>
28+
/// <param name="node">Lambda expression</param>
29+
/// <param name="filename">Filename to inject source code. if omit, temp filename will be used</param>
30+
/// <returns>Generated method</returns>
31+
public static T CompileWithDebugInfo<T>(this Expression<T> node, string filename = null)
2132
{
2233
#if NETSTANDARD1_3
2334
return node.Compile();
2435
#else
36+
if (filename == null)
37+
filename = Path.GetTempFileName();
2538
var name = "m_" + Guid.NewGuid().ToString("N");
2639
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(name), AssemblyBuilderAccess.Run);
2740

0 commit comments

Comments
 (0)