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.nio.{ CheckBuildSources, Globs }
|
||||
import sbt.internal.server.{
|
||||
BuildServerProtocol,
|
||||
Definition,
|
||||
LanguageServerProtocol,
|
||||
LanguageServerReporter,
|
||||
|
|
@ -383,7 +384,9 @@ object Defaults extends BuildCommon {
|
|||
sys.env.contains("CI") || SysProp.ci,
|
||||
// watch related settings
|
||||
pollInterval :== Watch.defaultPollInterval,
|
||||
) ++ LintUnused.lintSettings ++ DefaultBackgroundJobService.backgroundJobServiceSettings
|
||||
) ++ BuildServerProtocol.globalSettings
|
||||
++ LintUnused.lintSettings
|
||||
++ DefaultBackgroundJobService.backgroundJobServiceSettings
|
||||
)
|
||||
|
||||
def defaultTestTasks(key: Scoped): Seq[Setting[_]] =
|
||||
|
|
@ -2219,7 +2222,7 @@ object Classpaths {
|
|||
val stamper = (managedSourcePaths / outputFileStamper).value
|
||||
dependencyClasspathFiles.value.flatMap(p => cache.getOrElseUpdate(p, stamper).map(p -> _))
|
||||
}
|
||||
)
|
||||
) ++ BuildServerProtocol.configSettings
|
||||
|
||||
private[this] def exportClasspath(s: Setting[Task[Classpath]]): Setting[Task[Classpath]] =
|
||||
s.mapInitialize(init => Def.task { exportClasspath(streams.value, init.value) })
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import sbt.Def.ScopedKey
|
|||
import sbt.KeyRanks._
|
||||
import sbt.internal.InMemoryCacheStore.CacheStoreFactoryFactory
|
||||
import sbt.internal._
|
||||
import sbt.internal.bsp._
|
||||
import sbt.internal.inc.ScalaInstance
|
||||
import sbt.internal.io.WatchState
|
||||
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 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 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 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 sbt.internal.bsp._
|
||||
import sbt.internal.util.complete.DefaultParsers
|
||||
import sbt.librarymanagement.{ Configuration, Configurations }
|
||||
import Configurations.{ Compile, Test }
|
||||
import sbt.SlashSyntax0._
|
||||
import sbt.BuildSyntax._
|
||||
import scala.collection.mutable
|
||||
import sjsonnew.support.scalajson.unsafe.Converter
|
||||
import Def._
|
||||
import Keys._
|
||||
import ScopeFilter.Make._
|
||||
|
||||
object BuildServerProtocol {
|
||||
private[sbt] val idMap: mutable.Map[BuildTargetIdentifier, (ProjectRef, Configuration)] =
|
||||
mutable.Map.empty
|
||||
val BspBuildTargetSource = "bspBuildTargetSources"
|
||||
|
||||
def commands: List[Command] = List(bspBuildTargetSources)
|
||||
def commands: List[Command] = List()
|
||||
|
||||
/**
|
||||
* Command that expects list of URIs.
|
||||
* https://github.com/build-server-protocol/build-server-protocol/blob/master/docs/specification.md#build-target-sources-request
|
||||
*/
|
||||
def bspBuildTargetSources: Command = Command.args(BspBuildTargetSource, "<args>") {
|
||||
(s0: State, args: Seq[String]) =>
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
var s: State = s0
|
||||
val items = args map { arg =>
|
||||
val id = BuildTargetIdentifier(new URI(arg))
|
||||
val pair = idMap(id)
|
||||
println(pair.toString)
|
||||
val dirs = s0.setting(pair._1 / pair._2 / Keys.unmanagedSourceDirectories)
|
||||
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)
|
||||
lazy val globalSettings: Seq[Def.Setting[_]] = Seq(
|
||||
// https://github.com/build-server-protocol/build-server-protocol/blob/master/docs/specification.md#build-target-sources-request
|
||||
bspBuildTargetSources := (Def.inputTaskDyn {
|
||||
import DefaultParsers._
|
||||
val s = state.value
|
||||
val args: Seq[String] = spaceDelimited("<arg>").parsed
|
||||
val filter = toScopeFilter(args)
|
||||
// run bspBuildTargetSourceItem concurrently
|
||||
Def.task {
|
||||
import sbt.internal.bsp.codec.JsonProtocol._
|
||||
val items = bspBuildTargetSourceItem.all(filter).value
|
||||
val result = SourcesResult(items.toVector)
|
||||
s.respondEvent(result)
|
||||
}
|
||||
val result = SourcesResult(items.toVector)
|
||||
s0.respondEvent(result)
|
||||
s
|
||||
}
|
||||
}).evaluated
|
||||
)
|
||||
|
||||
// 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 =
|
||||
ref match {
|
||||
|
|
@ -61,25 +81,6 @@ object BuildServerProtocol {
|
|||
BuildTargetIdentifier(new URI(s"$build#$project/${config.id}"))
|
||||
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
|
||||
|
|
@ -117,7 +118,7 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel =>
|
|||
case (p, ref) =>
|
||||
val baseOpt = getSetting(ref / Keys.baseDirectory).map(_.toURI)
|
||||
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)
|
||||
val compileData = ScalaBuildTarget(
|
||||
scalaOrganization = getSetting(ref / Compile / Keys.scalaOrganization).get,
|
||||
|
|
@ -136,7 +137,7 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel =>
|
|||
dataKind = Some("scala"),
|
||||
data = Some(Converter.toJsonUnsafe(compileData)),
|
||||
)
|
||||
val testId = toId(ref, Test)
|
||||
val testId = getSetting(ref / Test / Keys.buildTargetIdentifier).get
|
||||
idMap(testId) = (ref, Test)
|
||||
// encode Test extending Compile
|
||||
val internalTestDeps =
|
||||
|
|
@ -164,4 +165,25 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel =>
|
|||
}
|
||||
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
|
||||
appendExec(
|
||||
Exec(
|
||||
s"""${BuildServerProtocol.BspBuildTargetSource} ${param.targets
|
||||
s"""${Keys.bspBuildTargetSources.key} ${param.targets
|
||||
.map(_.uri)
|
||||
.mkString(" ")}""",
|
||||
Option(r.id),
|
||||
|
|
|
|||
Loading…
Reference in New Issue