Coder Social home page Coder Social logo

agileobjects / readableexpressions Goto Github PK

View Code? Open in Web Editor NEW
392.0 12.0 21.0 33.37 MB

A library and Debugger Visualizer which translates Expression Trees into readable C# source code. .NET 3.5+ and .NET Standard 1.0+.

License: MIT License

C# 99.98% Visual Basic .NET 0.02%
expression-tree debugger-visualizers expression-parser expressions

readableexpressions's People

Contributors

danmannmann avatar stanleygoldman avatar stevewilkes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

readableexpressions's Issues

.NET Core Support

VS 2019 Preview 1 added custom visualizer support for .NET Core apps, but trying to use ReadableExpressions in one results in the following error:

Unable to load the custom visualizer.

Additional informaiton:
The debuggee-side visualizer assembly 'AgileObjects.ReadableExpressions.Visualizers.Vs16, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null' was not found at path 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\Common7\Packages\Debugger\Visualizers\netstandard2.0'.

Learn more about managed custom visualizers

Copying the assembly to the path mentioned in the error fixes the problem.

MSI Installer Issues

I'm encountering the same behavior as reported here. However, I'm not using .NET Core; I'm using .NET Framework v4.7.1.

I previously reported this in the MarketPlace Q&A, but I think I've figured out what might be happening.

Based on the attached log, it seems that installation succeeded. It appears I've been laboring under the mistaken impression that it didn't, because the installer didn't pause to indicate success. Most MSIs doβ€”in fact, this is the first one I've encountered in all these years that doesn't.

I do now have the assembly "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Packages\Debugger\Visualizers\AgileObjects.ReadableExpressions.Visualizers.Vs15.dll" as indicated. I haven't tried to use it yet, as I don't have any code handy for which I need it (I'm trying this out for potential future use).

Anyway... with this now it seems all is well.

Can you confirm that my experience aligns with the expected behavior of the MSI?


MSI6dec4.LOG

Visualizer window does not scroll horizontally

The visualizer window only scrolls vertically, so if a translated expression is 'wide' the vertical scrollbar is pushed beyond the right-hand boundary of the window and is inaccessible.

Installation failure v2.1.2

The 2.1.2 installer which is what is downloaded from the VS Marketplace appears to detect VS 2013 (12.0) on a system where it is not fully installed. My guess is some bits of the 12.0 system, but not the entire visual studio, is laid down as part of another product. I only have two subdirectories of C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7, and those are IDE and Tools. The MSI installation log is as follows:

Calling custom action ReadableExpressions.Visualizers.Installer.Custom!AgileObjects.ReadableExpressions.Visualizers.Installer.Custom.VisualizerInstallationActions.Install
Starting...
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Packages\Debugger\Visualizers'.

The 2.1.1 installer does install successfully, and it reports the visualizers were installed for 10.0, 12.0, and 16.0. I actually do have VS 10.0 and 16.0 installed.

It's not often I need to use your visualizer, but, it is powerful - thanks for the project and let me know if I can be more helpful in troubleshooting this issue.

no issue

no issue here, just wanted to give a big thanks to this project. its working great.

Performance when opening and closing preview window.

So, i have to mention that.
When opening preview window, it takes a seconds to open. Then after closing it - VS hangs for the same time. As result i prefer to quickly review string line instead of invoking more readable view.
Any ideas why?

System.NotSupportedException in the newest Visual Studio

Hi there! Extremely useful extension!
I've been using it for quite a while now, but after I reinstalled Visual Studio 2019 (I'm on version 16.8.1 right now), whenever I click on the magnifier button, I get the following error window:
image

I was going to try uninstalling and then installing the extension again, but the "Uninstall" button is grayed out:
image

I'd appreciate any help.

NetFramework xUnit test error

System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.
   at System.Windows.Forms.UnsafeNativeMethods.IWebBrowser2.get_RegisterAsDropTarget()
   at System.Windows.Forms.WebBrowser.set_AllowWebBrowserDrop(Boolean value)
   at AgileObjects.ReadableExpressions.Visualizers.Core.VisualizerDialog.OnShown(EventArgs e)
   at System.Windows.Forms.Form.CallShownEvent()
   at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
   at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
   at System.Windows.Forms.Control.InvokeMarshaledCallbacks()

Fixed by restarting VS :)

Moving window issue

Version 3.1.0

Visualize any expression, and move window up by mouse, release, move again.
You can examine preview window expanding.

Unnamed variable should use generated name

Expression:

