mirror of https://github.com/sbt/sbt.git
Merge pull request #6638 from hmemcpy/buildTarget/cleanCache
bsp: Implementing `buildTarget/cleanCache`
This commit is contained in:
commit
d197b5b77b
|
|
@ -402,7 +402,7 @@ object Keys {
|
|||
val bspTargetIdentifier = settingKey[BuildTargetIdentifier]("Build target identifier of a project and configuration.").withRank(DSetting)
|
||||
val bspWorkspace = settingKey[Map[BuildTargetIdentifier, Scope]]("Mapping of BSP build targets to sbt scopes").withRank(DSetting)
|
||||
private[sbt] val bspFullWorkspace = settingKey[BspFullWorkspace]("Mapping of BSP build targets to sbt scopes and meta-targets for the SBT build itself").withRank(DSetting)
|
||||
val bspInternalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[ConfigKey])]]("The project configurations that this configuration depends on, possibly transitivly").withRank(DSetting)
|
||||
val bspInternalDependencyConfigurations = settingKey[Seq[(ProjectRef, Set[ConfigKey])]]("The project configurations that this configuration depends on, possibly transitively").withRank(DSetting)
|
||||
val bspWorkspaceBuildTargets = taskKey[Seq[BuildTarget]]("List all the BSP build targets").withRank(DTask)
|
||||
val bspBuildTarget = taskKey[BuildTarget]("Description of the BSP build targets").withRank(DTask)
|
||||
val bspBuildTargetSources = inputKey[Unit]("").withRank(DTask)
|
||||
|
|
@ -415,6 +415,7 @@ object Keys {
|
|||
val bspBuildTargetCompileItem = taskKey[Int]("").withRank(DTask)
|
||||
val bspBuildTargetTest = inputKey[Unit]("Corresponds to buildTarget/test request").withRank(DTask)
|
||||
val bspBuildTargetRun = inputKey[Unit]("Corresponds to buildTarget/run request").withRank(DTask)
|
||||
val bspBuildTargetCleanCache = inputKey[Unit]("Corresponds to buildTarget/cleanCache request").withRank(DTask)
|
||||
val bspBuildTargetScalacOptions = inputKey[Unit]("").withRank(DTask)
|
||||
val bspBuildTargetScalacOptionsItem = taskKey[ScalacOptionsItem]("").withRank(DTask)
|
||||
val bspScalaTestClasses = inputKey[Unit]("Corresponds to buildTarget/scalaTestClasses request").withRank(DTask)
|
||||
|
|
|
|||
|
|
@ -186,6 +186,25 @@ object BuildServerProtocol {
|
|||
bspBuildTargetCompile / aggregate := false,
|
||||
bspBuildTargetTest := bspTestTask.evaluated,
|
||||
bspBuildTargetTest / aggregate := false,
|
||||
bspBuildTargetCleanCache := Def.inputTaskDyn {
|
||||
val s: State = state.value
|
||||
val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
||||
val workspace = bspFullWorkspace.value.filter(targets)
|
||||
workspace.warnIfBuildsNonEmpty(Method.CleanCache, s.log)
|
||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||
Def.task {
|
||||
val results = Keys.clean.result.all(filter).value
|
||||
val successes = anyOrThrow(results).size
|
||||
|
||||
// When asking to Rebuild Project, IntelliJ sends the root build as an additional target, however it is
|
||||
// not returned as part of the results. In this case, there's 1 build entry in the workspace, and we're
|
||||
// checking that the executed results plus this entry is equal to the total number of targets.
|
||||
// When rebuilding a single module, the root build isn't sent, just the requested targets.
|
||||
val cleaned = successes + workspace.builds.size == targets.size
|
||||
s.respondEvent(CleanCacheResult(None, cleaned))
|
||||
}
|
||||
}.evaluated,
|
||||
bspBuildTargetCleanCache / aggregate := false,
|
||||
bspBuildTargetScalacOptions := Def.inputTaskDyn {
|
||||
val s = state.value
|
||||
|
||||
|
|
@ -310,6 +329,7 @@ object BuildServerProtocol {
|
|||
final val Compile = "buildTarget/compile"
|
||||
final val Test = "buildTarget/test"
|
||||
final val Run = "buildTarget/run"
|
||||
final val CleanCache = "buildTarget/cleanCache"
|
||||
final val ScalacOptions = "buildTarget/scalacOptions"
|
||||
final val ScalaTestClasses = "buildTarget/scalaTestClasses"
|
||||
final val ScalaMainClasses = "buildTarget/scalaMainClasses"
|
||||
|
|
@ -397,6 +417,12 @@ object BuildServerProtocol {
|
|||
Some(r.id)
|
||||
)
|
||||
|
||||
case r if r.method == Method.CleanCache =>
|
||||
val param = Converter.fromJson[CleanCacheParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
val command = Keys.bspBuildTargetCleanCache.key
|
||||
val _ = callback.appendExec(s"$command $targets", Some(r.id))
|
||||
|
||||
case r if r.method == Method.ScalacOptions =>
|
||||
val param = Converter.fromJson[ScalacOptionsParams](json(r)).get
|
||||
val targets = param.targets.map(_.uri).mkString(" ")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
/**
|
||||
* Clean Cache Request
|
||||
* @param targets A sequence of build targets to clean
|
||||
*/
|
||||
final class CleanCacheParams private (
|
||||
val targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: CleanCacheParams => (this.targets == x.targets)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + "sbt.internal.bsp.CleanCacheParams".##) + targets.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"CleanCacheParams(" + targets + ")"
|
||||
}
|
||||
private[this] def copy(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier] = targets): CleanCacheParams = {
|
||||
new CleanCacheParams(targets)
|
||||
}
|
||||
def withTargets(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): CleanCacheParams = {
|
||||
copy(targets = targets)
|
||||
}
|
||||
}
|
||||
object CleanCacheParams {
|
||||
|
||||
def apply(targets: Vector[sbt.internal.bsp.BuildTargetIdentifier]): CleanCacheParams = new CleanCacheParams(targets)
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp
|
||||
/**
|
||||
* Clean Cache Response
|
||||
* @param message Optional message to display to the user
|
||||
* @param cleaned Indicates whether the clean cache request was performed or not
|
||||
*/
|
||||
final class CleanCacheResult private (
|
||||
val message: Option[String],
|
||||
val cleaned: Boolean) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: CleanCacheResult => (this.message == x.message) && (this.cleaned == x.cleaned)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.bsp.CleanCacheResult".##) + message.##) + cleaned.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"CleanCacheResult(" + message + ", " + cleaned + ")"
|
||||
}
|
||||
private[this] def copy(message: Option[String] = message, cleaned: Boolean = cleaned): CleanCacheResult = {
|
||||
new CleanCacheResult(message, cleaned)
|
||||
}
|
||||
def withMessage(message: Option[String]): CleanCacheResult = {
|
||||
copy(message = message)
|
||||
}
|
||||
def withMessage(message: String): CleanCacheResult = {
|
||||
copy(message = Option(message))
|
||||
}
|
||||
def withCleaned(cleaned: Boolean): CleanCacheResult = {
|
||||
copy(cleaned = cleaned)
|
||||
}
|
||||
}
|
||||
object CleanCacheResult {
|
||||
|
||||
def apply(message: Option[String], cleaned: Boolean): CleanCacheResult = new CleanCacheResult(message, cleaned)
|
||||
def apply(message: String, cleaned: Boolean): CleanCacheResult = new CleanCacheResult(Option(message), cleaned)
|
||||
}
|
||||
27
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/CleanCacheParamsFormats.scala
generated
Normal file
27
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/CleanCacheParamsFormats.scala
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait CleanCacheParamsFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val CleanCacheParamsFormat: JsonFormat[sbt.internal.bsp.CleanCacheParams] = new JsonFormat[sbt.internal.bsp.CleanCacheParams] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.CleanCacheParams = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val targets = unbuilder.readField[Vector[sbt.internal.bsp.BuildTargetIdentifier]]("targets")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.CleanCacheParams(targets)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.CleanCacheParams, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("targets", obj.targets)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
29
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/CleanCacheResultFormats.scala
generated
Normal file
29
protocol/src/main/contraband-scala/sbt/internal/bsp/codec/CleanCacheResultFormats.scala
generated
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.bsp.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait CleanCacheResultFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val CleanCacheResultFormat: JsonFormat[sbt.internal.bsp.CleanCacheResult] = new JsonFormat[sbt.internal.bsp.CleanCacheResult] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.CleanCacheResult = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val message = unbuilder.readField[Option[String]]("message")
|
||||
val cleaned = unbuilder.readField[Boolean]("cleaned")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.bsp.CleanCacheResult(message, cleaned)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.bsp.CleanCacheResult, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("message", obj.message)
|
||||
builder.addField("cleaned", obj.cleaned)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,8 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
|||
with sbt.internal.bsp.codec.TaskFinishParamsFormats
|
||||
with sbt.internal.bsp.codec.CompileParamsFormats
|
||||
with sbt.internal.bsp.codec.BspCompileResultFormats
|
||||
with sbt.internal.bsp.codec.CleanCacheParamsFormats
|
||||
with sbt.internal.bsp.codec.CleanCacheResultFormats
|
||||
with sbt.internal.bsp.codec.CompileTaskFormats
|
||||
with sbt.internal.bsp.codec.CompileReportFormats
|
||||
with sbt.internal.bsp.codec.TestParamsFormats
|
||||
|
|
|
|||
|
|
@ -368,6 +368,21 @@ type BspCompileResult {
|
|||
# data: any
|
||||
}
|
||||
|
||||
## Clean Cache Request
|
||||
type CleanCacheParams {
|
||||
## A sequence of build targets to clean
|
||||
targets: [sbt.internal.bsp.BuildTargetIdentifier]
|
||||
}
|
||||
|
||||
## Clean Cache Response
|
||||
type CleanCacheResult {
|
||||
## Optional message to display to the user
|
||||
message: String
|
||||
|
||||
## Indicates whether the clean cache request was performed or not
|
||||
cleaned: Boolean!
|
||||
}
|
||||
|
||||
## Compile Notifications
|
||||
|
||||
type CompileTask {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
|
||||
package testpkg
|
||||
|
||||
import sbt.internal.bsp.{ BspCompileResult, SourcesResult, StatusCode, WorkspaceBuildTargetsResult }
|
||||
import sbt.internal.bsp._
|
||||
import sbt.internal.langserver.ErrorCodes
|
||||
import sbt.IO
|
||||
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
import scala.concurrent.duration._
|
||||
|
||||
// starts svr using server-test/buildserver and perform custom server tests
|
||||
|
|
@ -108,6 +109,55 @@ object BuildServerTest extends AbstractServerTest {
|
|||
})
|
||||
}
|
||||
|
||||
test("buildTarget/cleanCache") { _ =>
|
||||
def targetDir =
|
||||
Paths
|
||||
.get(
|
||||
svr.baseDirectory.getAbsoluteFile.toString,
|
||||
"run-and-test/target/scala-2.13/classes/main"
|
||||
)
|
||||
.toFile
|
||||
|
||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||
svr.sendJsonRpc(
|
||||
s"""{ "jsonrpc": "2.0", "id": "43", "method": "buildTarget/compile", "params": {
|
||||
| "targets": [{ "uri": "$buildTarget" }]
|
||||
|} }""".stripMargin
|
||||
)
|
||||
svr.waitFor[BspCompileResult](10.seconds)
|
||||
assert(targetDir.list().contains("Main.class"))
|
||||
|
||||
svr.sendJsonRpc(
|
||||
s"""{ "jsonrpc": "2.0", "id": "44", "method": "buildTarget/cleanCache", "params": {
|
||||
| "targets": [{ "uri": "$buildTarget" }]
|
||||
|} }""".stripMargin
|
||||
)
|
||||
assert(processing("buildTarget/cleanCache"))
|
||||
val res = svr.waitFor[CleanCacheResult](10.seconds)
|
||||
assert(res.cleaned)
|
||||
assert(targetDir.list().isEmpty)
|
||||
}
|
||||
|
||||
test("buildTarget/cleanCache: rebuild project") { _ =>
|
||||
svr.sendJsonRpc(
|
||||
"""{ "jsonrpc": "2.0", "id": "45", "method": "workspace/buildTargets", "params": {} }"""
|
||||
)
|
||||
assert(processing("workspace/buildTargets"))
|
||||
val result = svr.waitFor[WorkspaceBuildTargetsResult](10.seconds)
|
||||
val allTargets = result.targets.map(_.id.uri)
|
||||
|
||||
svr.sendJsonRpc(
|
||||
s"""{ "jsonrpc": "2.0", "id": "46", "method": "buildTarget/cleanCache", "params": {
|
||||
| "targets": [
|
||||
| ${allTargets.map(uri => s"""{ "uri": "$uri" }""").mkString(",\n")}
|
||||
| ]
|
||||
|} }""".stripMargin
|
||||
)
|
||||
assert(processing("buildTarget/cleanCache"))
|
||||
val res = svr.waitFor[CleanCacheResult](10.seconds)
|
||||
assert(res.cleaned)
|
||||
}
|
||||
|
||||
test("workspace/reload") { _ =>
|
||||
svr.sendJsonRpc(
|
||||
"""{ "jsonrpc": "2.0", "id": "48", "method": "workspace/reload"}"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue