Scala Plugin
Scala Plugin for IntelliJ IDEA and Android Studio
New Module Layout for sbt Projects
Try out the enhanced sbt integration with IntelliJ Scala Plugin 2024.3
We’re introducing a new mode that better represents the structure of sbt projects in IntelliJ IDEA by organizing main and test sources into separate modules. The improved layout resolves several issues with compilation and highlighting. It also allows using different compiler options for main and test sources.
We strongly encourage you to try out this new functionality and share your feedback! Enable it via Settings | Build, Execution, Deployment | Build Tools | sbt and select Create separate modules for production and test sources.
Technical background
Each build tool has its own model to represent the project – this includes concepts of modules, dependencies, and much more.When the project is imported to IntelliJ IDEA, it is essential to translate this model into the IDE’s internal model, which may not perfectly align with the build tool’s structure.
Improperly mapping a given build tool’s model to IntelliJ IDEA’s model can lead to issues, such as code compiling when it shouldn’t (or vice versa) and incorrect highlighting.
A significant challenge when mapping the sbt model was the limited distinction between main and test sources. When managing dependencies between two modules, all sources from the dependent module were added to the parent module, making it impossible to include only the main sources. Another issue was configuring separate compiler options for main and test sources.
To address these issues, a new approach has been developed for mapping the sbt model to IntelliJ IDEA – creating separate modules for main and test sources.
How it works
For each project declared in the sbt build, two additional modules are created: main
and test
. They contain the main and test sources, respectively.
When the project is reloaded in the new mode, each run configuration that references a module should switch to the corresponding main or test module. This happens automatically when the new mode is activated. In very rare cases, it may not be possible to change the modules in the run configurations automatically. If this happens, a notification will appear, giving you the option to update the run configurations manually. If you miss the notification, you can still update the run configurations by explicitly using the Update Run Configurations to the new module naming scheme action.
Key improvements
These examples illustrate the most noticeable changes. However, enabling the new mode also allows for many other improvements, such as more accurate handling of transitive dependencies, support for compile->test
dependencies, and better management of -internal
configurations.
Different compiler options for Compile and Test scopes
sbt allows you to declare different compiler options in various configuration scopes. The new project model in IntelliJ IDEA now leverages this capability by recognizing compiler options declared in the Test
scope, allowing you to configure different options for Compile
and Test
scopes in the IDE.
For example, if you configure scalacOptions
in an sbt project like this:Test / scalacOptions += "-Ywarn-value-discard"
then warnings about discarded values will only be displayed in the test sources.
If you configure the options in the Compile scope like this:Compile / scalacOptions += "-Ywarn-value-discard"
then warnings can be displayed both in the main and test sources.
Compile scope project dependencies
Keeping main and test sources in separate modules allows for a more accurate representation of dependencies. This is particularly significant for classpath dependencies, which are always per-configuration in sbt.
Let’s consider a very common dependency example:core.dependsOn(foo)
which is always resolved to core.dependsOn(foo %”compile->compile”)
When separate modules for main and sources are created, this dependency resolves so that both core.main
and core.test
modules contain only the core.foo.main
dependency. None of the core modules has foo.test
in its dependencies, which is a proper sbt representation.
It’s worth mentioning that in the old implementation, the core module included the entire foo
module. This meant that core
test sources had access to foo
test sources.
How to enable this feature
As this feature is currently in Beta, it is not enabled by default. Enable it via Settings | Build, Execution, Deployment | Build Tools | sbt and select Create separate modules for production and test sources.
Feedback
We need your feedback! If you encounter any bugs in this feature, please report them to our YouTrack. If you have any questions, feel free to ask them on in our Discord.
Happy developing!
The IntelliJ Scala Plugin team