.Lambda #Lambda1<System.Action`2[System.Object,System.Object]>(
    System.Object $obj,
    System.Object $value) {
    .Block(System.Int32 $var1) {
        $var1 = 0
    }
}

Expected:

// generate unique name for variable, e.g. $varN
(obj, value) => var $var1 = 0

Actual:

(obj, value) => var  = 0

Increment and Decrement expressions are disassembled incorrectly

The Increment and Decrement expression types are diassembled like pre-increment/pre-decrement operators, but these operators are really only the equivalent of operand + 1 and operand - 1.

This expression:

var x =
    Expression.Variable(typeof(byte), "x");
        Expression.Assign(
            x,
            Expression.Convert(
	        Expression.Increment(
	            Expression.Convert(x, typeof(int))
	        ),
	    typeof(byte)
        )
    )
    .ToReadableString()
    .Dump();

outputs x = (byte)++(int)x, when x = (byte)((int) + 1) is the correct interpretation.

In idiomatic C#, this is x += 1 for a variable of type byte.

Incorrect operation priority for ternary operation

Sorry for too much code, as it is a part of big testcase.

required types

interface IQueryRunner
        {
            IDataContext DataContext { get; }
            Expression Expression { get; }
            object[] Parameters { get; }
        }

        interface IDataContext
        {
        }

        interface IDataReader
        {
        }

        class DataContext : IDataContext
        {
        }

        class QueryRunner : IQueryRunner
        {
            IDataContext IQueryRunner.DataContext => new DataContext();

            Expression IQueryRunner.Expression => Expression.Constant(null);

            object[] IQueryRunner.Parameters => Array.Empty<object>();
        }

        class SQLiteDataReader : IDataReader
        {
            public bool IsDBNull(int idx)
            {
                return default;
            }

            public int GetInt32(int idx)
            {
                return default;
            }

            public Guid GetGuid(int idx)
            {
                return default;
            }
        }

        class InheritanceTests
        {
            public enum TypeCodeEnum
            {
                Base,
                A,
                A1,
                A2,
            }

            public abstract class InheritanceBase
            {
                public Guid GuidValue { get; set; }

                public virtual TypeCodeEnum TypeCode
                {
                    get { return TypeCodeEnum.Base; }
                }
            }

            public abstract class InheritanceA : InheritanceBase
            {
                public List<InheritanceB> Bs { get; set; }

                public override TypeCodeEnum TypeCode
                {
                    get { return TypeCodeEnum.A; }
                }
            }

            public class InheritanceB : InheritanceBase
            {
            }

            public class InheritanceA2 : InheritanceA
            {
                public override TypeCodeEnum TypeCode
                {
                    get { return TypeCodeEnum.A2; }
                }
            }

            public class InheritanceA1 : InheritanceA
            {
                public override TypeCodeEnum TypeCode
                {
                    get { return TypeCodeEnum.A1; }
                }
            }
        }

        class TableBuilder
        {
            public class TableContext
            {
                public static object OnEntityCreated(IDataContext context, object entity)
                {
                    return entity;
                }
            }
        }

        public enum Test
        {
            One,
            Two
        }

Expression:

