Migrating from IntelliJ IDEA to VSCode and Metals – Staying Productive at Writing Scala

7 10 min read Scala
Paweł Kiersznowski

Paweł Kiersznowski

Scala Developer

Moving from IntelliJ IDEA to VSCode and Metals

In terms of writing Scala, IntelliJ IDEA has always been the most widely used IDE. Despite all of its unique and amazing features, the Scala community created a different coding environment strictly focused on fulfilling their developers’ specific needs. Scalameta contributors addressed them, and thanks to the work they’ve done, we can now write Scala in VSCode (and plenty of other code editors) – with the help of Metals, a language server that provides us IDE features in code editors.

In this article, you’ll find out why it’s worth giving VSCode and Metals a try, how does Metals work, how to do a quick setup, what plugins and features you should look at, and more importantly – how to move your IntelliJ settings and habits to be productive from day one.

Why VSCode + Metals instead of IntelliJ?

IntelliJ is doing a great job at increasing developer productivity, and while it might be enough for you, you might want to give Metals a shot because of the following differences:

  • Lower memory usage. VSCode by default uses a really low amount of RAM, which allows us to have multiple projects open at the same time. IntelliJ tends to be heavy – working with 3 projects simultaneously can make it quite unresponsive, despite having 32GB of RAM.
  • Lower CPU usage. Neither VSCode or Metals run indexing tasks as heavy as in JetBrains IDEs – indexing in IntelliJ can significantly slow down opening up a project, and is able to use even up to 70% of CPU, depending on the project size.
  • Warning/error output straight from the build tool. Thanks to this approach, we have a few significant benefits compared to using a custom presentation compiler (like the one in IntelliJ) for showing compilation output. The first benefit is reflecting the build tool output in the code editor – Metals guarantees you that if the code compiles successfully in the build tool, you won’t see any misleading errors in the editor. This also eliminates the need of writing any editor plugins for e.g. libraries providing code generated by macros, which cause a lot of incorrectly highlighted errors in IntelliJ – even with the help of BSP support.
  • Shared compilation. As you save the code you’re working on, it is instantly compiled in the background. If you’re using the same build tool in both the terminal and the editor, the waiting time is reduced to zero when you switch from the editor to the terminal to run a compile task because the code has already been compiled by Metals.
  • Fast code completion. Metals incorporates an optimized Scala presentation compiler which makes the code completion incredibly responsive.
  • Quick startup. This aspect makes it enormously comfortable to take a quick look at the project, not necessarily with the intent of coding.

How does Metals work?

Metals is powered by multiple components – most notably: LSP, BSP, and Bloop.

The main idea behind LSP (Language Server Protocol) is to provide the comfort of not having to implement features like auto-completion, go to definition, etc. separately for every single language. Thanks to this protocol, we can re-use these features in other editors with minimal effort.

BSP (Build Server Protocol) works similarly to LSP, except it revolves around build servers. The amount of available build tools is growing – BSP is here to save the IDE developers’ effort and time so they don’t have to write build tool-specific code, thanks to the abstraction layer delivered here.

Bloop (abbreviated from build loop) is the last link here. Metals imports builds to Bloop, fetches build information, and communicates back and forth with it every time we edit our code. Additionally, it enhances the responsivity and stability of Metals in terms of compiling our code – Bloop caches compilations for the same inputs and makes sure there are no conflicts when the compilation is running concurrently.

To sum up, the chain of execution is as follows: when the code is edited, VSCode is communicating with Metals through LSP, and then Metals exchanges information back and forward with Bloop through BSP.

Metals features in practice – examples

Auto-import

Code completions

Compilation warning output

Go-to-definition

Finding references

Renaming members

Type annotation suggestions

How do I start?

Installing VSCode and Metals is pretty straightforward – you can download it here, and then go to Extensions (Ctrl+Alt+X) and install Metals.

You can also skip those steps and just jump straight into a Gitpod with preinstalled VSCode and Metals. This will launch a session with a prebuilt coding environment in just a matter of seconds.

Importing IntelliJ settings

Getting used to new keybindings in a new editor can be burdensome – you might want to stick to a setup you already know. This is where IntelliJ Importer comes to the rescue. If you don’t have any customized keybindings to import, this plugin can always provide you the default IntelliJ ones.

You can also export your IntelliJ Code Style settings to a .editorconfig file and import it to the new editor, although the file in the majority will contain only IntelliJ specific options that won’t be unfortunately understood by VSCode. If you’re willing to give it a try and import basic settings like indent size, max line length, etc. – EditorConfig for VSCode will come in handy.

Recommended features and plugins

Git history

VSCode provides basic Git history support that provides us the ‘Timeline’ view containing a list of changes introduced by specific commits and allowing us to open up a diff view for each commit, copy their IDs and commit messages. If it doesn’t cover your basic needs, it’s worth taking a look at GitLens, which provides a way richer feature set.

