Skip to content

Commit b37e3de

Browse files
committed
IsExpression
1 parent a580dc6 commit b37e3de

File tree

3 files changed

+73
-32
lines changed

3 files changed

+73
-32
lines changed

ExpressionDebugger.Tests/DebugInfoInjectorTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,5 +674,24 @@ public static int Main()
674674
}"
675675
, str);
676676
}
677+
678+
[TestMethod]
679+
public void TestExpression()
680+
{
681+
Expression<Func<Data, Data>> lambda = data => new Data {Id = data.Id + "1", Records = data.Records.Select(it => it + 1)};
682+
var str = lambda.ToScript(new ExpressionDefinitions {IsExpression = true});
683+
Assert.AreEqual(@"
684+
public Expression<Func<DebugInfoInjectorTest.Data, DebugInfoInjectorTest.Data>> Main = data => new DebugInfoInjectorTest.Data()
685+
{
686+
Id = data.Id + ""1"",
687+
Records = data.Records.Select<int, int>(it => it + 1)
688+
};", str);
689+
}
690+
691+
public class Data
692+
{
693+
public string Id { get; set; }
694+
public IEnumerable<int> Records { get; set; }
695+
}
677696
}
678697
}

ExpressionTranslator/ExpressionDefinitions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ public class ExpressionDefinitions
1010
public bool IsStatic { get; set; }
1111
public string MethodName { get; set; }
1212
public IEnumerable<Type> Implements { get; set; }
13+
public bool IsExpression { get; set; }
1314
}
1415
}

ExpressionTranslator/ExpressionTranslator.cs

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,44 +1117,58 @@ private void WriteModifier(bool isPublic)
11171117

11181118
private Expression VisitLambda(LambdaExpression node, LambdaType type)
11191119
{
1120-
if (type == LambdaType.Function || type == LambdaType.Main)
1121-
{
1122-
var name = type == LambdaType.Main
1123-
? (Definitions?.MethodName ?? "Main")
1124-
: GetName(node);
1125-
WriteModifier(type == LambdaType.Main);
1126-
Write(Translate(node.ReturnType), " ", name);
1127-
var args = VisitArguments("(", node.Parameters, VisitParameterDeclaration, ")");
1128-
Indent();
1129-
var body = VisitBody(node.Body, true);
1130-
1131-
Outdent();
1132-
1133-
return Expression.Lambda(body, name, node.TailCall, args);
1134-
}
1135-
else
1120+
if (type == LambdaType.Inline || this.Definitions?.IsExpression == true)
11361121
{
1122+
if (type == LambdaType.Main)
1123+
{
1124+
var name = Definitions?.MethodName ?? "Main";
1125+
WriteModifier(true);
1126+
var funcType = MakeDelegateType(node.ReturnType, node.Parameters.Select(it => it.Type).ToArray());
1127+
var exprType = typeof(Expression<>).MakeGenericType(funcType);
1128+
Write(Translate(exprType), " ", name, " = ");
1129+
}
11371130
IList<ParameterExpression> args;
11381131
if (node.Parameters.Count == 1)
11391132
{
11401133
args = new List<ParameterExpression>();
11411134
var arg = VisitParameter(node.Parameters[0]);
1142-
args.Add((ParameterExpression)arg);
1135+
args.Add((ParameterExpression) arg);
11431136
}
11441137
else
11451138
{
1146-
args = VisitArguments("(", node.Parameters.ToList(), p => (ParameterExpression)VisitParameter(p), ")");
1139+
args = VisitArguments("(", node.Parameters.ToList(), p => (ParameterExpression) VisitParameter(p),")");
11471140
}
1141+
11481142
Write(" => ");
11491143
var body = VisitGroup(node.Body, ExpressionType.Quote);
1144+
if (type == LambdaType.Main)
1145+
Write(";");
11501146
return Expression.Lambda(body, node.Name, node.TailCall, args);
11511147
}
1148+
else
1149+
{
1150+
var name = type == LambdaType.Main
1151+
? (Definitions?.MethodName ?? "Main")
1152+
: GetName(node);
1153+
WriteModifier(type == LambdaType.Main);
1154+
Write(Translate(node.ReturnType), " ", name);
1155+
var args = VisitArguments("(", node.Parameters, VisitParameterDeclaration, ")");
1156+
Indent();
1157+
var body = VisitBody(node.Body, true);
1158+
1159+
Outdent();
1160+
1161+
return Expression.Lambda(body, name, node.TailCall, args);
1162+
}
11521163
}
11531164