var a1 = Expression.Parameter(typeof(IQueryRunner), "qr");
            var a2 = Expression.Parameter(typeof(IDataContext), "dctx");
            var a3 = Expression.Parameter(typeof(IDataReader), "rd");
            var a4 = Expression.Parameter(typeof(Expression), "expr");
            var a5 = Expression.Parameter(typeof(object[]), "ps");

            var ldr = Expression.Variable(typeof(SQLiteDataReader), "ldr");
            var mapperBody = Expression.Block(
                new[] { ldr },
                Expression.Assign(ldr, Expression.Convert(a3, typeof(SQLiteDataReader)) ),
                Expression.Condition(
                    Expression.Equal(
                        Expression.Condition(
                            Expression.Call(ldr, nameof(SQLiteDataReader.IsDBNull), null, Expression.Constant(0)),
                            Expression.Constant(InheritanceTests.TypeCodeEnum.Base),
                            Expression.Convert(
                                Expression.Call(ldr, nameof(SQLiteDataReader.GetInt32), null, Expression.Constant(0)),
                                typeof(InheritanceTests.TypeCodeEnum))),
                        Expression.Constant(InheritanceTests.TypeCodeEnum.A1)),
                    Expression.Convert(
                        Expression.Convert(
                            Expression.Call(
                                typeof(TableBuilder.TableContext).GetMethod(nameof(TableBuilder.TableContext.OnEntityCreated)),
                                a2,
                                Expression.MemberInit(
                                    Expression.New(typeof(InheritanceTests.InheritanceA1)),
                                    Expression.Bind(
                                        typeof(InheritanceTests.InheritanceA1).GetProperty("GuidValue"),
                                        Expression.Condition(
                                            Expression.Call(ldr, nameof(SQLiteDataReader.IsDBNull), null, Expression.Constant(1)),
                                            Expression.Constant(Guid.Empty),
                                            Expression.Call(ldr, nameof(SQLiteDataReader.GetGuid), null, Expression.Constant(1))))
                                    )
                                ),
                            typeof(InheritanceTests.InheritanceA1)),
                        typeof(InheritanceTests.InheritanceA)),
                    Expression.Convert(
                        Expression.Convert(
                            Expression.Call(
                                typeof(TableBuilder.TableContext).GetMethod(nameof(TableBuilder.TableContext.OnEntityCreated)),
                                a2,
                                Expression.MemberInit(
                                    Expression.New(typeof(InheritanceTests.InheritanceA2)),
                                    Expression.Bind(
                                        typeof(InheritanceTests.InheritanceA2).GetProperty("GuidValue"),
                                        Expression.Condition(
                                            Expression.Call(ldr, nameof(SQLiteDataReader.IsDBNull), null, Expression.Constant(1)),
                                            Expression.Constant(Guid.Empty),
                                            Expression.Call(ldr, nameof(SQLiteDataReader.GetGuid), null, Expression.Constant(1))))
                                    )
                                ),
                            typeof(InheritanceTests.InheritanceA2)),
                        typeof(InheritanceTests.InheritanceA))));

            var mapper = Expression.Lambda<Func<IQueryRunner, IDataContext, IDataReader, Expression, object[], InheritanceTests.InheritanceA>>(mapperBody, a1, a2, a3, a4, a5);

            var p1 = Expression.Parameter(typeof(IQueryRunner), "qr");
            var p2 = Expression.Parameter(typeof(IDataReader), "dr");


            var body = Expression.Invoke(
                mapper,
                p1,
                Expression.Property(p1, nameof(IQueryRunner.DataContext)),
                p2,
                Expression.Property(p1, nameof(IQueryRunner.Expression)),
                Expression.Property(p1, nameof(IQueryRunner.Parameters)));

            var lambda = Expression.Lambda<Func<IQueryRunner, IDataReader, InheritanceTests.InheritanceA>>(body, p1, p2);

Expected:

(qr, dr) => ((
    qr,
    dctx,
    rd,
    expr,
    ps) =>
{
    var ldr = (Issue83_linq2db.SQLiteDataReader)rd;

    return (ldr.IsDBNull(0)
        ? Issue83_linq2db.InheritanceTests.TypeCodeEnum.Base
        : (Issue83_linq2db.InheritanceTests.TypeCodeEnum)ldr.GetInt32(0)) == Issue83_linq2db.InheritanceTests.TypeCodeEnum.A1
        ? (Issue83_linq2db.InheritanceTests.InheritanceA)((Issue83_linq2db.InheritanceTests.InheritanceA1)Issue83_linq2db.TableBuilder.TableContext.OnEntityCreated(
            dctx,
            new Issue83_linq2db.InheritanceTests.InheritanceA1
            {
                GuidValue = ldr.IsDBNull(1) ? default(Guid) : ldr.GetGuid(1)
            }))
        : (Issue83_linq2db.InheritanceTests.InheritanceA)((Issue83_linq2db.InheritanceTests.InheritanceA2)Issue83_linq2db.TableBuilder.TableContext.OnEntityCreated(
            dctx,
            new Issue83_linq2db.InheritanceTests.InheritanceA2
            {
                GuidValue = ldr.IsDBNull(1) ? default(Guid) : ldr.GetGuid(1)
            }));
}).Invoke(
    qr,
    qr.DataContext,
    dr,
    qr.Expression,
    qr.Parameters)

Actual:

