better support of custom configurations in SemanticdbPlugin

Second take at https://github.com/sbt/sbt/issues/5886, which fixed the
problem for Test specifically but not for custom configurations.

* Any child of Compile (like Custom in the scripted) had to use
  testSettings, whether they were related to testing or not
* Custom configurations with grand parents (like SystemTest in the
  scripted) would get duplicated scalacOptions no matter what they used
This commit is contained in:
Brice Jaglin 2021-02-06 21:26:16 +01:00
parent 0a6e5c3116
commit 145966e3f3
8 changed files with 79 additions and 14 deletions

View File

@ -13,10 +13,10 @@ import java.io.File
import Keys._
import sbt.internal.SysProp
import sbt.librarymanagement.syntax._
import sbt.librarymanagement.CrossVersion
import sbt.librarymanagement.{ Configuration, CrossVersion }
import Project.inConfig
import sbt.internal.inc.ScalaInstance
import sbt.SlashSyntax0._
import sbt.ScopeFilter.Make._
object SemanticdbPlugin extends AutoPlugin {
override def requires = JvmPlugin
@ -50,7 +50,7 @@ object SemanticdbPlugin extends AutoPlugin {
}
) ++
inConfig(Compile)(configurationSettings) ++
inConfig(Test)(configurationSettings ++ testSettings)
inConfig(Test)(configurationSettings)
lazy val configurationSettings: Seq[Def.Setting[_]] = List(
semanticdbTargetRoot := {
@ -58,8 +58,22 @@ object SemanticdbPlugin extends AutoPlugin {
if (in) classDirectory.value
else semanticdbTargetRoot.value
},
semanticdbOptions --= Def.settingDyn {
val scalaV = scalaVersion.value
val config = configuration.value
Def.setting {
semanticdbTargetRoot.?.all(ancestorConfigs(config)).value.flatten
.flatMap(targetRootOptions(scalaV, _))
}
}.value,
semanticdbOptions ++=
targetRootOptions(scalaVersion.value, semanticdbTargetRoot.value),
scalacOptions --= Def.settingDyn {
val config = configuration.value
Def.setting {
semanticdbOptions.?.all(ancestorConfigs(config)).value.flatten.flatten
}
}.value,
scalacOptions ++= {
if (semanticdbEnabled.value)
semanticdbOptions.value
@ -67,15 +81,8 @@ object SemanticdbPlugin extends AutoPlugin {
}
)
lazy val testSettings: Seq[Def.Setting[_]] = List(
// remove Compile targetRoot from Test config
semanticdbOptions --= targetRootOptions(
(Compile / scalaVersion).value,
(Compile / semanticdbTargetRoot).value
),
// remove duplicated semanticdbOptions
scalacOptions --= (Compile / semanticdbOptions).value
)
@deprecated("use configurationSettings only", "1.5.0")
lazy val testSettings: Seq[Def.Setting[_]] = List()
def targetRootOptions(scalaVersion: String, targetRoot: File): Seq[String] = {
if (ScalaInstance.isDotty(scalaVersion)) {
@ -84,4 +91,11 @@ object SemanticdbPlugin extends AutoPlugin {
Seq(s"-P:semanticdb:targetroot:$targetRoot")
}
}
private def ancestorConfigs(config: Configuration) = {
def ancestors(configs: Vector[Configuration]): Vector[Configuration] =
configs ++ configs.flatMap(conf => ancestors(conf.extendsConfigs))
ScopeFilter(configurations = inConfigurations(ancestors(config.extendsConfigs): _*))
}
}

View File

@ -2,4 +2,29 @@ ThisBuild / scalaVersion := "2.12.12"
ThisBuild / semanticdbEnabled := true
ThisBuild / semanticdbIncludeInJar := true
// see https://github.com/sbt/sbt/issues/5886
lazy val check = taskKey[Unit]("Checks that scalacOptions have the same number of parameters across configurations")
lazy val anyConfigInThisProject = ScopeFilter(configurations = inAnyConfiguration)
lazy val Custom = config("custom").extend(Compile)
lazy val SystemTest = config("st").extend(IntegrationTest)
lazy val root = (project in file("."))
.configs(IntegrationTest, Custom, SystemTest)
.settings(
inConfig(IntegrationTest)(Defaults.testSettings ++ sbt.plugins.SemanticdbPlugin.configurationSettings),
inConfig(Custom)(Defaults.configSettings ++ sbt.plugins.SemanticdbPlugin.configurationSettings),
inConfig(SystemTest)(Defaults.testSettings ++ sbt.plugins.SemanticdbPlugin.configurationSettings),
check := {
val scalacOptionsCountsAcrossConfigs = scalacOptions.?.all(anyConfigInThisProject)
.value
.map(_.toSeq.flatten.size)
.filterNot(_ == 0)
.distinct
assert(
scalacOptionsCountsAcrossConfigs.size == 1,
s"Configurations expected to have the same number of scalacOptions but found different numbers: $scalacOptionsCountsAcrossConfigs"
)
}
)

View File

@ -0,0 +1,3 @@
package foo
object Custom

View File

@ -0,0 +1,3 @@
package foo
object IntegrationTest

View File

@ -1,6 +1,6 @@
package foo
object Test {
object Compile {
def main(args: Array[String]): Unit = {
println("hello world")
}

View File

@ -0,0 +1,3 @@
package foo
object SystemTest

View File

@ -0,0 +1,3 @@
package foo
object Test

View File

@ -1,2 +1,16 @@
> compile
$ exists target/scala-2.12/classes/META-INF/semanticdb/src/main/scala/foo/Test.scala.semanticdb
$ exists target/scala-2.12/classes/META-INF/semanticdb/src/main/scala/foo/Compile.scala.semanticdb
> test:compile
$ exists target/scala-2.12/test-classes/META-INF/semanticdb/src/test/scala/foo/Test.scala.semanticdb
> it:compile
$ exists target/scala-2.12/it-classes/META-INF/semanticdb/src/it/scala/foo/IntegrationTest.scala.semanticdb
> custom:compile
$ exists target/scala-2.12/custom-classes/META-INF/semanticdb/src/custom/scala/foo/Custom.scala.semanticdb
> st:compile
$ exists target/scala-2.12/st-classes/META-INF/semanticdb/src/st/scala/foo/SystemTest.scala.semanticdb
> check