ExpressionTreeVisualizer
ExpressionTreeVisualizer copied to clipboard
Support for Jetbrains Rider
I love this visualizer, it takes a lot of the pain away of working with expression trees.
Unfortunately, I'm on Rider. What would it take to have this visualizer work with JetBrains Rider 2020.1.4?
I've never used Rider, so I have no idea what are its' capabilities and extension points. But I guess you have a couple of options.
The ExpressionTreeToString package provides multiple string renderings for an expression tree, and powers the source view of the visualizer. You can get pretty close to the visualizer's information using the C# and textual tree formatters:
// using ExpressionTreeToString;
Expression<Func<int, int, string>> expr1 = (i, j) => (i + j + 5).ToString();
// C# pseudocode
Console.WriteLine(expr1.ToString("C#"));
// prints the following:
/*
(int i, int j) => i + j + 5.ToString()
*/
// prints a string with all the information in the visualizer's treeview
Console.WriteLine(expr1.ToString("Textual tree", "C#"));
/*
Lambda (Func<int, int, string>)
· Parameters[0] - Parameter (int) i
· Parameters[1] - Parameter (int) j
· Body - Call (string) ToString
· Object - Add (int)
· Left - Add (int)
· Left - Parameter (int) i
· Right - Parameter (int) j
· Right - Constant (int) = 5
*/
I imagine Rider has something like the VS Watch window? You could reference the package in your project, and at runtime call the ToString
extension method on the expression with the appropriate formatter.
If Rider allows you to import and use NuGet packages into the IDE environment only while debugging, you wouldn't have to modify your project.
To go further I have to elaborate on the visualizer architecture. For non-serializable types (like System.Linq.Expressions.Expression
) VS requires there to be 2 DLLs:
- The debuggee-side DLL is injected into the debugged process,, and generates serializable objects from the non-serializable debuggee-side objects. The serializable objects are then serialized and passed across to:
- the debugger-side DLL, loaded by VS, which then uses these objects for the visualizer UI.
For this visualizer (and other visualizers I've written), there end up being 4 components:
-
Serialization model -- generated from the original expression tree, with all the information the visualizer UI requires (
Serialization
subfolder) -
Debuggee-side -- the class that sends the serialization models (
Debuggee
subfolder) -
UI components -- views and view-models that display the UI from the serialization models (
UI
subfolder) -
Debugger-side -- requests information from the debuggee-side, in this case, the serialization models (
Visualizer
subfolder)
I imagine Rider has a similar architecture for extending the IDE while in a debugging session. We'd need to
- replace the debuggee-side DLL with whatever mechanism Rider uses to get information from the debuggee side, and
- replace the debugger-side DLL with whatever mechanism is used by Rider to display dialogs/views while debugging.
If Rider supports opening a WPF window on the IDE side, then the serialization model and UI components can be reused independent of Visual Studio as is; and they are available as a NuGet package.
If Rider doesn't support opening a WPF window, I imagine quite a bit more work would be involved -- the entire UI would have to be recreated in whatever UI framework Rider does support.
(I apologize for the length; I'm trying to give a comprehensive response.)
Addenda
Image from John M. Wrightly's series on writing debugging visualizers:
How the various components are split between packaged DLLs:
@maurei Do you have any further thoughts on this?
Hey @zspitz thanks for the thorough elaboration. I will be getting back at this soon!
There is an issue filed on YouTrack for this.
I've written a small demo application showing how to use the UI controls outside of the VS debugger. I think creating a Rider extension would be a similar process.