(qr, dr) => ((
    qr,
    dctx,
    rd,
    expr,
    ps) =>
{
    var ldr = (Issue83_linq2db.SQLiteDataReader)rd;

// Error is here:
//  "== Issue83_linq2db.InheritanceTests.TypeCodeEnum.A1" should be applied to ternary operation, not to false value
    return (ldr.IsDBNull(0)
        ? Issue83_linq2db.InheritanceTests.TypeCodeEnum.Base
        : (Issue83_linq2db.InheritanceTests.TypeCodeEnum)ldr.GetInt32(0) == Issue83_linq2db.InheritanceTests.TypeCodeEnum.A1)
        ? (Issue83_linq2db.InheritanceTests.InheritanceA)((Issue83_linq2db.InheritanceTests.InheritanceA1)Issue83_linq2db.TableBuilder.TableContext.OnEntityCreated(
            dctx,
            new Issue83_linq2db.InheritanceTests.InheritanceA1
            {
                GuidValue = ldr.IsDBNull(1) ? default(Guid) : ldr.GetGuid(1)
            }))
        : (Issue83_linq2db.InheritanceTests.InheritanceA)((Issue83_linq2db.InheritanceTests.InheritanceA2)Issue83_linq2db.TableBuilder.TableContext.OnEntityCreated(
            dctx,
            new Issue83_linq2db.InheritanceTests.InheritanceA2
            {
                GuidValue = ldr.IsDBNull(1) ? default(Guid) : ldr.GetGuid(1)
            }));
}).Invoke(
    qr,
    qr.DataContext,
    dr,
    qr.Expression,
    qr.Parameters)

VS2019 2.4.0 Update issues.

Hi, just tried to update to 2.4.0. Without success.
Uninstalling and then installing again shows that i have installed version 2.3.2 - why?
Manage Extensions window shows that i have update from 2.3.2 to 2.4.0.

Maybe there are some ways to cleanup registry or some folders to force installing correct version?
Visualizing types is not working as expected.

MSI file shows that it was created yesterday. But maybe with old content.

VS Professional 2019, Version 16.1.5

VS 2015 Update 2

Was this tested with the latest VS 2015? Because I see a NullReferenceException.

Brackets are removed when using a ternary operator

I found that important brackets are removed when using a ternary operator.

bool someCondition = true;
string trueValue = "hello";
string falseValue = "goodbye";
string someValue = " world";

Expression<Func<string>> expression = () => (someCondition ? trueValue : falseValue) + someValue;

Console.WriteLine(expression.ToReadableString()); /* Prints "() => someCondition ? trueValue : falseValue + someValue" */

The original expression and the printed expression are significantly different and will produce different output.

Func<string> f1 = () => (someCondition ? trueValue : falseValue) + someValue;
Func<string> f2 = () => someCondition ? trueValue : falseValue + someValue;
Console.WriteLine(f1()); /* Prints "hello world" */
Console.WriteLine(f2()); /* Prints "hello" */

There may be other cases where the brackets are important due to the order of operations but this was the first example I tried and found this issue.

Using Visual Studio 2015 with ReadableExpressions v1.9.0.0

NullReferenceException when opening the visualizer

at AgileObjects.ReadableExpressions.Translations.TranslationBuffer.WriteToTranslation(String stringValue) at AgileObjects.ReadableExpressions.Translations.StaticTranslators.DefinitionsTranslator.WriteParametersToTranslation(MethodBase method, TranslationBuffer buffer) at AgileObjects.ReadableExpressions.Translations.StaticTranslators.DefinitionsTranslator.Translate(MethodInfo method) at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.GetData(Object target, Stream outgoingData, Action2 serializer)
at AgileObjects.ReadableExpressions.Visualizers.Vs16ExpressionVisualizerObjectSource.GetData(Object target, Stream outgoingData)
at Microsoft.VisualStudio.DebuggerVisualizers.DebuggeeSide.Impl.ClrCustomVisualizerDebuggeeHost.GetData(Object visualizedObject)`

When I try to visualize the following expression:
{Method = {Boolean lambda_method(System.Runtime.CompilerServices.Closure, Core.Data.Models.Base.EntityBase, Core.Data.Models.Base.EntityBase)}} for the following delegate signature: Func<EntityBase, EntityBase, bool>

Moreover when I click the visualizer icon on the debugger popup of the delegate, I end up with an empty window that only shows the signature Func<x,y,z>. When I expand that node and visualize the Method (not Target) field of that delegate, I get that exception.

How to see resolved expression from debugger in VS 2017?

Following up comment on blog post here.

Reproduction Step

  1. Create a dummy project with AutoMapper
  2. Add a few mapping to AutoMapper config like
AutoMapper.Mapper.Initialize(cfg =>
{
    cfg.AllowNullCollections = true;
    cfg.CreateMap<Entity1, Entity1VM>().ReverseMap();
    cfg.CreateMap<Entity2, Entity2VM>().ReverseMap();
});

var expression = AutoMapper.Mapper.Configuration.BuildExecutionPlan(typeof(Entity1), typeof(Entity1VM));
  1. In debug, break right after expression has been initialized.
  2. Add expression to Watch window.

Expected behavior

Don't really know where to see the resolved expression. Should it be displayed from the Watch window?

Actual result

Here is what I currently get in Watch window.
image

Information

Regarding your question from the blog post, the AgileObjects.ReadableExpressions.Visualizers.Vs15.dll assembly is properly located in C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Packages\Debugger\Visualizers.

Versions

Microsoft Visual Studio Professional 2017
Version 15.2 (26430.6) Release
VisualStudio.15.Release/15.2.0+26430.6
Microsoft .NET Framework
Version 4.6.01586

ReadableExpressions.Visualizers v1.8.6

Bug: properties and constants

Hi,
I have two issues, but I'm not sure if ReadableExpressions is supposed to generate working C# code or if the idea is to just generate "human readable" code.

In any case, it would be awesome if there was a way to customize how some things are converted.

The two bugs/issues I ran into are:

Properties

obj.X = 5; where X is a property, will become obj.set_X(5);

Well, it's not really wrong as internally properties are just methods... but it would be cool if there was a setting to get the "expected" format.

Maybe have a setting like ConvertPropertyAccessToDirectSyntax or something like that.

Constants

var formatterExp = Constant(formatterInstance);
Call(formatterExp, deserializeMethod, arg1, arg2, arg3));

becomes:

ReferenceFormatter<MyObject>.Deserialize(arg1, arg2, arg3);

Obviously there's nothing else that ReadableExpressions could use other than the type name in this case.

But there should be something like a callback where I can customize how a Expression.Constant gets written. Having a simple Func<ConstantExpression, string> customizeConstantToString as a setting would be awesome.

UI changes

Syntax coloring is good, but...

  • Font size is too big, expected same font size as in code
  • Automatic window resizing is weird, better to open in the same window size and position. Maybe option for this?

Dont change Visual Studio language

Hi.

I use Microsoft Windows in one language and Microsoft Visual Studio in another one.
After install or update ReadableExpressions, it changes my Visual Studio language to use the "Same as Microsoft Windows".

Thanks.

VS 2017 - Magnifying glass icon duplicated

Hi, I'm using VS 2017 Enterprise (15.6.4), when hovering over a lambda expression two magnifying glasses are shown (see the picture attached), no matter on which one I click it shows me the same result.
Is this a bug or do I miss something?
Thx in advance

readableexpressions visualizers

Unnamed anonymous type variable naming issue

Reproduced at least with 3.2.2

image

Offender:
image

(qr, dr) => ((
    qr,
    dctx,
    rd,
    expr,
    ps,
    preamble) =>
{
    var ldr = (MySqlDataReader)dr;
    var anonymousType_Span class="kw">bool</span>_Span class="kw">int</span>_Span class="kw">int</span> = new { IsGroping = (ldr.IsDBNull(0) ? 0 : (int)ldr.GetInt64(0)) == 1, Id1 = ldr.GetInt32(1), Count = (int)ldr.GetInt64(2) };

    return anonymousType_Span class="kw">bool</span>_Span class="kw">int</span>_Span class="kw">int</span>;
}).Invoke(
    qr,
    qr.DataContext,
    dr,
    qr.Expression,
    qr.Parameters,
    qr.Preambles)

[Feature] Visualize Type, MethodInfo

Hi,
Thanks for great extension. It really helps me in modifying and analyzing expression trees.

But one thing i'm missing. Visual Studio 2019 and previous versions shows in hint very uninformative information for types, especially for complex generic types.

It would be better to see instead of

System.Tuple`2[[Tests.Playground.EagerLoadingTests+MasterClass, linq2db.Tests.Playground, Version=2.6.0.0, Culture=neutral, PublicKeyToken=e41013125f9e410a],[Tests.Playground.EagerLoadingTests+DetailClass, linq2db.Tests.Playground, Version=2.6.0.0, Culture=neutral, PublicKeyToken=e41013125f9e410a]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Shorter version

Tuple<MasterClass, DetailClass>

Also during modification Expression Tree, there are many MakeGenericMethod calls, so it is also better to show shorter hint for MethodInfo
Instead of

{System.Linq.IQueryable`1[System.Tuple`2[Tests.Playground.EagerLoadingTests+MasterClass,Tests.Playground.EagerLoadingTests+DetailClass]] SelectMany[MasterClass,DetailClass,Tuple`2](System.Linq.IQueryable`1[Tests.Playground.EagerLoadingTests+MasterClass], System.Linq.Expressions.Expression`1[System.Func`2[Tests.Playground.EagerLoadingTests+MasterClass,System.Collections.Generic.IEnumerable`1[Tests.Playground.EagerLoadingTests+DetailClass]]], System.Linq.Expressions.Expression`1[System.Func`3[Tests.Playground.EagerLoadingTests+MasterClass,Tests.Playground.EagerLoadingTests+DetailClass,System.Tuple`2[Tests.Playground.EagerLoadingTests+MasterClass,Tests.Playground.EagerLoadingTests+DetailClass]]])}