11541165
private HashSet<LambdaExpression> _visitedLambda;
11551166
private int _writerLevel;
11561167
protected override Expression VisitLambda<T>(Expression<T> node)
11571168
{
1169+
if (this.Definitions?.IsExpression == true)
1170+
return VisitLambda(node, LambdaType.Function);
1171+
11581172
Write(GetName(node));
11591173

11601174
if (_visitedLambda == null)
@@ -1282,14 +1296,25 @@ protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBind
12821296
return node.Update(args);
12831297
}
12841298

1285-
private static Type GetDelegateType(MethodInfo method)
1299+
private static Type MakeDelegateType(Type returnType, params Type[] parameters)
12861300
{
1287-
if (method.GetParameters().Any(it => it.IsOut || it.ParameterType.IsByRef))
1288-
throw new InvalidOperationException("Cannot handle non-public method");
1301+
var del = GetDelegateType(returnType != typeof(void), parameters.Length);
1302+
if (del.GetTypeInfo().IsGenericTypeDefinition)
1303+
{
1304+
var types = parameters.AsEnumerable();
1305+
if (returnType != typeof(void))
1306+
types = types.Concat(new[] { returnType });
1307+
del = del.MakeGenericType(types.ToArray());
1308+
}
12891309

1290-
if (method.ReturnType == typeof(void))
1310+
return del;
1311+
}
1312+
1313+
private static Type GetDelegateType(bool isFunc, int argCount)
1314+
{
1315+
if (!isFunc)
12911316
{
1292-
switch (method.GetParameters().Length)
1317+
switch (argCount)
12931318
{
12941319
case 0: return typeof(Action);
12951320
case 1: return typeof(Action<>);
@@ -1313,7 +1338,7 @@ private static Type GetDelegateType(MethodInfo method)
13131338
}
13141339
else
13151340
{
1316-
switch (method.GetParameters().Length)
1341+
switch (argCount)
13171342
{
13181343
case 0: return typeof(Func<>);
13191344
case 1: return typeof(Func<,>);
@@ -1352,14 +1377,10 @@ protected override Expression VisitMethodCall(MethodCallExpression node)
13521377
else if (!node.Method.IsPublic || node.Method.DeclaringType?.GetTypeInfo().IsNotPublic == true)
13531378
{
13541379
isNotPublic = true;
1355-
var del = GetDelegateType(node.Method);
1356-
if (del.GetTypeInfo().IsGenericTypeDefinition)
1357-
{
1358-
var types = node.Method.GetParameters().Select(it => it.ParameterType);
1359-
if (node.Method.ReturnType != typeof(void))
1360-
types = types.Concat(new[] { node.Method.ReturnType });
1361-
del = del.MakeGenericType(types.ToArray());
1362-
}
1380+
if (node.Method.GetParameters().Any(it => it.IsOut || it.ParameterType.IsByRef))
1381+
throw new InvalidOperationException("Cannot handle non-public method");
1382+
1383+
var del = MakeDelegateType(node.Method.ReturnType, node.Method.GetParameters().Select(it => it.ParameterType).ToArray());
13631384
var func = node.Method.CreateDelegate(del);
13641385
Write(GetConstant(func, GetVarName(node.Method.Name)), ".Invoke");
13651386
}

0 commit comments

Comments
 (0)