Local history

Having a local history can be incredibly useful if you tend to forget about committing changes or simply just want to go back to changes from several minutes ago without much fuss. VSCode doesn’t have this feature built-in, but fortunately, there’s an existing plugin we can use.

Settings Sync

This feature will come in handy for anyone working on multiple machines – it’ll keep your settings the same across all computers. Settings Sync also makes local and remote backups of your settings so you can revert to your previous setup anytime.

Error lens

A neat plugin that improves your coding experience by delivering more prominent warning/error output by highlighting and printing the message inline.

Live Share

This plugin is equivalent to the Code With Me feature recently introduced in IntelliJ IDEA. Absolute timesaver for fans of pair-programming.

VSCode in the browser

Excellent project that lets you easily host your environment on a dedicated machine, providing the ability to code using any device and also preserving your workstation lifespan by offloading intensive tasks to the server. It works wonderfully on a tablet – if you want to turn yours into a ultra-mobile workstation, you should take a look at this plugin.

You can either set it up on your virtual machine (or container) or deploy it to a cloud hosting platform. There are a few platforms that provide free or low price plans – you can find them here.

Shrink/expand selection

A Metals feature that is also present in JetBrains IDEs, but is often forgotten because of a slight change in the keyboard shortcut when moving to VSCode – you can shrink or expand the current selection with Shift+Alt+Left and Shift+Alt+Right.

Linked Editing

A convenient mechanism that edits a tag when its matching closing tag is modified. You can enable this feature by switching this setting (Ctrl+Shift+P -> Open Default Settings (JSON)):

"editor.linkedEditing": true

Useful miscellaneous VSCode settings

There is still some room to adjust VSCode to our liking a little bit – consider the settings below to see if some of them will come useful to you.

{
   "editor.formatOnSave":true,
   "editor.minimap.enabled":false,
   "files.autoSave":"afterDelay",
   "files.autoSaveDelay":500,
   "editor.snippetSuggestions":"top",
   "files.watcherExclude":{
      "**/.git/objects/**":true,
      "**/.git/subtree-cache/**":true,
      "**/node_modules/**":true,
      "**/.direnv/**":true,
      "**/.venv/**":true
   },
   "search.exclude":{
      "**/node_modules":true,
      "**/bower_components":true,
      "**/venv/**":true,
      "**/.git/**":true,
      "**/project":true,
      "**/target":true,
      "**/.bloop":true,
      "**/.metals":true
   },
   "telemetry.enableTelemetry":false,
   "telemetry.enableCrashReporter":false,
   "liveshare.guestApprovalRequired":true
}

editor.minimap.enabled – Shows a zoomed-out preview of your code (visible on the top right on the screenshot below). Can be useful unless you’re on a smaller screen – it can become easy to ignore. Having this disabled will also improve your performance.

files.autoSave – By default, VS Code doesn’t save your changes to disk automatically. You can use this option to keep it disabled, save the changes after a configured delay when focus moves out of the editor (onFocusChange), or when the focus moves out of the VSCode window (onWindowChange).

files.watcherExclude and search.exclude – list of paths that shouldn’t be considered by VSCode for analysis or searching.

telemetry.enableTelemetry and telemetry.enableCrashReporter – Controls sending usage data and crash reports to Microsoft.

liveshare.guestApprovalRequired – If you’re using the Live Share extension, you can prevent signed-in guests from joining until you decide to approve them.

Conclusion

Recently we have seen great movement in terms of improving developer productivity. We have plenty of editors available for our use, each of them having captivating feature sets. It’s a decent opportunity to take a look at other tools than the ones we stuck to during our ongoing programming journey.

Today we grabbed a chance to discover Metals’ inner workings, find out how it stands out combined with VSCode, see how easy it is to do a quick setup with the help of Gitpod, and learn about many productivity-enhancing extensions and plugins in our new code editor.

7 Comments

Metals works fine with VSCodium. Not all extensions mentioned in the article might be found on https://open-vsx.org/ though – and I believe that’s the extensions registry that VSCodium supports by default.

Intellij is still the best at least because of Code-with-me, rich debugging tools, functional errors highlighting and functional type hints

One problem: I can run a main method (any of existent), test suite or test case in IntelliJ by a couple of clicks or by a one keys combo. It is out of box feature. I did not find it in vscode. It requires an additional configuration and show the error message if I have more than one main method.

Great. Very very useful stuff. I find Intelij very good for refactoring.
Can u please share your observations on refactoring in VsCode.

Thanks! In terms of refactoring – Metals tries to catch up with IntelliJ, but it’s still quite not up there. It’s faster to use IntelliJ for this kind of operation.

Leave a Reply