mirror of https://github.com/sbt/sbt.git
Refactor bspBuildTargetSources to be an input task + ScopeFilter
This commit is contained in:
parent
1ccff0ca6d
commit
10b2154d2e
|
|
@ -43,6 +43,7 @@ import sbt.internal.librarymanagement.mavenint.{
|
||||||
import sbt.internal.librarymanagement.{ CustomHttp => _, _ }
|
import sbt.internal.librarymanagement.{ CustomHttp => _, _ }
|
||||||
import sbt.internal.nio.{ CheckBuildSources, Globs }
|
import sbt.internal.nio.{ CheckBuildSources, Globs }
|
||||||
import sbt.internal.server.{
|
import sbt.internal.server.{
|
||||||
|
BuildServerProtocol,
|
||||||
Definition,
|
Definition,
|
||||||
LanguageServerProtocol,
|
LanguageServerProtocol,
|
||||||
LanguageServerReporter,
|
LanguageServerReporter,
|
||||||
|
|
@ -383,7 +384,9 @@ object Defaults extends BuildCommon {
|
||||||
sys.env.contains("CI") || SysProp.ci,
|
sys.env.contains("CI") || SysProp.ci,
|
||||||
// watch related settings
|
// watch related settings
|
||||||
pollInterval :== Watch.defaultPollInterval,
|
pollInterval :== Watch.defaultPollInterval,
|
||||||
) ++ LintUnused.lintSettings ++ DefaultBackgroundJobService.backgroundJobServiceSettings
|
) ++ BuildServerProtocol.globalSettings
|
||||||
|
++ LintUnused.lintSettings
|
||||||
|
++ DefaultBackgroundJobService.backgroundJobServiceSettings
|
||||||
)
|
)
|
||||||
|
|
||||||
def defaultTestTasks(key: Scoped): Seq[Setting[_]] =
|
def defaultTestTasks(key: Scoped): Seq[Setting[_]] =
|
||||||
|
|
@ -2219,7 +2222,7 @@ object Classpaths {
|
||||||
val stamper = (managedSourcePaths / outputFileStamper).value
|
val stamper = (managedSourcePaths / outputFileStamper).value
|
||||||
dependencyClasspathFiles.value.flatMap(p => cache.getOrElseUpdate(p, stamper).map(p -> _))
|
dependencyClasspathFiles.value.flatMap(p => cache.getOrElseUpdate(p, stamper).map(p -> _))
|
||||||
}
|
}
|
||||||
)
|
) ++ BuildServerProtocol.configSettings
|
||||||
|
|
||||||
private[this] def exportClasspath(s: Setting[Task[Classpath]]): Setting[Task[Classpath]] =
|
private[this] def exportClasspath(s: Setting[Task[Classpath]]): Setting[Task[Classpath]] =
|
||||||
s.mapInitialize(init => Def.task { exportClasspath(streams.value, init.value) })
|
s.mapInitialize(init => Def.task { exportClasspath(streams.value, init.value) })
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import sbt.Def.ScopedKey
|
||||||
import sbt.KeyRanks._
|
import sbt.KeyRanks._
|
||||||
import sbt.internal.InMemoryCacheStore.CacheStoreFactoryFactory
|
import sbt.internal.InMemoryCacheStore.CacheStoreFactoryFactory
|
||||||
import sbt.internal._
|
import sbt.internal._
|
||||||
|
import sbt.internal.bsp._
|
||||||
import sbt.internal.inc.ScalaInstance
|
import sbt.internal.inc.ScalaInstance
|
||||||
import sbt.internal.io.WatchState
|
import sbt.internal.io.WatchState
|
||||||
import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt }
|
import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt }
|
||||||
|
|
@ -337,6 +338,9 @@ object Keys {
|
||||||
val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on")
|
val internalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[String])]]("The project configurations that this configuration depends on")
|
||||||
val closeClassLoaders = settingKey[Boolean]("Close classloaders in run and test when the task completes.").withRank(DSetting)
|
val closeClassLoaders = settingKey[Boolean]("Close classloaders in run and test when the task completes.").withRank(DSetting)
|
||||||
val allowZombieClassLoaders = settingKey[Boolean]("Allow a classloader that has previously been closed by `run` or `test` to continue loading classes.")
|
val allowZombieClassLoaders = settingKey[Boolean]("Allow a classloader that has previously been closed by `run` or `test` to continue loading classes.")
|
||||||
|
val buildTargetIdentifier = settingKey[BuildTargetIdentifier]("Id for BSP build target.").withRank(DSetting)
|
||||||
|
val bspBuildTargetSources = inputKey[Unit]("").withRank(DTask)
|
||||||
|
val bspBuildTargetSourceItem = taskKey[SourcesItem]("").withRank(DTask)
|
||||||
|
|
||||||
val useCoursier = settingKey[Boolean]("Use Coursier for dependency resolution.").withRank(BSetting)
|
val useCoursier = settingKey[Boolean]("Use Coursier for dependency resolution.").withRank(BSetting)
|
||||||
val csrCacheDirectory = settingKey[File]("Coursier cache directory. Uses -Dsbt.coursier.home or Coursier's default.").withRank(CSetting)
|
val csrCacheDirectory = settingKey[File]("Coursier cache directory. Uses -Dsbt.coursier.home or Coursier's default.").withRank(CSetting)
|
||||||
|
|
|
||||||
|
|
@ -11,49 +11,69 @@ package server
|
||||||
|
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import sbt.internal.bsp._
|
import sbt.internal.bsp._
|
||||||
|
import sbt.internal.util.complete.DefaultParsers
|
||||||
import sbt.librarymanagement.{ Configuration, Configurations }
|
import sbt.librarymanagement.{ Configuration, Configurations }
|
||||||
import Configurations.{ Compile, Test }
|
import Configurations.{ Compile, Test }
|
||||||
import sbt.SlashSyntax0._
|
import sbt.SlashSyntax0._
|
||||||
import sbt.BuildSyntax._
|
import sbt.BuildSyntax._
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import sjsonnew.support.scalajson.unsafe.Converter
|
import sjsonnew.support.scalajson.unsafe.Converter
|
||||||
|
import Def._
|
||||||
|
import Keys._
|
||||||
|
import ScopeFilter.Make._
|
||||||
|
|
||||||
object BuildServerProtocol {
|
object BuildServerProtocol {
|
||||||
private[sbt] val idMap: mutable.Map[BuildTargetIdentifier, (ProjectRef, Configuration)] =
|
private[sbt] val idMap: mutable.Map[BuildTargetIdentifier, (ProjectRef, Configuration)] =
|
||||||
mutable.Map.empty
|
mutable.Map.empty
|
||||||
val BspBuildTargetSource = "bspBuildTargetSources"
|
|
||||||
|
|
||||||
def commands: List[Command] = List(bspBuildTargetSources)
|
def commands: List[Command] = List()
|
||||||
|
|
||||||
/**
|
lazy val globalSettings: Seq[Def.Setting[_]] = Seq(
|
||||||
* Command that expects list of URIs.
|
// https://github.com/build-server-protocol/build-server-protocol/blob/master/docs/specification.md#build-target-sources-request
|
||||||
* https://github.com/build-server-protocol/build-server-protocol/blob/master/docs/specification.md#build-target-sources-request
|
bspBuildTargetSources := (Def.inputTaskDyn {
|
||||||
*/
|
import DefaultParsers._
|
||||||
def bspBuildTargetSources: Command = Command.args(BspBuildTargetSource, "<args>") {
|
val s = state.value
|
||||||
(s0: State, args: Seq[String]) =>
|
val args: Seq[String] = spaceDelimited("<arg>").parsed
|
||||||
import sbt.internal.bsp.codec.JsonProtocol._
|
val filter = toScopeFilter(args)
|
||||||
var s: State = s0
|
// run bspBuildTargetSourceItem concurrently
|
||||||
val items = args map { arg =>
|
Def.task {
|
||||||
val id = BuildTargetIdentifier(new URI(arg))
|
import sbt.internal.bsp.codec.JsonProtocol._
|
||||||
val pair = idMap(id)
|
val items = bspBuildTargetSourceItem.all(filter).value
|
||||||
println(pair.toString)
|
val result = SourcesResult(items.toVector)
|
||||||
val dirs = s0.setting(pair._1 / pair._2 / Keys.unmanagedSourceDirectories)
|
s.respondEvent(result)
|
||||||
val (next, managed) = s.unsafeRunTask(pair._1 / pair._2 / Keys.managedSources)
|
|
||||||
s = next
|
|
||||||
val items = (dirs.toVector map { dir =>
|
|
||||||
SourceItem(dir.toURI, SourceItemKind.Directory, false)
|
|
||||||
}) ++
|
|
||||||
(managed.toVector map { x =>
|
|
||||||
SourceItem(x.toURI, SourceItemKind.File, true)
|
|
||||||
})
|
|
||||||
SourcesItem(id, items)
|
|
||||||
}
|
}
|
||||||
val result = SourcesResult(items.toVector)
|
}).evaluated
|
||||||
s0.respondEvent(result)
|
)
|
||||||
s
|
|
||||||
}
|
|
||||||
|
|
||||||
// def json(s: String): JValue = Parser.parseUnsafe(s)
|
// This will be coped to Compile, Test, etc
|
||||||
|
lazy val configSettings: Seq[Def.Setting[_]] = Seq(
|
||||||
|
buildTargetIdentifier := {
|
||||||
|
val ref = thisProjectRef.value
|
||||||
|
val c = configuration.value
|
||||||
|
toId(ref, c)
|
||||||
|
},
|
||||||
|
bspBuildTargetSourceItem := {
|
||||||
|
val id = buildTargetIdentifier.value
|
||||||
|
val dirs = unmanagedSourceDirectories.value
|
||||||
|
val managed = managedSources.value
|
||||||
|
val items = (dirs.toVector map { dir =>
|
||||||
|
SourceItem(dir.toURI, SourceItemKind.Directory, false)
|
||||||
|
}) ++
|
||||||
|
(managed.toVector map { x =>
|
||||||
|
SourceItem(x.toURI, SourceItemKind.File, true)
|
||||||
|
})
|
||||||
|
SourcesItem(id, items)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def toScopeFilter(args: Seq[String]): ScopeFilter = {
|
||||||
|
val filters = args map { arg =>
|
||||||
|
val id = BuildTargetIdentifier(new URI(arg))
|
||||||
|
val pair = idMap(id)
|
||||||
|
ScopeFilter(inProjects(pair._1), inConfigurations(pair._2))
|
||||||
|
}
|
||||||
|
filters.tail.foldLeft(filters.head) { _ || _ }
|
||||||
|
}
|
||||||
|
|
||||||
def toId(ref: ProjectReference, config: Configuration): BuildTargetIdentifier =
|
def toId(ref: ProjectReference, config: Configuration): BuildTargetIdentifier =
|
||||||
ref match {
|
ref match {
|
||||||
|
|
@ -61,25 +81,6 @@ object BuildServerProtocol {
|
||||||
BuildTargetIdentifier(new URI(s"$build#$project/${config.id}"))
|
BuildTargetIdentifier(new URI(s"$build#$project/${config.id}"))
|
||||||
case _ => sys.error(s"unexpected $ref")
|
case _ => sys.error(s"unexpected $ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
def idForConfig(
|
|
||||||
ref: ClasspathDep[ProjectRef],
|
|
||||||
from: Configuration
|
|
||||||
): Seq[BuildTargetIdentifier] = {
|
|
||||||
val configStr = ref.configuration.getOrElse("compile")
|
|
||||||
val configExprs0 = configStr.split(",").toList
|
|
||||||
val configExprs1 = configExprs0 map { expr =>
|
|
||||||
if (expr.contains("->")) {
|
|
||||||
val xs = expr.split("->")
|
|
||||||
(xs(0), xs(1))
|
|
||||||
} else ("compile", expr)
|
|
||||||
}
|
|
||||||
configExprs1 flatMap {
|
|
||||||
case (fr, "compile") if fr == from.name => Some(toId(ref.project, Compile))
|
|
||||||
case (fr, "test") if fr == from.name => Some(toId(ref.project, Test))
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is mixed into NetworkChannel
|
// This is mixed into NetworkChannel
|
||||||
|
|
@ -117,7 +118,7 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel =>
|
||||||
case (p, ref) =>
|
case (p, ref) =>
|
||||||
val baseOpt = getSetting(ref / Keys.baseDirectory).map(_.toURI)
|
val baseOpt = getSetting(ref / Keys.baseDirectory).map(_.toURI)
|
||||||
val internalCompileDeps = p.dependencies.flatMap(idForConfig(_, Compile)).toVector
|
val internalCompileDeps = p.dependencies.flatMap(idForConfig(_, Compile)).toVector
|
||||||
val compileId = toId(ref, Compile)
|
val compileId = getSetting(ref / Compile / Keys.buildTargetIdentifier).get
|
||||||
idMap(compileId) = (ref, Compile)
|
idMap(compileId) = (ref, Compile)
|
||||||
val compileData = ScalaBuildTarget(
|
val compileData = ScalaBuildTarget(
|
||||||
scalaOrganization = getSetting(ref / Compile / Keys.scalaOrganization).get,
|
scalaOrganization = getSetting(ref / Compile / Keys.scalaOrganization).get,
|
||||||
|
|
@ -136,7 +137,7 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel =>
|
||||||
dataKind = Some("scala"),
|
dataKind = Some("scala"),
|
||||||
data = Some(Converter.toJsonUnsafe(compileData)),
|
data = Some(Converter.toJsonUnsafe(compileData)),
|
||||||
)
|
)
|
||||||
val testId = toId(ref, Test)
|
val testId = getSetting(ref / Test / Keys.buildTargetIdentifier).get
|
||||||
idMap(testId) = (ref, Test)
|
idMap(testId) = (ref, Test)
|
||||||
// encode Test extending Compile
|
// encode Test extending Compile
|
||||||
val internalTestDeps =
|
val internalTestDeps =
|
||||||
|
|
@ -164,4 +165,25 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel =>
|
||||||
}
|
}
|
||||||
WorkspaceBuildTargetsResult(ts.toVector)
|
WorkspaceBuildTargetsResult(ts.toVector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def idForConfig(
|
||||||
|
ref: ClasspathDep[ProjectRef],
|
||||||
|
from: Configuration
|
||||||
|
): Seq[BuildTargetIdentifier] = {
|
||||||
|
val configStr = ref.configuration.getOrElse("compile")
|
||||||
|
val configExprs0 = configStr.split(",").toList
|
||||||
|
val configExprs1 = configExprs0 map { expr =>
|
||||||
|
if (expr.contains("->")) {
|
||||||
|
val xs = expr.split("->")
|
||||||
|
(xs(0), xs(1))
|
||||||
|
} else ("compile", expr)
|
||||||
|
}
|
||||||
|
configExprs1 flatMap {
|
||||||
|
case (fr, "compile") if fr == from.name =>
|
||||||
|
Some(getSetting(ref.project / Compile / Keys.buildTargetIdentifier).get)
|
||||||
|
case (fr, "test") if fr == from.name =>
|
||||||
|
Some(getSetting(ref.project / Test / Keys.buildTargetIdentifier).get)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ private[sbt] object LanguageServerProtocol {
|
||||||
val param = Converter.fromJson[SourcesParams](json(r)).get
|
val param = Converter.fromJson[SourcesParams](json(r)).get
|
||||||
appendExec(
|
appendExec(
|
||||||
Exec(
|
Exec(
|
||||||
s"""${BuildServerProtocol.BspBuildTargetSource} ${param.targets
|
s"""${Keys.bspBuildTargetSources.key} ${param.targets
|
||||||
.map(_.uri)
|
.map(_.uri)
|
||||||
.mkString(" ")}""",
|
.mkString(" ")}""",
|
||||||
Option(r.id),
|
Option(r.id),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue