Search code examples
scalaintellij-ideasbtintellij-scala

Intellij SBT project: How to change the content roots?


This is the current content root configuration in my project:

current configuration

However, I want the "scala" directory to be the actual test content root, and not the directory named "test". If I modify it, I get the warning that "Module is imported from Sbt. Any changes in its configuration will may be lost after re-importing." (and, indeed, they are).

enter image description here

Unfortunately, I couldn't find where in my Build.scala file (or any other file) this configuration is declared. What I can do to once and for all convince IntelliJ that "scala" is the correct test content root?

This is my Build.scala file (this is a Play 2.5.4 project if it matters):

import play.routes.compiler.StaticRoutesGenerator
import play.sbt.PlayScala
import play.sbt.routes.RoutesKeys._
import sbt.Keys._
import sbt._

object Build extends Build {
  val main = Project("Mp3Streamer", file(".")).enablePlugins(PlayScala).settings(
    scalaVersion := "2.11.8",
    version := "1.0-SNAPSHOT",
    addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full),
    libraryDependencies ++= Seq(
      // a bunch of dependencies
    ),

    resolvers += Resolver.mavenLocal,
    javaOptions ++= Seq("-Xmx4000M", "-Xms2024M", "-XX:MaxPermSize=2000M"),
    routesGenerator := StaticRoutesGenerator
  )
}

Solution

  • By adding scalaSource in Test := baseDirectory.value / "test" "/scala", to my Build.scala file, I've been able to make the "scala" folder a test source, but the parent "test" folder was still also a test source:

    enter image description here

    As far as I could tell, this is a setting inherited from Play, since if I removed the .enablePlugins(PlayScala) code, the "test" folder stops being a test source. Following the instructions in https://www.playframework.com/documentation/2.5.x/Anatomy#Default-SBT-layout, I disabled the play layout, and then manually added the source and resource directories, which I copied from https://github.com/playframework/playframework/blob/master/framework/src/sbt-plugin/src/main/scala/play/sbt/PlayLayoutPlugin.scala#L9, only modifying the test source, and adding my own resource folders. My modified Build.scala file is now:

    val main = Project("Mp3Streamer", file("."))
          .enablePlugins(PlayScala)
          .disablePlugins(PlayLayoutPlugin)
          .settings(
               target := baseDirectory.value / "target",
    
               sourceDirectory in Compile := baseDirectory.value / "app",
               // My change
               sourceDirectory in Test := baseDirectory.value / "test" / "scala",
    
               resourceDirectory in Compile := baseDirectory.value / "conf",
    
               scalaSource in Compile := baseDirectory.value / "app",
               // My change
               scalaSource in Test := baseDirectory.value / "test" / "scala",
               // I've added this resource
               resourceDirectory in Test := baseDirectory.value / "test" / "resources",
    
               javaSource in Compile := baseDirectory.value / "app",
    
               sourceDirectories in(Compile, TwirlKeys.compileTemplates) := Seq((sourceDirectory in Compile).value),
               sourceDirectories in(Test, TwirlKeys.compileTemplates) := Seq((sourceDirectory in Test).value),
    
               // sbt-web
               sourceDirectory in Assets := (sourceDirectory in Compile).value / "assets",
               sourceDirectory in TestAssets := (sourceDirectory in Test).value / "assets",
    
    
               resourceDirectory in Assets := baseDirectory.value / "public",
    
               // Native packager
               sourceDirectory in Universal := baseDirectory.value / "dist",
    
               // Everything else is the same as the original Build.scala file
    

    Honestly, this feels so hacky that I'll probably end up modifying my directory structure to match Play's default... But it's the principle that counts!