Last time we talked about ReSharper out of process, we took a (very long!) look at the magnitude of the task. It’s a massively complex job, re-architecturing an application with 14 years worth of assumptions of COM based APIs into an asynchronous cross process model.
That post details the complexity of moving the project model out of process – migrating from calling Visual Studio’s COM APIs on the UI thread, to using the MSBuild APIs in a separate process. This is now done, and has been the default way we manage the list of projects, files and references since ReSharper 2019.2.
As we’ve just been talking about our roadmap for ReSharper 2020.1, it’s time to ask the obvious question: where are we now?
Current internal builds are running a large part of ReSharper out of process, although it’s definitely not fully functional. Joining the project model, ReSharper’s code model is now running out of process too. This includes all of the language parsing, analysis and inspections, caching, syntactic and semantic highlighting as well as the Alt+Enter menu and quick fixes and context actions. This is a significant milestone, although it’s not quite complete – we’re still working on document and text control handling and integration.
While this step is significant, there’s still a lot to do before this is usable and ready for release. Most of ReSharper’s features work on top of the code model, and these features have not yet been updated to work when running out of process. For example, an action that is invoked from a menu item needs to run out of process, but might still need data from Visual Studio, such as which item is selected in Solution Explorer or open in the editor. We can pass all the necessary data to the ReSharper process, but need to balance this carefully, as fetching the data requires time on the UI thread.
Similarly, refactorings require UI running in the Visual Studio process, based on data from the backend ReSharper process. We’ve made a lot of changes already for Rider that will apply here, and we’re hoping this makes the task easier. But we still need all of these features to be migrated before we can say this is done.
We’ll be continuing this work during 2020. We won’t have anything to try in 2020.1, but we do plan to release experimental builds as the year progresses.
If you’re interested in some of the technical challenges of running ReSharper out of process, read on for a taste of some of the things we’ve been working on since our last post. Feel free to skip this section – this is only for the curious!
One of the biggest challenges is that this massive architectural refactoring has to happen in our main development branch. This is a long term refactoring. It’s not something we can stop the world and fix – we need to keep up to date with new versions of C# and Visual Studio, so we need to keep ReSharper moving forward, and make the changes for out of process.
In other words, the architecture has to work both in-process and out of process, all from the same code base. We can’t have two implementations of everything, as that will double our testing load, and will inevitably lead to bugs as the implementations diverge. So we’ve been refactoring internal components to run either in-process or out of process, and we can even toggle between in and out of process dynamically at run time!
But this leads to complexity too. When our component container creates new object instances, and passes in dependencies, it needs to know if those dependencies are in or out of process. And it can be different each time it’s run!
The process of loading a solution is also significantly affected by moving to an out of process model. There are specific milestones during solution load where we need to perform tasks. For example, building caches requires the list of files in a project, so we need to load the project model first. Various other steps require the caches, and so on.
Even though we’re moving ReSharper to run out of process, this doesn’t mean that all of ReSharper will be running in a separate process – there are still parts that need to live in the Visual Studio process, and yes, you’ve guessed it, some of them are solution load tasks (e.g. we still get some project model details from Visual Studio’s COM APIs for projects that don’t support MSBuild).
All of this means that we have to synchronise solution load tasks across two processes. Fortunately, these problems have been solved, and we can now construct ReSharper in or out of process, load solutions, load the project model, and build and use the code model to run analysis and quick fixes.
Before we can move on, we need to finish off the work with documents and text controls. Obviously, the Visual Studio editor integration needs to remain in the Visual Studio process, but we want everything else to be in the external ReSharper process. And of course, we need it to work correctly both in and out of process. But once this is done, we get to move up a layer, and start work on the action system, and more UI-facing features!
So while we don’t have anything visible in ReSharper 2020.1, a lot of updates are happening towards making ReSharper out of process a reality.