Build Server Protocol in sbt

EDIT: sbt 1.4.0 is now released

Partial support for the BSP protocol has been shipped in sbt milestone 1.4.0-M1. And so it is now possible for any BSP client, Metals and IntelliJ for instance, to connect to sbt server.

Both Metals and IntelliJ are used to relying on Bloop for importing an sbt project. Bloop is a build server that manages compilation, test and run of several workspaces concurrently. It supports BSP and much more.

The combination of Bloop and IDEs has proved to be reliable and efficient. However, the integration with sbt is still burdened by the injection of a plugin (sbt-bloop). For this reason we decided to implement BSP in sbt.

In this post I propose you try to import your project in Metals or IntelliJ by connecting to the sbt server directly, using BSP.

The good aspect of it is that the IDE uses the exact same compiler than you do when you run sbt compile, thereby:

  • you are immune to inconsistencies (false error reports)
  • you avoid duplicated compilation which consume resources
  • when you run sbt test or sbt run your code is already compiled

Metals

Metals is a BSP client which means that it relies on a BSP server to delegate compilation, run and test.

By default Metals connects to Bloop. Here we want to prevent that because we want Metals to connect to sbt server instead of Bloop.

  1. Close VS Code and remove the .bloop folder, which contains the Bloop configuration files. You can optionally remove the project/metals.sbt file that is not needed anymore.
  2. Open VS Code again. Metals will propose you to import the build. Deny it by clicking on Not now.
  3. Set sbt version to 1.4.0 in the project/build.properties file.
  4. You are good to start the sbt shell.

Once sbt is loaded you should see a log saying that sbt server started. You can also check that a .bsp/sbt.json file has been created. This file contains the information that Metals needs to connect to sbt.

  1. In the Metals panel click the Connect to build server button and see the magic happens.

Metals sends several requests to sbt to extract the build structure out of it. You can see that in the sbt shell as well as in the Metals log (View > Output then choose Metals in the dropdown list).

  1. Open a source file and start coding.

Each time you save a file, Metals sends a compilation request to sbt. Every compile error or warning is reported by sbt to Metals so that it can highlight them to you.

About code navigation

Code Navigation in Metals relies on the semanticdb files that are generated by the semanticdb compiler plugin. You can enable this plugin by setting semanticdbEnabled := true in your build.sbt file.

Do not forget to reload sbt and click Connect to build server again.

BSP discovery

Since the .bsp/sbt.json file exists, Metals will always try to connect to sbt. This is not very convenient because it starts an sbt process in the background that you cannot interact with. I recommend to always start sbt in a shell before opening VS Code.

EDIT: The new sbtn thin client in sbt 1.4.0 makes it very easy to interact with the sbt server in the
background.

IntelliJ IDEA

The IntelliJ Scala plugin offers the ability to import a Scala project using BSP. Like Metals, it is used to relying on Bloop and that’s why it creates the Bloop configuration file.

In the following tutorial I use IntelliJ IDEA version 2020.1.2.

  1. Set sbt version to 1.4.0 in the project/build.properties file.
  2. Start the sbt shell.

Once sbt is loaded you should see a log saying that sbt server started. You can also check that a .bsp/sbt.json file has been created. This file contains the information that IntelliJ needs to connect to sbt. We are ready to go.

  1. We need to import the project from scratch, so remove the .idea folder.
  2. Open IntelliJ in the project folder (in Linux or Mac OS you can run idea . command) and choose BSP.
  3. Don’t bother if it creates the Bloop configuration files, it will then connect to sbt and not Bloop.

In the sbt shell you should see the requests that IntelliJ sent to extract the build structure. After that you are ready to start coding in IntelliJ.

You can improve the experience by customizing the BSP settings. Go to File > Settings > Build, Execution, Deployment > Build Tools > BSP. Uncheck export sbt projects to Bloop before import and check build automatically on file save.

On file save, IntelliJ will use sbt to compile the changes and it will report the compiler diagnostics sent back by sbt.

BSP discovery

Since the .bsp/sbt.json file exists, IntelliJ will always try to connect to sbt. This is not very convenient because it starts an sbt process in the background that you cannot interact with. I recommend to always start sbt in a shell before opening your IntelliJ project.

EDIT: The new sbtn thin client in sbt 1.4.0 makes it very easy to interact with the sbt server in the
background.

14 Likes