More informative version

IQueryable<Tuple<MasterClass, DetailClass>> SelectMany<MasterClass, DetailClass, Tuple<MasterClass, DetailClass>>
(
	IQueryable<MasterClass> source,
	Expression<Func<MasterClass, IEnumerable<DetailClass>>> collectionSelector,
	Expression<Func<MasterClass, DetailClass, Tuple<MasterClass, DetailClass>>> resultSelector
)

I have did MethodInfo visualization myself using assembly level DebuggerDisplay

[assembly: DebuggerDisplay("{LinqToDB.Common.Internal.MethodInfoExtensions.ShortDisplayName(this)}", Target = typeof(MethodInfo))]

But with no chance to visualize Type, the following attribute won't work

[assembly: DebuggerDisplay("{LinqToDB.Common.Internal.TypeExtensions.ShortDisplayName(this)}", Target = typeof(Type))]

It is possible to visualize Type and MethodInfo using your extension?
Thanks.

VS 2017 extension not working

It seems like the extension is not working as expected in VS 2017. When I add the expression variable to the watch window and click on the magnifier icon, an error is shown stating that a custom viewer can't be loaded.
untitled
couldnotloadcustomviewer

I am using VS 2017 version 15.3.5.
I would also recommend providing information on how to access the data from your extension at the page in the marketplace. Also, please provide some indicator that the installation has finished.

Incorrect code generated for Convert with conversion method

Hello, thank you for this great tool!

I started to use it and found following issue:

            var from = typeof(string);
            var to = typeof(int);

            var p = Expression.Parameter(from, "p");

            var body = Expression.Condition(
                Expression.NotEqual(p, Expression.Constant(null, from)),
                Expression.Convert(p, to, to.GetMethod(nameof(int.Parse), new[] { from })),
                Expression.Constant(0));

            var expr = Expression.Lambda<Func<string, int>>(body, p);

produces following C# code:

p => (p != null) ? (int)p : 0

when it should be

p => (p != null) ? int.Parse(p) : 0

.Net Core error

