Cross-platform testing of Visual Studio editor extensions
One of the highest impact change that went into the new version of Visual Studio for Mac (2019 or 8.0 depending if you talk marketing or engineering) is a completely new implementation of the source editor.
What the team1 did is take the Visual Studio editor from Windows (with large swath of it opensource by the way) that had already been designed with portability in mind and bring that dream to fruition by implementing a state-of-the-art CALayer-backed, CoreText powered, native Cocoa frontend.
Not only does it make the editing experience much faster and more pleasing, the implications for extension authors are tremendous as the editor is not only text data structures and the UI on top of it but also a wide range of exposed and extendable facilities all easily implementable thanks to its use of MEF (Managed Extensibility Framework).
There is one extender in particular that everyone should be familiar with and that’s Roslyn. Not only is Roslyn your favorite compiler and analyzer framework, it’s also what powers all the editing smartness in the IDE for C# and VB.
How do they do it? Simple, every bit of editing feature you enjoy in Visual Studio is ultimately implemented as an MEF extension of the editor (including syntax highlighting, intellisense, code fixes, lightbulbs, info bubbles, etc…) that takes advantage of Roslyn syntactic and semantic models.
Want to know why the C# experience in the new editor also seems better? They are simply reusing those same exact Roslyn editor extensions than on Windows with absolutely no changes. Thus instead of re-doing all that integration ourselves and adding our own layer of bugs, we are now in the same boat than Visual Studio Windows itself.
That last point is the most ground-breaking part in my opinion. With the new editor in Visual Studio Mac, we now have a single, easy to use, easy to extend API to bring all and any improvements we wish to the editor experience in the IDE no matter if its on Windows or on Mac.
In my team we are embracing this fully by bringing all the work we have done over the past months to improve the experience of editing mobile UI markups in Visual Studio Windows to Visual Studio for Mac as well (stay tuned for that).
I wish I could say it was a complex process for self-congratulatory purposes but, as it turns out, we have been able to share and port 95% of our code to Visual Studio for Mac by only doing a tiny amount of refactoring with the crux of the changes being around splitting the UI and IDE specific parts of the extensions into their own, MEF importable parts.
Introducing MiniEditor
That last bit is actually what brings me to write this article. One difficulty of being an extender that has to work on two IDE fronts is that it makes it more complicated to unit-test our work because we need to make it function in a fashion that’s both IDE-agnostic and UI-toolkit agnostic.
Since the (now) two existing implementations are both platform specific, we needed to go fill that void with essentially a third one that would only carry the truly cross-platform pieces of the puzzle. Thus MiniEditor was born.
In a nutshell, MiniEditor is a project that assembles a subset of code from the open-sourced editor bits (that I already mentioned above) and a minimal amount of glue code and mocks so that you can easily test your editor extensions (provided they are themselves platform-agnostic).
More specifically the two key testing objectives that we had for MiniEditor (for now) were:
- Being able to test our low-level infrastructure code that uses interfaces such as
ITextDocument
,ITextBuffer
,ITextSnapshot
and so on with the real implementation of those interfaces - Ensure the correctness of our async completion Intellisense providers
The README on the GitHub project page gives a good run down of how to setup the library and use it.
Hopefully this gives you an appetite to start porting (or creating) your own editor extensions to Visual Studio for Mac today!