We are pleased to announce the official release of our VSCode & VIM plugins.
This blog post was kept minimalistic for a reason, so I wanted to expand in a little bit more on the technical details, even though this all might be subject to change.
Establishing a Development Process
First things first: The 1.0 release for VSCode was the first stepping stone of taking over the work that has originally started in the Reason Language Server and to establish a coordinated release pipeline that moves in the same speed as the syntax, compiler and documentation. It was important to us to make the plugin experience almost plug-and-play, without any configuration / installation steps if possible.
It took us some time understanding the characteristics of each editor (vim, vscode, sublime), and I even taught myself VIML development just to be able to build a plugin that theoretically doesn’t need any other plugin to work properly. Maybe let’s highlight our core philosophy we put behind our plugin development:
Create a toolchain that is built around ReScript’s Compile Time Speed
The ReScript compiler is pretty much an “instant-compiler”, so we wanted to build our tooling around the compilation speeds to spare us a lot of headaches with caches etc.
There were a few concerns we had with pre-existing tooling:
- Caches caused a lot of bad UX
- Long running language servers caused memory leaks, which required lots of annoying manual restarts and hogged multiple GB of memory after a few hours
- Huge files caused huge delays on code completion, type hints etc.
- The existing tools had too many features and we didn’t understand what’s going on (especially when the tooling is a monolithic lsp server)
- Finding the right setup for beginners was a nightmare (“just give me one official plugin so i can get to work”)
So how did we tackle these problems?
Type Hints, Jump to Definition, Autocomplete
We created a pretty lean binary that is able to get all the required type-hint / autocompletion information in a short-lived subprocess call that returns relevant JSON data. Cristiano fine tuned it to be fast (also for complex React modules), and our goal is to keep it fast. Our LSP (the one provided with rescript-vscode) is essentially a thin wrapper around this. To give you more context on “fast”: It’s perfectly fine to type-hint in VIM without any async call, it’s fast enough to run on the main thread and still offers nice UX, even in huge / complex ReScript files.
This system is extremely easy to use, since the binary is optimized to ReScript project structures, and knows exactly where to find the build-artifacts etc. It is an internal tool that will eventually be shipped directly within the ReScript npm package if the design turns out to be successful.
That said, we might change our opinion on the approach, for now this seems like the most sensible way from a development process / engineering angle, and the results are pretty good so far. So don’t rely on any tooling internals.
Compiler Output Diagnostics
We also kinda formalized the Error Diagnostics protocol, that all our tools rely on. That means we have a very easy time implementing the error, warning, build state parsing mechanism in different languages without getting out of sync.
The VSCode LSP and the vanilla vim extension both implement the same parsing logic in JS and VIML. It’s pretty easy to read and understand, which improved the whole collaboration process between the compiler / editor teams by a huge margin. Better quality, and more reliable tests for our editor plugins!
Make our Plugins Self Sustained
All our plugins are one-stop-shops, which means you just install the plugin, and you are set. Our VSCode plugin has no switches, no toggles, you just open your ReScript workspace, and the tool will do its job. No separate toolchains, no concepts wrangling, just you and your code.
VIM is a little bit more complex, because everyone has essentially a different setup. We made sure that the plugin brings all the stuff you need, so you can stitch together all the functionality you need in your
vimrc file. E.g. we included all binaries / LSP stuff you need to setup coc-vim without any extra tools.
Remove all Unnecessary Functionality
The original RLS had a lot of bells and whistles that we actually didn’t need. So we just used the stuff we found useful. That means that you will notice some differences between your previous and new setup, and maybe you will miss some functionality. For now, the biggest upside is a more reliable setup, that is easy to debug and easy to understand (and no memory leaks).
As soon as we are feeling more comfortable with the problem domain, we will add back functionality as we go. The codebases got way simpler, so we are positive to move fast in the future.
Things to Watch Out for When Using our Plugins
Since we removed a lot of stuff, we also temporarily removed functionality, e.g. extracting types for incomplete programs. That means whenever you want to get
autocompletion functionality, you’ll need to first make sure to save / build the file you are currently working on.
Building the file (no matter if there’s a type error or not), will create the necessary build artifacts, which will be used to extract all the information we need to provide said functionality.
So whenever you are not getting any type hints, make sure that your current buffer does actually compile.
This was a long post, but since it took us a while to get something worth shipping, we thought we provide you with a little bit more background knowledge. The team is getting really comfortable with the current solution, and we are looking forward improving the experience in the future.