An unhandled exception of type 'System.TypeInitializationException' was thrown by the custom visualizer component in the process being debugged. The type initializer for 'AgileObjects.ReadableExpressions.Visualizers.Core.Configuration.VisualizerDialogSettings' threw an exception.

   at AgileObjects.ReadableExpressions.Visualizers.Core.Configuration.VisualizerDialogSettings.GetInstance()
   at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.GetDialogSettings()
   at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.<>c.<Translate>b__4_0(TranslationSettings settings)
   at AgileObjects.ReadableExpressions.ExpressionExtensions.GetTranslationSettings(Func`2 configuration)
   at AgileObjects.ReadableExpressions.ExpressionExtensions.ToReadableString(Expression expression, Func`2 configuration)
   at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.Translate(Expression expression)
   at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.GetTranslationFor(Object target)
   at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.GetData(Object target, Stream outgoingData, Action`2 serializer)
   at AgileObjects.ReadableExpressions.Visualizers.Vs16ExpressionVisualizerObjectSource.GetData(Object target, Stream outgoingData)
   at Microsoft.VisualStudio.DebuggerVisualizers.DebuggeeSide.Impl.ClrCustomVisualizerDebuggeeHost.GetData(Object visualizedObject)```

Issue with displaying expression with \0 (0x00) character

(This issue affects also visual studio's visualizer)
If visualized expression contains \0 in character/string constant, visualization displays expression only to that point. I suspect that rendered expression doesn't escape it and visual studio window, used for display, treat it as terminating character.

Invalid ternary operation code generated

        public enum Test
        {
            One,
            Two
        }

Expression<Func<bool, bool>> expr = flag => (flag ? Test.One : Test.Two) == Test.Two;

Expected:

flag => (flag ? Test.One : Test.Two) == Test.Two
or 
flag => (int)(flag ? Test.One : Test.Two) == 1

Actual:

flag => ((int)flag ? Test.One : Test.Two) == 1

Translation of captured values

I have tried using the TranslateConstantsUsing option, but it does not seem to change the string. Am I doing something wrong? I was using this code for testing:
expression.ToReadableString(c => c.TranslateConstantsUsing((type, value) => "Hello");

Maybe I didn't understand what this setting is doing. I have an Expression like this: x => x.Property.Equals(value)) and I want to translate the variable name value to the actual value in the variable. How can I translate this value?

System.ArgumentOutOfRangeException

An unhandled exception of type 'System.ArgumentOutOfRangeException' was thrown by the custom visualizer component in the process being debugged.
Length cannot be less than zero. (Parameter 'length')
   at System.String.Substring(Int32 startIndex, Int32 length)
   at AgileObjects.ReadableExpressions.Extensions.PublicTypeExtensions.GetGenericTypeVariableName(String variableName, Type namingType, TranslationSettings settings)
   at AgileObjects.ReadableExpressions.Extensions.PublicTypeExtensions.GetVariableName(Type type, TranslationSettings settings)
   at AgileObjects.ReadableExpressions.Extensions.PublicTypeExtensions.GetVariableNameInCamelCase(Type type, TranslationSettings settings)
   at AgileObjects.ReadableExpressions.Translations.ParameterTranslation.UnnamedParameterTranslation..ctor(ParameterExpression parameter, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.ParameterTranslation.For(ParameterExpression parameter, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.AgileObjects.ReadableExpressions.Translations.Interfaces.ITranslationContext.GetCodeBlockTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.AssignmentTranslation..ctor(BinaryExpression assignment, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.AgileObjects.ReadableExpressions.Translations.Interfaces.ITranslationContext.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation.BlockStatementTranslation..ctor(Expression expression, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation.BlockAssignmentStatementTranslation..ctor(BinaryExpression assignment, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation.GetBlockStatements(BlockExpression block, ITranslationContext context, Boolean& hasMultiStatementStatement, Int32& estimatedStatementsSize, Boolean& hasGoto)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation..ctor(BlockExpression block, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.AgileObjects.ReadableExpressions.Translations.Interfaces.ITranslationContext.GetCodeBlockTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.ConditionalTranslation.TernaryTranslation..ctor(ConditionalExpression conditional, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.ConditionalTranslation.For(ConditionalExpression conditional, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.AgileObjects.ReadableExpressions.Translations.Interfaces.ITranslationContext.GetCodeBlockTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.ConditionalTranslation.TernaryTranslation..ctor(ConditionalExpression conditional, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.ConditionalTranslation.For(ConditionalExpression conditional, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.AgileObjects.ReadableExpressions.Translations.Interfaces.ITranslationContext.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation.BlockStatementTranslation..ctor(Expression expression, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation.GetBlockStatements(BlockExpression block, ITranslationContext context, Boolean& hasMultiStatementStatement, Int32& estimatedStatementsSize, Boolean& hasGoto)
   at AgileObjects.ReadableExpressions.Translations.BlockTranslation..ctor(BlockExpression block, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.AgileObjects.ReadableExpressions.Translations.Interfaces.ITranslationContext.GetCodeBlockTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.LambdaTranslation..ctor(LambdaExpression lambda, ITranslationContext context)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree.GetTranslationFor(Expression expression)
   at AgileObjects.ReadableExpressions.Translations.TranslationTree..ctor(Expression expression, TranslationSettings settings)
   at AgileObjects.ReadableExpressions.ExpressionExtensions.ToReadableString(Expression expression, Func`2 configuration)
   at AgileObjects.ReadableExpressions.Visualizers.Core.ExpressionVisualizerObjectSource.GetData(Object target, Stream outgoingData, Action`2 serializer)
   at AgileObjects.ReadableExpressions.Visualizers.Vs16ExpressionVisualizerObjectSource.GetData(Object target, Stream outgoingData)
   at Microsoft.VisualStudio.DebuggerVisualizers.DebuggeeSide.Impl.ClrCustomVisualizerDebuggeeHost.GetData(Object visualizedObject)

Misplaced return

This translates to

typeMapDestination.Foos =
{
var passedDestination = (dest == null) ? null : typeMapDestination.Foos;
var collectionDestination = (passedDestination != null) ? passedDestination : new List<ComplexTypeMapper.Foo>();
return (resolvedValue == null)
? collectionDestination
: {
var enumerator = resolvedValue.GetEnumerator();
while (true)
{
if (enumerator.MoveNext())
{
var item = enumerator.Current;
collectionDestination.Add(ctxt.Map(item, null));
}
else
{
break;
}
}

        return collectionDestination;
return     }

}

VS 2019 support

Opening this issue to track support of the extension for VS 2019 which is currently in Preview 1.

MSI does not install for VS2017 Enterprise

πŸ‘‹ Hello,

Testing out your debugger visualizer, and I notice it does not install for Visual Studio 2017 Enterprise.

I have 2015 Professional and 2017 Enterprise installed.
The extension appears in the 2015 list and not in the 2017 list.

=== Logging stopped: 9/19/2018  10:54:51 ===
MSI (c) (5C:E8) [10:54:51:283]: Note: 1: 1707 
MSI (c) (5C:E8) [10:54:51:283]: Note: 1: 2205 2:  3: Error 
MSI (c) (5C:E8) [10:54:51:283]: Note: 1: 2228 2:  3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1707 
MSI (c) (5C:E8) [10:54:51:283]: Note: 1: 2205 2:  3: Error 
MSI (c) (5C:E8) [10:54:51:283]: Note: 1: 2228 2:  3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1709 
MSI (c) (5C:E8) [10:54:51:283]: Product: AgileObjects.ReadableExpressions.Visualizers -- Installation completed successfully.

MSI (c) (5C:E8) [10:54:51:284]: Windows Installer installed the product. Product Name: AgileObjects.ReadableExpressions.Visualizers. Product Version: 1.12.1.0. Product Language: 1033. Manufacturer: AgileObjects. Installation success or error status: 0.

MSI (c) (5C:E8) [10:54:51:284]: Grabbed execution mutex.
MSI (c) (5C:E8) [10:54:51:284]: Cleaning up uninstalled install packages, if any exist
MSI (c) (5C:E8) [10:54:51:285]: MainEngineThread is returning 0
=== Verbose logging stopped: 9/19/2018  10:54:51 ===

Correct parantheses for arithmetic unary minus

Please correct me if I'm wrong, but shouldn't double negation of x yield "-(-x)"?
Instead it returns "--x".

The following statement fails:
Assert.AreEqual(Expression.Negate(Expression.Negate(Expression.Parameter(typeof(double), "x"))).ToReadableString(), "-(-x)");

DBNull.Value outputs empty string

My expression tree is assigning DBNull.Value to a DBParameter.Value property.

DebugView:
.Constant<System.Data.Common.DbParameter>(@d1).Value = .Constant<System.Object>()

ReadableExpressions:
Value = ;

It confuses when the output is not legal C#. Can a placeholder be output where the missing value should go?

Body of Expression with type Func[SomeClass, AnonymousType] isn't resolved with the custom naming factory

I tried using ReadableExpressions to convert an Expression that contains a Func[SomeClass, AnonymousType] to C# code:

expression.Body.ToReadableString(c=>c.NameAnonymousTypesUsing(x=>MyNameFactory(x)))

however, it returns

new {A = x.A, B = x.B}

which, while it is valid code, drops the type information. I'd expect the anonymous type to be presserved and renamed using the factory I provided (which currently is not being called), returning something like this:

new MyClassNameAsGeneratedByMyFactory(){A = x.A, B = x.B}

Is this by design or is it a bug?

Visual Studio 2022 Support

Well, Visual Studio 2022 preview is become usable for me. One thing that I have missed is ReadableExpressions.
Any plans to support?

Thanks!

Installation failure 2.3.0

I have VS 2017 and 2019 and the installer fails with an unspecified error. I have unblocked the msi and bypassed Windows Defender.

Possible formatting bug

v = (a, b) => (a + b)).Invoke(1, 2

Note the missing parenthesis before the lambda and at the end of the Invoke method call.

Minimal example:

        var a = Expression.Parameter(typeof(int), "a");
        var b = Expression.Parameter(typeof(int), "b");
        var body = Expression.Block(Expression.Add(a, b));
        var lambda = Expression.Lambda(body, a, b);
        var call = Expression.Invoke(lambda, Expression.Constant(1), Expression.Constant(2));
        var variable = Expression.Variable(typeof(int), "v");
        var assign = Expression.Assign(variable, call);
        Console.WriteLine(assign.ToReadableString());

Method visualization is broken

Try to visualize any of these methods.

var methods = typeof(Queryable).GetRuntimeMethods()
    .Where(e => e.Name == "SelectMany").ToArray();

Invalid output:

public static IQueryable Queryable.SelectMany
(
    IQueryable source,
    Expression<FUNC>> selector
)

Same issue with visualizing types.

Version 3.0.1

Translating params

Expression<Func<string>> expr = ()=>string.Concat("1","2","3","4","5");
expr.ToReadableString().Dump();

I get

() => new[] { "1", "2", "3", "4", "5" }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.