|
1 | 1 | using System; |
2 | 2 | using System.Collections.Generic; |
| 3 | +using System.Diagnostics; |
3 | 4 | #if !NETSTANDARD1_3 |
4 | 5 | using System.Dynamic; |
5 | 6 | #endif |
|
12 | 13 |
|
13 | 14 | namespace ExpressionDebugger |
14 | 15 | { |
15 | | - internal class DebugInfoInjector : ExpressionVisitor, IDisposable |
| 16 | + public class DebugInfoInjector : ExpressionVisitor, IDisposable |
16 | 17 | { |
17 | 18 | private const int Tabsize = 4; |
18 | 19 | private readonly SymbolDocumentInfo _document; |
@@ -373,6 +374,7 @@ protected override Expression VisitBinary(BinaryExpression node) |
373 | 374 | Write(" ", Translate(node.NodeType), " "); |
374 | 375 | right = VisitGroup(node.Right, node.NodeType, true); |
375 | 376 | } |
| 377 | + |
376 | 378 | return node.Update(left, node.Conversion, right); |
377 | 379 | } |
378 | 380 |
|
@@ -543,11 +545,12 @@ IEnumerable<Expression> VisitBlockBody(IList<Expression> exprs, bool shouldRetur |
543 | 545 |
|
544 | 546 | Expression VisitBlock(BlockExpression node, bool shouldReturn) |
545 | 547 | { |
546 | | - var assignedVariables = new HashSet<ParameterExpression>(node.Expressions |
| 548 | + var assignedVariables = node.Expressions |
547 | 549 | .Where(exp => exp.NodeType == ExpressionType.Assign) |
548 | 550 | .Select(exp => ((BinaryExpression)exp).Left) |
549 | 551 | .Where(exp => exp.NodeType == ExpressionType.Parameter) |
550 | | - .Select(exp => (ParameterExpression)exp)); |
| 552 | + .Select(exp => (ParameterExpression)exp) |
| 553 | + .ToHashSet(); |
551 | 554 |
|
552 | 555 | var list = new List<ParameterExpression>(); |
553 | 556 | var hasDeclaration = false; |
@@ -681,48 +684,7 @@ protected override Expression VisitConstant(ConstantExpression node) |
681 | 684 | Write("valueof(", Translate(type), ")"); |
682 | 685 | } |
683 | 686 |
|
684 | | - if (_document == null || CanEmitConstant(value, node.Type)) |
685 | | - return node; |
686 | | - |
687 | | - var i = GlobalReference.GetIndex(value); |
688 | | - return Expression.Convert( |
689 | | - Expression.Call( |
690 | | - typeof(GlobalReference).GetMethod(nameof(GlobalReference.GetObject)), |
691 | | - Expression.Constant(i)), |
692 | | - node.Type); |
693 | | - } |
694 | | - |
695 | | - private static bool CanEmitConstant(object value, Type type) |
696 | | - { |
697 | | - if (value == null |
698 | | - || type.GetTypeInfo().IsPrimitive |
699 | | - || type == typeof(string) |
700 | | - || type == typeof(decimal)) |
701 | | - return true; |
702 | | - |
703 | | - if (value is Type t) |
704 | | - return ShouldLdtoken(t); |
705 | | - |
706 | | - if (value is MethodBase mb) |
707 | | - return ShouldLdtoken(mb); |
708 | | - |
709 | | - return false; |
710 | | - } |
711 | | - |
712 | | - private static bool ShouldLdtoken(Type t) |
713 | | - { |
714 | | - return t is TypeBuilder |
715 | | - || t.IsGenericParameter |
716 | | - || t.IsVisible; |
717 | | - } |
718 | | - |
719 | | - private static bool ShouldLdtoken(MethodBase mb) |
720 | | - { |
721 | | - if (mb is DynamicMethod) |
722 | | - return false; |
723 | | - |
724 | | - Type dt = mb.DeclaringType; |
725 | | - return dt == null || ShouldLdtoken(dt); |
| 687 | + return node; |
726 | 688 | } |
727 | 689 |
|
728 | 690 | protected override Expression VisitDefault(DefaultExpression node) |
@@ -951,6 +913,8 @@ protected override Expression VisitIndex(IndexExpression node) |
951 | 913 | : VisitGroup(node.Object, node.NodeType); |
952 | 914 |
|
953 | 915 | var args = VisitArguments("[", node.Arguments, Visit, "]"); |
| 916 | + |
| 917 | + //TODO: |
954 | 918 | return node.Update(obj, args); |
955 | 919 | } |
956 | 920 |
|
@@ -1480,6 +1444,36 @@ protected override Expression VisitUnary(UnaryExpression node) |
1480 | 1444 | return node.Update(operand); |
1481 | 1445 | } |
1482 | 1446 |
|
| 1447 | + public Delegate Compile(LambdaExpression node) |
| 1448 | + { |
| 1449 | +#if NETSTANDARD1_3 |
| 1450 | + return node.Compile(); |
| 1451 | +#else |
| 1452 | + |
| 1453 | + var assemblyName = "m_" + Guid.NewGuid().ToString("N"); |
| 1454 | + var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.Run); |
| 1455 | + |
| 1456 | + var daType = typeof(DebuggableAttribute); |
| 1457 | + var daCtor = daType.GetConstructor(new[] { typeof(DebuggableAttribute.DebuggingModes) }); |
| 1458 | + var daBuilder = new CustomAttributeBuilder(daCtor, new object[] { |
| 1459 | + DebuggableAttribute.DebuggingModes.DisableOptimizations | |
| 1460 | + DebuggableAttribute.DebuggingModes.Default }); |
| 1461 | + asm.SetCustomAttribute(daBuilder); |
| 1462 | + |
| 1463 | + var mod = asm.DefineDynamicModule(assemblyName, true); |
| 1464 | + var type = mod.DefineType("Program", TypeAttributes.Public | TypeAttributes.Class); |
| 1465 | + var meth = type.DefineMethod("Main", MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.Static); |
| 1466 | + |
| 1467 | + var injected = (LambdaExpression)Inject(node); |
| 1468 | + var gen = DebugInfoGenerator.CreatePdbGenerator(); |
| 1469 | + injected.CompileToMethod(meth, gen); |
| 1470 | + |
| 1471 | + var newtype = type.CreateType(); |
| 1472 | + |
| 1473 | + return Delegate.CreateDelegate(node.Type, newtype.GetMethod("Main")); |
| 1474 | +#endif |
| 1475 | + } |
| 1476 | + |
1483 | 1477 | enum LambdaType |
1484 | 1478 | { |
1485 | 1479 | Main, |
|
0 commit comments