Metals with Scala 3

Michał Bednarz
8 min readDec 17, 2020

--

At the end of 2020, the work on the upcoming release of Scala 3 is intensifying. This is the perfect time to get to know, explore, and eventually add Metals to your toolkit!

What is Metals?

If you are already familiar with Metals, you can proceed to Scala 3 project setup with Metals.

Regardless of whether you are a seasoned Scala developer or if you start your journey with this programming language just now, there is a great chance that you began with IntelliJ as your IDE. Through the Scala plugin, IntelliJ provides features that are very useful while working with Scala.

Though the most popular, IntelliJ comes with its disadvantages. It is heavyweight and it can be slow. Metals is the alternative that contains all the functionalities that you need to get the work done and at the same time, it is lightweight and fast. This is why we observe the increase in the number of Metals users in spite of the fact that this is a pretty recently created open-source project. Developers expect their IDE to make their workflow productive and seamless. Metals does this job perfectly.

Thanks to Metals we can have support for Scala in any popular text editor such as VS Code, Sublime Text, Vim, Emacs, and others, while the Scala plugin mentioned earlier is a tool dedicated exclusively to IntelliJ. What exactly allows Metals to so seamlessly integrate with a range of different text editors?

What tools are used by Metals under the hood?

The main driving force behind Metals is the Language Server Protocol (LSP) which allows handling language syntax and semantics independently of the editor presentation. Metals is a language server itself. Any editor that supports LSP is able to reuse the Metals language server to provide Scala support. Some editors can be further modified via extensions to provide an easier setup of the server. Metals, among others, has VS Code and Vim extensions.

Besides LSP, Metals also uses Build Server Protocol (BSP) which facilitates communication between build tools and IDEs. Thanks to the BSP client, which in this case is the Metals language server, editors can easily communicate with a BSP server to compile source code, run tests, etc. Check out this article if you want to learn more about BSP.

The main BSP server used by Metals is Bloop which is used to compile, test, and run Scala code. It can be easily integrated with different IDEs and build tools. Learn more about it here.

As you can already see, LSP and BSP are the tools that allow Metals to provide support for so many editors and build tools at once.

Metals Installation in VS Code

Though Metals can be used in a range of different text editors, Visual Studio Code is probably the most popular and provides the best beginner-friendly experience for users. Because of that, the examples are going to be coming from this editor. In VS Code you can get Metals like any other extension — install it via the VS Code marketplace. The exact installation tutorials for the editors, namely VS Code, Vim, Sublime Text, Emacs, and Eclipse can be found in the documentation.

Scala 3 project setup with Metals

The following instructions will explain how to set up a project from scratch. If you want to import the existing project, it can be done with Metals very easily as well. To do so, open the project directory. Then you will be prompted to import it. Do this and the project will be ready to work with!

Metals uses giter8 to provide a number of predefined templates that can be used to set up a new Scala project. One of them is a Scala 3 template. Let’s go through the process of creating a new project with Metals step by step.

First, open an empty workspace, select the Metals extension and press the New Scala project button. Alternatively, you can open the command palette with Ctrl+Shift+P (Cmd+Shift+P) and type Metals: New Scala project.

In a couple of seconds, after the Metals language server starts, the dropdown with all available project templates will appear. In this example, we are going to select the Scala 3 template. You will be prompted to select the directory that you want the project to be created in. By default, it shows you the parent of the current directory. The last thing you will need to do is to choose the name or use the default one suggested by Metals.

Now, we are able to start working on your new Scala 3 project. The only thing, that is needed to utilize all of the Metals features, is to import the build definition which you will be prompted to do in a popup window. In the case of a current project, the build is defined with sbt.

In a while, you will be able to run and develop code with Metals. Now open src/main/scala/Main.scala file. One of the first features that can be noticed is run | debug located above the main method, which will allow you to run your program by clicking on it.

The output of this simple program will be visible in the debug console.

Scala 3 version support

For now, Metals supports Scala 3 versions up to 3.0.0-M3 which will be released any time now. As you can see in the build definition below, the project from our example uses 3.0.0-M2. You can usually expect the support for a new version within the next day of the release.

Worksheets

Scala 3 comes with plenty of awesome features. Worksheets are a great tool that can be used to experiment because they let you quickly evaluate Scala expressions. The worksheet is a file with a format *.worksheet.sc. Create it by typing Metals: Create Worksheet in the command palette.

As a new feature, traits in Scala 3 now can have parameters. Paste the code below into the worksheet to try it out.

On save, the code within the worksheet will be instantly evaluated. As we can see the evaluated class field matches with the argument provided to the trait.

Language feature support

Editors are expected to provide a couple of functionalities which are necessary for developers in their day-to-day job. Let’s find out which of them work with Scala 3!

First of all, let’s create a new file called ColorEnum.scala alongside Main.scala. The file contains an example definition of an enum which is a new feature introduced in Scala 3.

Besides, in the main method, we can define three values representing enum cases.

Go to the symbol definition

This is a crucial functionality that lets you find the location in which a given symbol is defined. To use it in VS Code, move your mouse cursor over the symbol and press Ctrl (Cmd). Metals will provide a definition preview. Left-click on the symbol while still holding the key to proceed to the definition location. Alternatively, you can right-click on it and select Go to definition.

References

We already know how to navigate from the specific identifier to its definition. We can also utilize Metals to find all usages of a given class, method, or value. It can be accomplished in a similar way to the symbol definition navigation. Simply hold Ctrl (Cmd) and left-click on the definition identifier. Alternatively, you can right-click and pick Go to references. You will be provided with all the references that can be easily previewed and navigated to.

Rename

Scala 3 symbols can be already renamed as well! To rename the identifier, right-click on it and select Rename Symbol. All the references will be changed accordingly.

Completions

In most statically typed languages like Scala, editors can suggest the name of the symbol based on the context that we are in. This is also the case with Metals and Scala 3. Once you start typing the name of the enum case, you will be able to see all the possible names of fields and methods. Though right now in Metals, only basic completions work with Scala 3, we still have to wait for the implementation of advanced completions like for example exhaustive match/case which could be very useful with regard to enums.

As you can see, thanks to the features described earlier, working with Scala 3 is already possible in a pretty convenient way. Of course, there is a lot of work to do. What other features do we expect from Metals for Scala 3 in the near future? We can for sure expect advanced completions like for example auto imports of classes or exhaustive matches. In addition to that, we are still missing symbol outline, go to implementation, and code actions, which would be also good to have.

There is also one more feature which is not available only in the case of Scala 3 — go-to sources. It is available for other versions of Scala and for Java though. This feature is important for troubleshooting and certainly, we will want to have it in the future.

Summary

Fortunately, the work behind the support for Scala 3 in Metals is ahead of time for the Scala enthusiasts that are eager to experiment with the new features directly in their editor. Although a couple of important features are not yet supported, hopefully, they will be implemented even before the official release of Scala 3!

--

--