mirror of https://github.com/sbt/sbt.git
Fix BuildServerTest
This commit is contained in:
parent
924150851c
commit
03ca5365f5
|
|
@ -152,7 +152,7 @@ object Command {
|
||||||
def combine(cmds: Seq[Command]): State => Parser[() => State] = {
|
def combine(cmds: Seq[Command]): State => Parser[() => State] = {
|
||||||
val (simple, arbs) = separateCommands(cmds)
|
val (simple, arbs) = separateCommands(cmds)
|
||||||
state =>
|
state =>
|
||||||
arbs.map(_ parser state).foldLeft(simpleParser(simple)(state))(_ | _)
|
arbs.map(_.parser(state)).foldLeft(simpleParser(simple)(state))(_ | _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[this] def separateCommands(
|
private[this] def separateCommands(
|
||||||
|
|
@ -188,7 +188,7 @@ object Command {
|
||||||
else parse(command, state.nonMultiParser)) match {
|
else parse(command, state.nonMultiParser)) match {
|
||||||
case Right(s) => s() // apply command. command side effects happen here
|
case Right(s) => s() // apply command. command side effects happen here
|
||||||
case Left(errMsg) =>
|
case Left(errMsg) =>
|
||||||
state.log error errMsg
|
state.log.error(errMsg)
|
||||||
state.fail
|
state.fail
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,11 @@ import sbt.internal.inc.{
|
||||||
MixedAnalyzingCompiler,
|
MixedAnalyzingCompiler,
|
||||||
ScalaInstance
|
ScalaInstance
|
||||||
}
|
}
|
||||||
import xsbti.{ CrossValue, HashedVirtualFileRef, VirtualFile, VirtualFileRef }
|
import sbt.internal.io.Retry
|
||||||
|
import xsbti.{ CompileFailed, CrossValue, HashedVirtualFileRef, VirtualFile, VirtualFileRef }
|
||||||
import xsbti.compile.{
|
import xsbti.compile.{
|
||||||
AnalysisContents,
|
AnalysisContents,
|
||||||
|
AnalysisStore,
|
||||||
ClassFileManagerType,
|
ClassFileManagerType,
|
||||||
ClasspathOptionsUtil,
|
ClasspathOptionsUtil,
|
||||||
CompileAnalysis,
|
CompileAnalysis,
|
||||||
|
|
@ -2393,11 +2395,10 @@ object Defaults extends BuildCommon {
|
||||||
*/
|
*/
|
||||||
private[sbt] def compileScalaBackendTask: Initialize[Task[CompileResult]] = Def.task {
|
private[sbt] def compileScalaBackendTask: Initialize[Task[CompileResult]] = Def.task {
|
||||||
val setup: Setup = compileIncSetup.value
|
val setup: Setup = compileIncSetup.value
|
||||||
val useBinary: Boolean = enableBinaryCompileAnalysis.value
|
|
||||||
val _ = compileIncremental.value
|
val _ = compileIncremental.value
|
||||||
val exportP = exportPipelining.value
|
val exportP = exportPipelining.value
|
||||||
// Save analysis midway if pipelining is enabled
|
// Save analysis midway if pipelining is enabled
|
||||||
val store = MixedAnalyzingCompiler.staticCachedStore(setup.cachePath, !useBinary)
|
val store = analysisStore
|
||||||
val contents = store.unsafeGet()
|
val contents = store.unsafeGet()
|
||||||
if (exportP) {
|
if (exportP) {
|
||||||
// this stores the eary analysis (again) in case the subproject contains a macro
|
// this stores the eary analysis (again) in case the subproject contains a macro
|
||||||
|
|
@ -2422,9 +2423,7 @@ object Defaults extends BuildCommon {
|
||||||
.debug(s"${name.value}: compileEarly: blocking on earlyOutputPing")
|
.debug(s"${name.value}: compileEarly: blocking on earlyOutputPing")
|
||||||
earlyOutputPing.await.value
|
earlyOutputPing.await.value
|
||||||
}) {
|
}) {
|
||||||
val useBinary: Boolean = enableBinaryCompileAnalysis.value
|
val store = earlyAnalysisStore
|
||||||
val store =
|
|
||||||
MixedAnalyzingCompiler.staticCachedStore(earlyCompileAnalysisFile.value.toPath, !useBinary)
|
|
||||||
store.get.toOption match {
|
store.get.toOption match {
|
||||||
case Some(contents) => contents.getAnalysis
|
case Some(contents) => contents.getAnalysis
|
||||||
case _ => Analysis.empty
|
case _ => Analysis.empty
|
||||||
|
|
@ -2436,13 +2435,11 @@ object Defaults extends BuildCommon {
|
||||||
|
|
||||||
def compileTask: Initialize[Task[CompileAnalysis]] = Def.task {
|
def compileTask: Initialize[Task[CompileAnalysis]] = Def.task {
|
||||||
val setup: Setup = compileIncSetup.value
|
val setup: Setup = compileIncSetup.value
|
||||||
val useBinary: Boolean = enableBinaryCompileAnalysis.value
|
val store = analysisStore
|
||||||
val c = fileConverter.value
|
val c = fileConverter.value
|
||||||
// TODO - expose bytecode manipulation phase.
|
// TODO - expose bytecode manipulation phase.
|
||||||
val analysisResult: CompileResult = manipulateBytecode.value
|
val analysisResult: CompileResult = manipulateBytecode.value
|
||||||
if (analysisResult.hasModified) {
|
if (analysisResult.hasModified) {
|
||||||
val store =
|
|
||||||
MixedAnalyzingCompiler.staticCachedStore(setup.cacheFile.toPath, !useBinary)
|
|
||||||
val contents = AnalysisContents.create(analysisResult.analysis(), analysisResult.setup())
|
val contents = AnalysisContents.create(analysisResult.analysis(), analysisResult.setup())
|
||||||
store.set(contents)
|
store.set(contents)
|
||||||
}
|
}
|
||||||
|
|
@ -2455,73 +2452,72 @@ object Defaults extends BuildCommon {
|
||||||
analysis
|
analysis
|
||||||
}
|
}
|
||||||
|
|
||||||
def compileIncrementalTaskSettings =
|
def compileIncrementalTaskSettings = inTask(compileIncremental)(
|
||||||
inTask(compileIncremental)(
|
Seq(
|
||||||
Seq(
|
(TaskZero / compileIncremental) := {
|
||||||
(TaskZero / compileIncremental) := (Def
|
val bspTask = (compile / bspCompileTask).value
|
||||||
.cachedTask {
|
val result = cachedCompileIncrementalTask.result.value
|
||||||
val s = streams.value
|
val reporter = (compile / bspReporter).value
|
||||||
val ci = (compile / compileInputs).value
|
val store = analysisStore
|
||||||
// This is a cacheable version
|
val ci = (compile / compileInputs).value
|
||||||
val ci2 = (compile / compileInputs2).value
|
result match
|
||||||
val ping = (TaskZero / earlyOutputPing).value
|
case Result.Value(res) =>
|
||||||
val reporter = (compile / bspReporter).value
|
val analysis = store.unsafeGet().getAnalysis()
|
||||||
val setup: Setup = (TaskZero / compileIncSetup).value
|
reporter.sendSuccessReport(analysis)
|
||||||
val useBinary: Boolean = enableBinaryCompileAnalysis.value
|
bspTask.notifySuccess(analysis)
|
||||||
val c = fileConverter.value
|
res
|
||||||
val analysisResult: CompileResult =
|
case Result.Inc(cause) =>
|
||||||
BspCompileTask
|
val compileFailed = cause.directCause.collect { case c: CompileFailed => c }
|
||||||
.compute(bspTargetIdentifier.value, thisProjectRef.value, configuration.value) {
|
reporter.sendFailureReport(ci.options.sources)
|
||||||
bspTask =>
|
bspTask.notifyFailure(compileFailed)
|
||||||
// TODO - Should readAnalysis + saveAnalysis be scoped by the compile task too?
|
throw cause
|
||||||
compileIncrementalTaskImpl(bspTask, s, ci, ping, reporter)
|
},
|
||||||
}
|
packagedArtifact := {
|
||||||
val analysisOut = c.toVirtualFile(setup.cachePath())
|
val (hasModified, out) = compileIncremental.value
|
||||||
val store =
|
artifact.value -> out
|
||||||
MixedAnalyzingCompiler.staticCachedStore(setup.cachePath, !useBinary)
|
},
|
||||||
val contents =
|
artifact := artifactSetting.value,
|
||||||
AnalysisContents.create(analysisResult.analysis(), analysisResult.setup())
|
artifactClassifier := Some("noresources"),
|
||||||
store.set(contents)
|
artifactPath := artifactPathSetting(artifact).value,
|
||||||
Def.declareOutput(analysisOut)
|
|
||||||
val dir = classDirectory.value
|
|
||||||
if (dir / "META-INF" / "MANIFEST.MF").exists then
|
|
||||||
IO.delete(dir / "META-INF" / "MANIFEST.MF")
|
|
||||||
// inline mappings
|
|
||||||
val mappings = Path
|
|
||||||
.allSubpaths(dir)
|
|
||||||
.filter(_._1.isFile())
|
|
||||||
.map { case (p, path) =>
|
|
||||||
val vf = c.toVirtualFile(p.toPath())
|
|
||||||
(vf: HashedVirtualFileRef) -> path
|
|
||||||
}
|
|
||||||
.toSeq
|
|
||||||
// inlined to avoid caching mappings
|
|
||||||
val pkgConfig = Pkg.Configuration(
|
|
||||||
mappings,
|
|
||||||
artifactPath.value,
|
|
||||||
packageOptions.value,
|
|
||||||
)
|
|
||||||
val out = Pkg(
|
|
||||||
pkgConfig,
|
|
||||||
c,
|
|
||||||
s.log,
|
|
||||||
Pkg.timeFromConfiguration(pkgConfig)
|
|
||||||
)
|
|
||||||
s.log.debug(s"wrote $out")
|
|
||||||
Def.declareOutput(out)
|
|
||||||
analysisResult.hasModified() -> (out: HashedVirtualFileRef)
|
|
||||||
})
|
|
||||||
.tag(Tags.Compile, Tags.CPU)
|
|
||||||
.value,
|
|
||||||
packagedArtifact := {
|
|
||||||
val (hasModified, out) = compileIncremental.value
|
|
||||||
artifact.value -> out
|
|
||||||
},
|
|
||||||
artifact := artifactSetting.value,
|
|
||||||
artifactClassifier := Some("noresources"),
|
|
||||||
artifactPath := artifactPathSetting(artifact).value,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private val cachedCompileIncrementalTask = Def
|
||||||
|
.cachedTask {
|
||||||
|
val s = streams.value
|
||||||
|
val ci = (compile / compileInputs).value
|
||||||
|
val bspTask = (compile / bspCompileTask).value
|
||||||
|
// This is a cacheable version
|
||||||
|
val ci2 = (compile / compileInputs2).value
|
||||||
|
val ping = (TaskZero / earlyOutputPing).value
|
||||||
|
val setup: Setup = (TaskZero / compileIncSetup).value
|
||||||
|
val store = analysisStore
|
||||||
|
val c = fileConverter.value
|
||||||
|
// TODO - Should readAnalysis + saveAnalysis be scoped by the compile task too?
|
||||||
|
val analysisResult = Retry(compileIncrementalTaskImpl(bspTask, s, ci, ping))
|
||||||
|
val analysisOut = c.toVirtualFile(setup.cachePath())
|
||||||
|
val contents = AnalysisContents.create(analysisResult.analysis(), analysisResult.setup())
|
||||||
|
store.set(contents)
|
||||||
|
Def.declareOutput(analysisOut)
|
||||||
|
val dir = classDirectory.value
|
||||||
|
if (dir / "META-INF" / "MANIFEST.MF").exists then IO.delete(dir / "META-INF" / "MANIFEST.MF")
|
||||||
|
// inline mappings
|
||||||
|
val mappings = Path
|
||||||
|
.allSubpaths(dir)
|
||||||
|
.filter(_._1.isFile())
|
||||||
|
.map { case (p, path) =>
|
||||||
|
val vf = c.toVirtualFile(p.toPath())
|
||||||
|
(vf: HashedVirtualFileRef) -> path
|
||||||
|
}
|
||||||
|
.toSeq
|
||||||
|
// inlined to avoid caching mappings
|
||||||
|
val pkgConfig = Pkg.Configuration(mappings, artifactPath.value, packageOptions.value)
|
||||||
|
val out = Pkg(pkgConfig, c, s.log, Pkg.timeFromConfiguration(pkgConfig))
|
||||||
|
s.log.debug(s"wrote $out")
|
||||||
|
Def.declareOutput(out)
|
||||||
|
analysisResult.hasModified() -> (out: HashedVirtualFileRef)
|
||||||
|
}
|
||||||
|
.tag(Tags.Compile, Tags.CPU)
|
||||||
|
|
||||||
private val incCompiler = ZincUtil.defaultIncrementalCompiler
|
private val incCompiler = ZincUtil.defaultIncrementalCompiler
|
||||||
private[sbt] def compileJavaTask: Initialize[Task[CompileResult]] = Def.task {
|
private[sbt] def compileJavaTask: Initialize[Task[CompileResult]] = Def.task {
|
||||||
|
|
@ -2549,8 +2545,7 @@ object Defaults extends BuildCommon {
|
||||||
task: BspCompileTask,
|
task: BspCompileTask,
|
||||||
s: TaskStreams,
|
s: TaskStreams,
|
||||||
ci: Inputs,
|
ci: Inputs,
|
||||||
promise: PromiseWrap[Boolean],
|
promise: PromiseWrap[Boolean]
|
||||||
reporter: BuildServerReporter,
|
|
||||||
): CompileResult = {
|
): CompileResult = {
|
||||||
lazy val x = s.text(ExportStream)
|
lazy val x = s.text(ExportStream)
|
||||||
def onArgs(cs: Compilers) =
|
def onArgs(cs: Compilers) =
|
||||||
|
|
@ -2565,16 +2560,12 @@ object Defaults extends BuildCommon {
|
||||||
val compilers: Compilers = ci.compilers
|
val compilers: Compilers = ci.compilers
|
||||||
val setup: Setup = ci.setup
|
val setup: Setup = ci.setup
|
||||||
val i = ci.withCompilers(onArgs(compilers)).withSetup(onProgress(setup))
|
val i = ci.withCompilers(onArgs(compilers)).withSetup(onProgress(setup))
|
||||||
try
|
try incCompiler.compile(i, s.log)
|
||||||
val result = incCompiler.compile(i, s.log)
|
|
||||||
reporter.sendSuccessReport(result.getAnalysis)
|
|
||||||
result
|
|
||||||
catch
|
catch
|
||||||
case e: Throwable =>
|
case e: Throwable =>
|
||||||
if !promise.isCompleted then
|
if !promise.isCompleted then
|
||||||
promise.failure(e)
|
promise.failure(e)
|
||||||
ConcurrentRestrictions.cancelAllSentinels()
|
ConcurrentRestrictions.cancelAllSentinels()
|
||||||
reporter.sendFailureReport(ci.options.sources)
|
|
||||||
throw e
|
throw e
|
||||||
finally x.close() // workaround for #937
|
finally x.close() // workaround for #937
|
||||||
}
|
}
|
||||||
|
|
@ -2591,12 +2582,8 @@ object Defaults extends BuildCommon {
|
||||||
override def definesClass(classpathEntry: VirtualFile): DefinesClass =
|
override def definesClass(classpathEntry: VirtualFile): DefinesClass =
|
||||||
cachedPerEntryDefinesClassLookup(classpathEntry)
|
cachedPerEntryDefinesClassLookup(classpathEntry)
|
||||||
val extra = extraIncOptions.value.map(t2)
|
val extra = extraIncOptions.value.map(t2)
|
||||||
val useBinary: Boolean = enableBinaryCompileAnalysis.value
|
val store = earlyAnalysisStore
|
||||||
val eapath = earlyCompileAnalysisFile.value.toPath
|
val eaOpt = if exportPipelining.value then Some(store) else None
|
||||||
val eaOpt =
|
|
||||||
if exportPipelining.value then
|
|
||||||
Some(MixedAnalyzingCompiler.staticCachedStore(eapath, !useBinary))
|
|
||||||
else None
|
|
||||||
Setup.of(
|
Setup.of(
|
||||||
lookup,
|
lookup,
|
||||||
(compile / skip).value,
|
(compile / skip).value,
|
||||||
|
|
@ -2672,6 +2659,8 @@ object Defaults extends BuildCommon {
|
||||||
javacOptions.value.toVector,
|
javacOptions.value.toVector,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
bspCompileTask :=
|
||||||
|
BspCompileTask.start(bspTargetIdentifier.value, thisProjectRef.value, configuration.value)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2698,8 +2687,7 @@ object Defaults extends BuildCommon {
|
||||||
def compileAnalysisSettings: Seq[Setting[_]] = Seq(
|
def compileAnalysisSettings: Seq[Setting[_]] = Seq(
|
||||||
previousCompile := {
|
previousCompile := {
|
||||||
val setup = compileIncSetup.value
|
val setup = compileIncSetup.value
|
||||||
val useBinary: Boolean = enableBinaryCompileAnalysis.value
|
val store = analysisStore
|
||||||
val store = MixedAnalyzingCompiler.staticCachedStore(setup.cacheFile.toPath, !useBinary)
|
|
||||||
val prev = store.get().toOption match {
|
val prev = store.get().toOption match {
|
||||||
case Some(contents) =>
|
case Some(contents) =>
|
||||||
val analysis = Option(contents.getAnalysis).toOptional
|
val analysis = Option(contents.getAnalysis).toOptional
|
||||||
|
|
@ -2711,6 +2699,18 @@ object Defaults extends BuildCommon {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private inline def analysisStore: AnalysisStore = {
|
||||||
|
val setup = compileIncSetup.value
|
||||||
|
val useBinary = enableBinaryCompileAnalysis.value
|
||||||
|
MixedAnalyzingCompiler.staticCachedStore(setup.cacheFile.toPath, !useBinary)
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline def earlyAnalysisStore: AnalysisStore = {
|
||||||
|
val earlyAnalysisPath = earlyCompileAnalysisFile.value.toPath
|
||||||
|
val useBinary = enableBinaryCompileAnalysis.value
|
||||||
|
MixedAnalyzingCompiler.staticCachedStore(earlyAnalysisPath, !useBinary)
|
||||||
|
}
|
||||||
|
|
||||||
def printWarningsTask: Initialize[Task[Unit]] =
|
def printWarningsTask: Initialize[Task[Unit]] =
|
||||||
Def.task {
|
Def.task {
|
||||||
val analysis = compile.value match { case a: Analysis => a }
|
val analysis = compile.value match { case a: Analysis => a }
|
||||||
|
|
@ -4828,7 +4828,7 @@ trait BuildExtra extends BuildCommon with DefExtra {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.value
|
.evaluated
|
||||||
) ++ inTask(scoped)((config / forkOptions) := forkOptionsTask.value)
|
) ++ inTask(scoped)((config / forkOptions) := forkOptionsTask.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import sbt.internal.io.WatchState
|
||||||
import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt }
|
import sbt.internal.librarymanagement.{ CompatibilityWarningOptions, IvySbt }
|
||||||
import sbt.internal.remotecache.RemoteCacheArtifact
|
import sbt.internal.remotecache.RemoteCacheArtifact
|
||||||
import sbt.internal.server.BuildServerProtocol.BspFullWorkspace
|
import sbt.internal.server.BuildServerProtocol.BspFullWorkspace
|
||||||
import sbt.internal.server.{ BuildServerReporter, ServerHandler }
|
import sbt.internal.server.{ BspCompileTask, BuildServerReporter, ServerHandler }
|
||||||
import sbt.internal.util.{ AttributeKey, ProgressState, SourcePosition }
|
import sbt.internal.util.{ AttributeKey, ProgressState, SourcePosition }
|
||||||
import sbt.internal.util.StringAttributeKey
|
import sbt.internal.util.StringAttributeKey
|
||||||
import sbt.io._
|
import sbt.io._
|
||||||
|
|
@ -44,6 +44,7 @@ import xsbti.compile.analysis.ReadStamps
|
||||||
import scala.concurrent.duration.{ Duration, FiniteDuration }
|
import scala.concurrent.duration.{ Duration, FiniteDuration }
|
||||||
import scala.xml.{ NodeSeq, Node => XNode }
|
import scala.xml.{ NodeSeq, Node => XNode }
|
||||||
|
|
||||||
|
|
||||||
// format: off
|
// format: off
|
||||||
|
|
||||||
object Keys {
|
object Keys {
|
||||||
|
|
@ -438,6 +439,7 @@ object Keys {
|
||||||
val bspBuildTargetOutputPathsItem = taskKey[OutputPathsItem]("").withRank(DTask)
|
val bspBuildTargetOutputPathsItem = taskKey[OutputPathsItem]("").withRank(DTask)
|
||||||
val bspBuildTargetCompile = inputKey[Unit]("").withRank(DTask)
|
val bspBuildTargetCompile = inputKey[Unit]("").withRank(DTask)
|
||||||
val bspBuildTargetCompileItem = taskKey[Int]("").withRank(DTask)
|
val bspBuildTargetCompileItem = taskKey[Int]("").withRank(DTask)
|
||||||
|
@cacheLevel(include = Array.empty) private[sbt] val bspCompileTask = taskKey[BspCompileTask]("").withRank(DTask)
|
||||||
val bspBuildTargetTest = inputKey[Unit]("Corresponds to buildTarget/test request").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 bspBuildTargetRun = inputKey[Unit]("Corresponds to buildTarget/run request").withRank(DTask)
|
||||||
val bspBuildTargetCleanCache = inputKey[Unit]("Corresponds to buildTarget/cleanCache request").withRank(DTask)
|
val bspBuildTargetCleanCache = inputKey[Unit]("Corresponds to buildTarget/cleanCache request").withRank(DTask)
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,8 @@ object RemoteCache {
|
||||||
Def._outputDirectory = Some(outDir)
|
Def._outputDirectory = Some(outDir)
|
||||||
val caches = s.get(BasicKeys.cacheStores)
|
val caches = s.get(BasicKeys.cacheStores)
|
||||||
caches match
|
caches match
|
||||||
case Some(xs) => Def._cacheStore = AggregateActionCacheStore(xs)
|
case Some(xs) if xs.nonEmpty => Def._cacheStore = AggregateActionCacheStore(xs)
|
||||||
case None =>
|
case _ =>
|
||||||
val tempDiskCache = (s.baseDir / "target" / "bootcache").toPath()
|
val tempDiskCache = (s.baseDir / "target" / "bootcache").toPath()
|
||||||
Def._cacheStore = DiskActionCacheStore(tempDiskCache)
|
Def._cacheStore = DiskActionCacheStore(tempDiskCache)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ object Act {
|
||||||
keyMap: Map[String, AttributeKey[_]],
|
keyMap: Map[String, AttributeKey[_]],
|
||||||
data: Settings[Scope]
|
data: Settings[Scope]
|
||||||
): Parser[ParsedKey] =
|
): Parser[ParsedKey] =
|
||||||
scopedKeyFull(index, current, defaultConfigs, keyMap) flatMap { choices =>
|
scopedKeyFull(index, current, defaultConfigs, keyMap).flatMap { choices =>
|
||||||
select(choices, data)(showRelativeKey2(current))
|
select(choices, data)(showRelativeKey2(current))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,7 +355,7 @@ object Act {
|
||||||
val normKeys = taskKeys(_.label)
|
val normKeys = taskKeys(_.label)
|
||||||
val valid = allKnown ++ normKeys
|
val valid = allKnown ++ normKeys
|
||||||
val suggested = normKeys.map(_._1).toSet
|
val suggested = normKeys.map(_._1).toSet
|
||||||
val keyP = filterStrings(examples(ID, suggested, "key"), valid.keySet, "key") map valid
|
val keyP = filterStrings(examples(ID, suggested, "key"), valid.keySet, "key").map(valid)
|
||||||
|
|
||||||
((token(
|
((token(
|
||||||
value(keyP).map(_ -> slashSeq)
|
value(keyP).map(_ -> slashSeq)
|
||||||
|
|
@ -515,7 +515,7 @@ object Act {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
action match {
|
action match {
|
||||||
case SingleAction => akp flatMap evaluate
|
case SingleAction => akp.flatMap(evaluate)
|
||||||
case ShowAction | PrintAction | MultiAction =>
|
case ShowAction | PrintAction | MultiAction =>
|
||||||
rep1sep(akp, token(Space)) flatMap { pairs =>
|
rep1sep(akp, token(Space)) flatMap { pairs =>
|
||||||
val flat: mutable.ListBuffer[(ScopedKey[_], Seq[String])] = mutable.ListBuffer.empty
|
val flat: mutable.ListBuffer[(ScopedKey[_], Seq[String])] = mutable.ListBuffer.empty
|
||||||
|
|
|
||||||
|
|
@ -9,57 +9,23 @@ package sbt.internal.server
|
||||||
|
|
||||||
import sbt._
|
import sbt._
|
||||||
import sbt.internal.bsp._
|
import sbt.internal.bsp._
|
||||||
import sbt.internal.io.Retry
|
|
||||||
import sbt.internal.server.BspCompileTask.{ compileReport, exchange }
|
|
||||||
import sbt.librarymanagement.Configuration
|
import sbt.librarymanagement.Configuration
|
||||||
import sjsonnew.support.scalajson.unsafe.Converter
|
import sjsonnew.support.scalajson.unsafe.Converter
|
||||||
import xsbti.compile.CompileResult
|
import xsbti.compile.CompileAnalysis
|
||||||
import xsbti.{ CompileFailed, Problem, Severity }
|
import xsbti.{ CompileFailed, Problem, Severity }
|
||||||
|
|
||||||
import scala.util.control.NonFatal
|
|
||||||
|
|
||||||
object BspCompileTask {
|
object BspCompileTask {
|
||||||
private lazy val exchange = StandardMain.exchange
|
|
||||||
|
|
||||||
def compute(targetId: BuildTargetIdentifier, project: ProjectRef, config: Configuration)(
|
def start(
|
||||||
compile: BspCompileTask => CompileResult
|
|
||||||
): CompileResult = {
|
|
||||||
val task = BspCompileTask(targetId, project, config)
|
|
||||||
try {
|
|
||||||
task.notifyStart()
|
|
||||||
val result = Retry(compile(task))
|
|
||||||
task.notifySuccess(result)
|
|
||||||
result
|
|
||||||
} catch {
|
|
||||||
case NonFatal(cause) =>
|
|
||||||
val compileFailed = cause match {
|
|
||||||
case failed: CompileFailed => Some(failed)
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
task.notifyFailure(compileFailed)
|
|
||||||
throw cause
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def apply(
|
|
||||||
targetId: BuildTargetIdentifier,
|
targetId: BuildTargetIdentifier,
|
||||||
project: ProjectRef,
|
project: ProjectRef,
|
||||||
config: Configuration
|
config: Configuration
|
||||||
): BspCompileTask = {
|
): BspCompileTask = {
|
||||||
val taskId = TaskId(BuildServerTasks.uniqueId, Vector())
|
val taskId = TaskId(BuildServerTasks.uniqueId, Vector())
|
||||||
val targetName = BuildTargetName.fromScope(project.project, config.name)
|
val targetName = BuildTargetName.fromScope(project.project, config.name)
|
||||||
BspCompileTask(targetId, targetName, taskId, System.currentTimeMillis())
|
val task = BspCompileTask(targetId, targetName, taskId, System.currentTimeMillis())
|
||||||
}
|
task.notifyStart()
|
||||||
|
task
|
||||||
private def compileReport(
|
|
||||||
problems: Seq[Problem],
|
|
||||||
targetId: BuildTargetIdentifier,
|
|
||||||
elapsedTimeMillis: Long
|
|
||||||
): CompileReport = {
|
|
||||||
val countBySeverity = problems.groupBy(_.severity).view.mapValues(_.size)
|
|
||||||
val warnings = countBySeverity.getOrElse(Severity.Warn, 0)
|
|
||||||
val errors = countBySeverity.getOrElse(Severity.Error, 0)
|
|
||||||
CompileReport(targetId, None, errors, warnings, Some(elapsedTimeMillis.toInt))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,16 +41,16 @@ case class BspCompileTask private (
|
||||||
val message = s"Compiling $targetName"
|
val message = s"Compiling $targetName"
|
||||||
val data = Converter.toJsonUnsafe(CompileTask(targetId))
|
val data = Converter.toJsonUnsafe(CompileTask(targetId))
|
||||||
val params = TaskStartParams(id, startTimeMillis, message, "compile-task", data)
|
val params = TaskStartParams(id, startTimeMillis, message, "compile-task", data)
|
||||||
exchange.notifyEvent("build/taskStart", params)
|
StandardMain.exchange.notifyEvent("build/taskStart", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def notifySuccess(result: CompileResult): Unit = {
|
private[sbt] def notifySuccess(analysis: CompileAnalysis): Unit = {
|
||||||
import scala.jdk.CollectionConverters.*
|
import scala.jdk.CollectionConverters.*
|
||||||
val endTimeMillis = System.currentTimeMillis()
|
val endTimeMillis = System.currentTimeMillis()
|
||||||
val elapsedTimeMillis = endTimeMillis - startTimeMillis
|
val elapsedTimeMillis = endTimeMillis - startTimeMillis
|
||||||
val sourceInfos = result.analysis().readSourceInfos().getAllSourceInfos.asScala
|
val sourceInfos = analysis.readSourceInfos().getAllSourceInfos.asScala
|
||||||
val problems = sourceInfos.values.flatMap(_.getReportedProblems).toSeq
|
val problems = sourceInfos.values.flatMap(_.getReportedProblems).toSeq
|
||||||
val report = compileReport(problems, targetId, elapsedTimeMillis)
|
val report = compileReport(problems, elapsedTimeMillis)
|
||||||
val params = TaskFinishParams(
|
val params = TaskFinishParams(
|
||||||
id,
|
id,
|
||||||
endTimeMillis,
|
endTimeMillis,
|
||||||
|
|
@ -93,7 +59,7 @@ case class BspCompileTask private (
|
||||||
"compile-report",
|
"compile-report",
|
||||||
Converter.toJsonUnsafe(report)
|
Converter.toJsonUnsafe(report)
|
||||||
)
|
)
|
||||||
exchange.notifyEvent("build/taskFinish", params)
|
StandardMain.exchange.notifyEvent("build/taskFinish", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def notifyProgress(percentage: Int, total: Int): Unit = {
|
private[sbt] def notifyProgress(percentage: Int, total: Int): Unit = {
|
||||||
|
|
@ -110,14 +76,14 @@ case class BspCompileTask private (
|
||||||
Some("compile-progress"),
|
Some("compile-progress"),
|
||||||
Some(data)
|
Some(data)
|
||||||
)
|
)
|
||||||
exchange.notifyEvent("build/taskProgress", params)
|
StandardMain.exchange.notifyEvent("build/taskProgress", params)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[sbt] def notifyFailure(cause: Option[CompileFailed]): Unit = {
|
private[sbt] def notifyFailure(cause: Option[CompileFailed]): Unit = {
|
||||||
val endTimeMillis = System.currentTimeMillis()
|
val endTimeMillis = System.currentTimeMillis()
|
||||||
val elapsedTimeMillis = endTimeMillis - startTimeMillis
|
val elapsedTimeMillis = endTimeMillis - startTimeMillis
|
||||||
val problems = cause.map(_.problems().toSeq).getOrElse(Seq.empty[Problem])
|
val problems = cause.map(_.problems().toSeq).getOrElse(Seq.empty[Problem])
|
||||||
val report = compileReport(problems, targetId, elapsedTimeMillis)
|
val report = compileReport(problems, elapsedTimeMillis)
|
||||||
val params = TaskFinishParams(
|
val params = TaskFinishParams(
|
||||||
id,
|
id,
|
||||||
endTimeMillis,
|
endTimeMillis,
|
||||||
|
|
@ -126,6 +92,13 @@ case class BspCompileTask private (
|
||||||
"compile-report",
|
"compile-report",
|
||||||
Converter.toJsonUnsafe(report)
|
Converter.toJsonUnsafe(report)
|
||||||
)
|
)
|
||||||
exchange.notifyEvent("build/taskFinish", params)
|
StandardMain.exchange.notifyEvent("build/taskFinish", params)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def compileReport(problems: Seq[Problem], elapsedTimeMillis: Long): CompileReport = {
|
||||||
|
val countBySeverity = problems.groupBy(_.severity).view.mapValues(_.size)
|
||||||
|
val warnings = countBySeverity.getOrElse(Severity.Warn, 0)
|
||||||
|
val errors = countBySeverity.getOrElse(Severity.Error, 0)
|
||||||
|
CompileReport(targetId, None, errors, warnings, Some(elapsedTimeMillis.toInt))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ import java.io.File
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
// import scala.annotation.nowarn
|
|
||||||
import scala.util.control.NonFatal
|
import scala.util.control.NonFatal
|
||||||
import scala.util.{ Failure, Success }
|
import scala.util.{ Failure, Success }
|
||||||
import scala.annotation.nowarn
|
import scala.annotation.nowarn
|
||||||
|
|
@ -62,14 +61,10 @@ object BuildServerProtocol {
|
||||||
|
|
||||||
private val bspReload = "bspReload"
|
private val bspReload = "bspReload"
|
||||||
|
|
||||||
private lazy val targetIdentifierParser: Parser[Seq[BuildTargetIdentifier]] =
|
private val targetIdentifierParser: Parser[Seq[BuildTargetIdentifier]] =
|
||||||
Def
|
Def
|
||||||
.spaceDelimited()
|
.spaceDelimited()
|
||||||
.map { xs =>
|
.map(xs => xs.map(uri => BuildTargetIdentifier(URI.create(uri))))
|
||||||
xs.map { uri =>
|
|
||||||
BuildTargetIdentifier(URI.create(uri))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val commands: Seq[Command] = Seq(
|
lazy val commands: Seq[Command] = Seq(
|
||||||
Command.single(bspReload) { (state, reqId) =>
|
Command.single(bspReload) { (state, reqId) =>
|
||||||
|
|
@ -103,7 +98,7 @@ object BuildServerProtocol {
|
||||||
bspSbtEnabled := true,
|
bspSbtEnabled := true,
|
||||||
bspFullWorkspace := bspFullWorkspaceSetting.value,
|
bspFullWorkspace := bspFullWorkspaceSetting.value,
|
||||||
bspWorkspace := bspFullWorkspace.value.scopes,
|
bspWorkspace := bspFullWorkspace.value.scopes,
|
||||||
bspWorkspaceBuildTargets := (Def
|
bspWorkspaceBuildTargets := Def
|
||||||
.task {
|
.task {
|
||||||
val workspace = Keys.bspFullWorkspace.value
|
val workspace = Keys.bspFullWorkspace.value
|
||||||
val state = Keys.state.value
|
val state = Keys.state.value
|
||||||
|
|
@ -121,186 +116,137 @@ object BuildServerProtocol {
|
||||||
state.respondEvent(WorkspaceBuildTargetsResult(successfulBuildTargets.toVector))
|
state.respondEvent(WorkspaceBuildTargetsResult(successfulBuildTargets.toVector))
|
||||||
successfulBuildTargets
|
successfulBuildTargets
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.value,
|
.value,
|
||||||
// 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
|
bspBuildTargetSources := bspInputTask { (workspace, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val items = bspBuildTargetSourcesItem.result.all(filter).value
|
||||||
.flatMapTask { targets =>
|
val buildItems = workspace.builds.map { case (id, loadedBuildUnit) =>
|
||||||
val s = state.value
|
val base = loadedBuildUnit.localBase
|
||||||
// val targets = spaceDelimited().parsed.map(uri => BuildTargetIdentifier(URI.create(uri)))
|
val sbtFiles = configurationSources(base)
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
val pluginData = loadedBuildUnit.unit.plugins.pluginData
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
val dirs = pluginData.unmanagedSourceDirectories
|
||||||
// run the worker task concurrently
|
val sourceFiles = getStandaloneSourceFiles(pluginData.unmanagedSources, dirs)
|
||||||
Def.task {
|
val managedDirs = pluginData.managedSourceDirectories
|
||||||
val items = bspBuildTargetSourcesItem.result.all(filter).value
|
val managedSourceFiles =
|
||||||
val buildItems = workspace.builds.map { case (id, loadedBuildUnit) =>
|
getStandaloneSourceFiles(pluginData.managedSources, managedDirs)
|
||||||
val base = loadedBuildUnit.localBase
|
val items =
|
||||||
val sbtFiles = configurationSources(base)
|
dirs.map(toSourceItem(SourceItemKind.Directory, generated = false)) ++
|
||||||
val pluginData = loadedBuildUnit.unit.plugins.pluginData
|
sourceFiles.map(toSourceItem(SourceItemKind.File, generated = false)) ++
|
||||||
val dirs = pluginData.unmanagedSourceDirectories
|
managedDirs.map(toSourceItem(SourceItemKind.Directory, generated = true)) ++
|
||||||
val sourceFiles = getStandaloneSourceFiles(pluginData.unmanagedSources, dirs)
|
managedSourceFiles.map(toSourceItem(SourceItemKind.File, generated = true)) ++
|
||||||
val managedDirs = pluginData.managedSourceDirectories
|
sbtFiles.map(toSourceItem(SourceItemKind.File, generated = false))
|
||||||
val managedSourceFiles =
|
Result.Value(SourcesItem(id, items.toVector))
|
||||||
getStandaloneSourceFiles(pluginData.managedSources, managedDirs)
|
}
|
||||||
val items =
|
val successfulItems = anyOrThrow(items ++ buildItems)
|
||||||
dirs.map(toSourceItem(SourceItemKind.Directory, generated = false)) ++
|
val result = SourcesResult(successfulItems.toVector)
|
||||||
sourceFiles.map(toSourceItem(SourceItemKind.File, generated = false)) ++
|
state.value.respondEvent(result)
|
||||||
managedDirs.map(toSourceItem(SourceItemKind.Directory, generated = true)) ++
|
}.evaluated,
|
||||||
managedSourceFiles.map(toSourceItem(SourceItemKind.File, generated = true)) ++
|
|
||||||
sbtFiles.map(toSourceItem(SourceItemKind.File, generated = false))
|
|
||||||
Result.Value(SourcesItem(id, items.toVector))
|
|
||||||
}
|
|
||||||
val successfulItems = anyOrThrow(items ++ buildItems)
|
|
||||||
val result = SourcesResult(successfulItems.toVector)
|
|
||||||
s.respondEvent(result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.value,
|
|
||||||
bspBuildTargetSources / aggregate := false,
|
bspBuildTargetSources / aggregate := false,
|
||||||
bspBuildTargetResources := (Def
|
bspBuildTargetResources := bspInputTask { (_, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val items = bspBuildTargetResourcesItem.result.all(filter).value
|
||||||
.flatMapTask { targets =>
|
val successfulItems = anyOrThrow(items)
|
||||||
val s = state.value
|
val result = ResourcesResult(successfulItems.toVector)
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
state.value.respondEvent(result)
|
||||||
workspace.warnIfBuildsNonEmpty(Method.Resources, s.log)
|
}.evaluated,
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
|
||||||
// run the worker task concurrently
|
|
||||||
Def.task {
|
|
||||||
val items = bspBuildTargetResourcesItem.result.all(filter).value
|
|
||||||
val successfulItems = anyOrThrow(items)
|
|
||||||
val result = ResourcesResult(successfulItems.toVector)
|
|
||||||
s.respondEvent(result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.value,
|
|
||||||
bspBuildTargetResources / aggregate := false,
|
bspBuildTargetResources / aggregate := false,
|
||||||
bspBuildTargetDependencySources := (Def
|
bspBuildTargetDependencySources := bspInputTask { (_, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val items = bspBuildTargetDependencySourcesItem.result.all(filter).value
|
||||||
.flatMapTask { targets =>
|
val successfulItems = anyOrThrow(items)
|
||||||
val s = state.value
|
val result = DependencySourcesResult(successfulItems.toVector)
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
state.value.respondEvent(result)
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
}.evaluated,
|
||||||
// run the worker task concurrently
|
|
||||||
Def.task {
|
|
||||||
import sbt.internal.bsp.codec.JsonProtocol._
|
|
||||||
val items = bspBuildTargetDependencySourcesItem.result.all(filter).value
|
|
||||||
val successfulItems = anyOrThrow(items)
|
|
||||||
val result = DependencySourcesResult(successfulItems.toVector)
|
|
||||||
s.respondEvent(result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.value,
|
|
||||||
bspBuildTargetDependencySources / aggregate := false,
|
bspBuildTargetDependencySources / aggregate := false,
|
||||||
bspBuildTargetCompile := (Def
|
bspBuildTargetCompile := bspInputTask { (workspace, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val s = state.value
|
||||||
.flatMapTask { targets =>
|
workspace.warnIfBuildsNonEmpty(Method.Compile, s.log)
|
||||||
val s: State = state.value
|
val statusCodes = Keys.bspBuildTargetCompileItem.result.all(filter).value
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
val aggregatedStatusCode = allOrThrow(statusCodes) match {
|
||||||
workspace.warnIfBuildsNonEmpty(Method.Compile, s.log)
|
case Seq() => StatusCode.Success
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
case codes => codes.max
|
||||||
Def.task {
|
}
|
||||||
val statusCodes = Keys.bspBuildTargetCompileItem.result.all(filter).value
|
s.respondEvent(BspCompileResult(None, aggregatedStatusCode))
|
||||||
val aggregatedStatusCode = allOrThrow(statusCodes) match {
|
}.evaluated,
|
||||||
case Seq() => StatusCode.Success
|
bspBuildTargetOutputPaths := bspInputTask { (_, filter) =>
|
||||||
case codes => codes.max
|
val items = bspBuildTargetOutputPathsItem.result.all(filter).value
|
||||||
}
|
val successfulItems = anyOrThrow(items)
|
||||||
s.respondEvent(BspCompileResult(None, aggregatedStatusCode))
|
val result = OutputPathsResult(successfulItems.toVector)
|
||||||
}
|
state.value.respondEvent(result)
|
||||||
})
|
}.evaluated,
|
||||||
.value,
|
bspBuildTargetOutputPaths / aggregate := false,
|
||||||
bspBuildTargetCompile / aggregate := false,
|
bspBuildTargetCompile / aggregate := false,
|
||||||
bspBuildTargetTest := bspTestTask.evaluated,
|
bspBuildTargetTest := bspTestTask.evaluated,
|
||||||
bspBuildTargetTest / aggregate := false,
|
bspBuildTargetTest / aggregate := false,
|
||||||
bspBuildTargetCleanCache := (Def
|
bspBuildTargetCleanCache := bspInputTask { (workspace, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val s = state.value
|
||||||
.flatMapTask { targets =>
|
workspace.warnIfBuildsNonEmpty(Method.CleanCache, s.log)
|
||||||
val s: State = state.value
|
val results = Keys.clean.result.all(filter).value
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
val successes = anyOrThrow(results).size
|
||||||
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
|
// When asking to rebuild Project, IntelliJ sends the root build as an additional target,
|
||||||
// not returned as part of the results. In this case, there's 1 build entry in the workspace, and we're
|
// however it is not returned as part of the results. We're checking that the number of
|
||||||
// checking that the executed results plus this entry is equal to the total number of targets.
|
// results equals the number of scopes (not the root build).
|
||||||
// When rebuilding a single module, the root build isn't sent, just the requested targets.
|
// When rebuilding a single module, the root build isn't sent, just the requested targets.
|
||||||
val cleaned = successes + workspace.builds.size == targets.size
|
val cleaned = successes == workspace.scopes.size
|
||||||
s.respondEvent(CleanCacheResult(None, cleaned))
|
s.respondEvent(CleanCacheResult(None, cleaned))
|
||||||
}
|
}.evaluated,
|
||||||
})
|
|
||||||
.value,
|
|
||||||
bspBuildTargetCleanCache / aggregate := false,
|
bspBuildTargetCleanCache / aggregate := false,
|
||||||
bspBuildTargetScalacOptions := (Def
|
bspBuildTargetScalacOptions := bspInputTask { (workspace, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val items = bspBuildTargetScalacOptionsItem.result.all(filter).value
|
||||||
.flatMapTask { targets =>
|
val appProvider = appConfiguration.value.provider()
|
||||||
val s = state.value
|
val sbtJars = appProvider.mainClasspath()
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
val buildItems = workspace.builds.map { build =>
|
||||||
val builds = workspace.builds
|
val plugins: LoadedPlugins = build._2.unit.plugins
|
||||||
|
val scalacOptions = plugins.pluginData.scalacOptions
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
val pluginClasspath = plugins.classpath
|
||||||
Def.task {
|
val converter = plugins.pluginData.converter
|
||||||
val items = bspBuildTargetScalacOptionsItem.result.all(filter).value
|
val classpath =
|
||||||
val appProvider = appConfiguration.value.provider()
|
pluginClasspath.map(converter.toPath).map(_.toFile).map(_.toURI).toVector ++
|
||||||
val sbtJars = appProvider.mainClasspath()
|
(sbtJars).map(_.toURI).toVector
|
||||||
val buildItems = builds.map { build =>
|
val item = ScalacOptionsItem(
|
||||||
val plugins: LoadedPlugins = build._2.unit.plugins
|
build._1,
|
||||||
val scalacOptions = plugins.pluginData.scalacOptions
|
scalacOptions.toVector,
|
||||||
val pluginClasspath = plugins.classpath
|
classpath,
|
||||||
val converter = plugins.pluginData.converter
|
new File(build._2.localBase, "project/target").toURI
|
||||||
val classpath =
|
)
|
||||||
pluginClasspath.map(converter.toPath).map(_.toFile).map(_.toURI).toVector ++
|
Result.Value(item)
|
||||||
(sbtJars).map(_.toURI).toVector
|
}
|
||||||
val item = ScalacOptionsItem(
|
val successfulItems = anyOrThrow(items ++ buildItems)
|
||||||
build._1,
|
val result = ScalacOptionsResult(successfulItems.toVector)
|
||||||
scalacOptions.toVector,
|
state.value.respondEvent(result)
|
||||||
classpath,
|
}.evaluated,
|
||||||
new File(build._2.localBase, "project/target").toURI
|
|
||||||
)
|
|
||||||
Result.Value(item)
|
|
||||||
}
|
|
||||||
val successfulItems = anyOrThrow(items ++ buildItems)
|
|
||||||
val result = ScalacOptionsResult(successfulItems.toVector)
|
|
||||||
s.respondEvent(result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.value,
|
|
||||||
bspBuildTargetScalacOptions / aggregate := false,
|
bspBuildTargetScalacOptions / aggregate := false,
|
||||||
bspScalaTestClasses := (Def
|
bspBuildTargetJVMRunEnvironment := bspInputTask { (_, filter) =>
|
||||||
.input((s: State) => targetIdentifierParser)
|
val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value
|
||||||
.flatMapTask { targets =>
|
val successfulItems = anyOrThrow(items)
|
||||||
val s = state.value
|
val result = JvmRunEnvironmentResult(successfulItems.toVector, None)
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
state.value.respondEvent(result)
|
||||||
workspace.warnIfBuildsNonEmpty(Method.ScalaTestClasses, s.log)
|
}.evaluated,
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
bspBuildTargetJVMRunEnvironment / aggregate := false,
|
||||||
Def.task {
|
bspBuildTargetJVMTestEnvironment := bspInputTask { (_, filter) =>
|
||||||
val items = bspScalaTestClassesItem.result.all(filter).value
|
val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value
|
||||||
val successfulItems = anyOrThrow[Seq[ScalaTestClassesItem]](items).flatten
|
val successfulItems = anyOrThrow(items)
|
||||||
val result = ScalaTestClassesResult(
|
val result = JvmTestEnvironmentResult(successfulItems.toVector, None)
|
||||||
items = successfulItems.toVector,
|
state.value.respondEvent(result)
|
||||||
originId = None: Option[String]
|
}.evaluated,
|
||||||
)
|
bspBuildTargetJVMTestEnvironment / aggregate := false,
|
||||||
s.respondEvent(result)
|
bspScalaTestClasses := bspInputTask { (workspace, filter) =>
|
||||||
}
|
val s = state.value
|
||||||
})
|
val items = bspScalaTestClassesItem.result.all(filter).value
|
||||||
.value,
|
workspace.warnIfBuildsNonEmpty(Method.ScalaTestClasses, s.log)
|
||||||
bspScalaMainClasses := (Def
|
val successfulItems = anyOrThrow[Seq[ScalaTestClassesItem]](items).flatten
|
||||||
.input((s: State) => targetIdentifierParser)
|
val result = ScalaTestClassesResult(
|
||||||
.flatMapTask { targets =>
|
items = successfulItems.toVector,
|
||||||
val s = state.value
|
originId = None: Option[String]
|
||||||
val workspace = bspFullWorkspace.value.filter(targets)
|
)
|
||||||
workspace.warnIfBuildsNonEmpty(Method.ScalaMainClasses, s.log)
|
s.respondEvent(result)
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
}.evaluated,
|
||||||
Def.task {
|
bspScalaMainClasses := bspInputTask { (_, filter) =>
|
||||||
val items = bspScalaMainClassesItem.result.all(filter).value
|
val items = bspScalaMainClassesItem.result.all(filter).value
|
||||||
val successfulItems = anyOrThrow(items)
|
val successfulItems = anyOrThrow(items)
|
||||||
val result = ScalaMainClassesResult(successfulItems.toVector, None)
|
val result = ScalaMainClassesResult(successfulItems.toVector, None)
|
||||||
s.respondEvent(result)
|
state.value.respondEvent(result)
|
||||||
}
|
}.evaluated,
|
||||||
})
|
|
||||||
.value,
|
|
||||||
bspScalaMainClasses / aggregate := false
|
bspScalaMainClasses / aggregate := false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -344,22 +290,6 @@ object BuildServerProtocol {
|
||||||
bspBuildTargetCompileItem := bspCompileTask.value,
|
bspBuildTargetCompileItem := bspCompileTask.value,
|
||||||
bspBuildTargetRun := bspRunTask.evaluated,
|
bspBuildTargetRun := bspRunTask.evaluated,
|
||||||
bspBuildTargetScalacOptionsItem := scalacOptionsTask.value,
|
bspBuildTargetScalacOptionsItem := scalacOptionsTask.value,
|
||||||
bspBuildTargetJVMRunEnvironment := bspInputTask { (state, _, _, filter) =>
|
|
||||||
Def.task {
|
|
||||||
val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value
|
|
||||||
val successfulItems = anyOrThrow(items)
|
|
||||||
val result = JvmRunEnvironmentResult(successfulItems.toVector, None)
|
|
||||||
state.respondEvent(result)
|
|
||||||
}
|
|
||||||
}.evaluated,
|
|
||||||
bspBuildTargetJVMTestEnvironment := bspInputTask { (state, _, _, filter) =>
|
|
||||||
Def.task {
|
|
||||||
val items = bspBuildTargetJvmEnvironmentItem.result.all(filter).value
|
|
||||||
val successfulItems = anyOrThrow(items)
|
|
||||||
val result = JvmTestEnvironmentResult(successfulItems.toVector, None)
|
|
||||||
state.respondEvent(result)
|
|
||||||
}
|
|
||||||
}.evaluated,
|
|
||||||
bspBuildTargetJvmEnvironmentItem := jvmEnvironmentItem().value,
|
bspBuildTargetJvmEnvironmentItem := jvmEnvironmentItem().value,
|
||||||
bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value,
|
bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value,
|
||||||
bspScalaTestClassesItem := scalaTestClassesTask.value,
|
bspScalaTestClassesItem := scalaTestClassesTask.value,
|
||||||
|
|
@ -755,21 +685,16 @@ object BuildServerProtocol {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def bspInputTask[T](
|
private inline def bspInputTask[T](
|
||||||
taskImpl: (
|
inline taskImpl: (BspFullWorkspace, ScopeFilter) => T
|
||||||
State,
|
|
||||||
Seq[BuildTargetIdentifier],
|
|
||||||
BspFullWorkspace,
|
|
||||||
ScopeFilter
|
|
||||||
) => Def.Initialize[Task[T]]
|
|
||||||
): Def.Initialize[InputTask[T]] =
|
): Def.Initialize[InputTask[T]] =
|
||||||
Def
|
Def
|
||||||
.input((s: State) => targetIdentifierParser)
|
.input(_ => targetIdentifierParser)
|
||||||
.flatMapTask { targets =>
|
.flatMapTask { targets =>
|
||||||
val s = state.value
|
val s = state.value
|
||||||
val workspace: BspFullWorkspace = bspFullWorkspace.value.filter(targets)
|
val workspace: BspFullWorkspace = bspFullWorkspace.value.filter(targets)
|
||||||
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
val filter = ScopeFilter.in(workspace.scopes.values.toList)
|
||||||
taskImpl(s, targets, workspace, filter)
|
Def.task(taskImpl(workspace, filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
private def jvmEnvironmentItem(): Initialize[Task[JvmEnvironmentItem]] = Def.task {
|
private def jvmEnvironmentItem(): Initialize[Task[JvmEnvironmentItem]] = Def.task {
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,7 @@ sealed trait BuildServerReporter extends Reporter {
|
||||||
|
|
||||||
protected def publishDiagnostic(problem: Problem): Unit
|
protected def publishDiagnostic(problem: Problem): Unit
|
||||||
|
|
||||||
def sendSuccessReport(
|
def sendSuccessReport(analysis: CompileAnalysis): Unit
|
||||||
analysis: CompileAnalysis,
|
|
||||||
): Unit
|
|
||||||
|
|
||||||
def sendFailureReport(sources: Array[VirtualFile]): Unit
|
def sendFailureReport(sources: Array[VirtualFile]): Unit
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
ThisBuild / scalaVersion := "2.13.8"
|
ThisBuild / scalaVersion := "2.13.8"
|
||||||
|
|
||||||
Global / serverLog / logLevel := Level.Debug
|
Global / serverLog / logLevel := Level.Debug
|
||||||
|
Global / cacheStores := Seq.empty
|
||||||
|
|
||||||
lazy val runAndTest = project.in(file("run-and-test"))
|
lazy val runAndTest = project.in(file("run-and-test"))
|
||||||
.settings(
|
.settings(
|
||||||
|
|
|
||||||
|
|
@ -7,27 +7,27 @@
|
||||||
|
|
||||||
package testpkg
|
package testpkg
|
||||||
|
|
||||||
import sbt.internal.bsp._
|
import sbt.internal.bsp.*
|
||||||
import sbt.internal.langserver.ErrorCodes
|
import sbt.internal.langserver.ErrorCodes
|
||||||
import sbt.IO
|
import sbt.IO
|
||||||
import sbt.internal.protocol.JsonRpcRequestMessage
|
import sbt.internal.protocol.JsonRpcRequestMessage
|
||||||
import sbt.internal.protocol.codec.JsonRPCProtocol._
|
import sbt.internal.protocol.codec.JsonRPCProtocol.*
|
||||||
import sjsonnew.JsonWriter
|
import sjsonnew.JsonWriter
|
||||||
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
|
import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter }
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Files
|
||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration.*
|
||||||
|
|
||||||
// starts svr using server-test/buildserver and perform custom server tests
|
// starts svr using server-test/buildserver and perform custom server tests
|
||||||
object BuildServerTest extends AbstractServerTest {
|
class BuildServerTest extends AbstractServerTest {
|
||||||
|
|
||||||
import sbt.internal.bsp.codec.JsonProtocol._
|
import sbt.internal.bsp.codec.JsonProtocol._
|
||||||
|
|
||||||
override val testDirectory: String = "buildserver"
|
override val testDirectory: String = "buildserver"
|
||||||
|
|
||||||
test("build/initialize") { _ =>
|
test("build/initialize") {
|
||||||
initializeRequest()
|
initializeRequest()
|
||||||
assert(svr.waitForString(10.seconds) { s =>
|
assert(svr.waitForString(10.seconds) { s =>
|
||||||
(s contains """"id":"8"""") &&
|
(s contains """"id":"8"""") &&
|
||||||
|
|
@ -36,7 +36,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("workspace/buildTargets") { _ =>
|
test("workspace/buildTargets") {
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
"""{ "jsonrpc": "2.0", "id": "16", "method": "workspace/buildTargets", "params": {} }"""
|
"""{ "jsonrpc": "2.0", "id": "16", "method": "workspace/buildTargets", "params": {} }"""
|
||||||
)
|
)
|
||||||
|
|
@ -50,7 +50,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
assert(!result.targets.exists(_.displayName.contains("badBuildTarget")))
|
assert(!result.targets.exists(_.displayName.contains("badBuildTarget")))
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/sources") { _ =>
|
test("buildTarget/sources") {
|
||||||
val buildTarget = buildTargetUri("util", "Compile")
|
val buildTarget = buildTargetUri("util", "Compile")
|
||||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||||
svr.sendJsonRpc(buildTargetSources(24, Seq(buildTarget, badBuildTarget)))
|
svr.sendJsonRpc(buildTargetSources(24, Seq(buildTarget, badBuildTarget)))
|
||||||
|
|
@ -59,7 +59,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
val sources = s.items.head.sources.map(_.uri)
|
val sources = s.items.head.sources.map(_.uri)
|
||||||
assert(sources.contains(new File(svr.baseDirectory, "util/src/main/scala").toURI))
|
assert(sources.contains(new File(svr.baseDirectory, "util/src/main/scala").toURI))
|
||||||
}
|
}
|
||||||
test("buildTarget/sources: base sources") { _ =>
|
test("buildTarget/sources: base sources") {
|
||||||
val buildTarget = buildTargetUri("buildserver", "Compile")
|
val buildTarget = buildTargetUri("buildserver", "Compile")
|
||||||
svr.sendJsonRpc(buildTargetSources(25, Seq(buildTarget)))
|
svr.sendJsonRpc(buildTargetSources(25, Seq(buildTarget)))
|
||||||
assert(processing("buildTarget/sources"))
|
assert(processing("buildTarget/sources"))
|
||||||
|
|
@ -73,7 +73,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
assert(sources.contains(expectedSource))
|
assert(sources.contains(expectedSource))
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/sources: sbt") { _ =>
|
test("buildTarget/sources: sbt") {
|
||||||
val x = new URI(s"${svr.baseDirectory.getAbsoluteFile.toURI}#buildserver-build")
|
val x = new URI(s"${svr.baseDirectory.getAbsoluteFile.toURI}#buildserver-build")
|
||||||
svr.sendJsonRpc(buildTargetSources(26, Seq(x)))
|
svr.sendJsonRpc(buildTargetSources(26, Seq(x)))
|
||||||
assert(processing("buildTarget/sources"))
|
assert(processing("buildTarget/sources"))
|
||||||
|
|
@ -83,16 +83,15 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
"build.sbt",
|
"build.sbt",
|
||||||
"project/A.scala",
|
"project/A.scala",
|
||||||
"project/src/main/java",
|
"project/src/main/java",
|
||||||
"project/src/main/scala-2",
|
"project/src/main/scala-3",
|
||||||
"project/src/main/scala-2.12",
|
s"project/src/main/scala-sbt-${sbtVersion}",
|
||||||
"project/src/main/scala-sbt-1.0",
|
|
||||||
"project/src/main/scala/",
|
"project/src/main/scala/",
|
||||||
"project/target/scala-2.12/sbt-1.0/src_managed/main"
|
"target/out/jvm/scala-3.3.1/buildserver-build/src_managed/main"
|
||||||
).map(rel => new File(svr.baseDirectory.getAbsoluteFile, rel).toURI).sorted
|
).map(rel => new File(svr.baseDirectory.getAbsoluteFile, rel).toURI).sorted
|
||||||
assert(sources == expectedSources)
|
assert(sources == expectedSources)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/compile") { _ =>
|
test("buildTarget/compile") {
|
||||||
val buildTarget = buildTargetUri("util", "Compile")
|
val buildTarget = buildTargetUri("util", "Compile")
|
||||||
|
|
||||||
compile(buildTarget, id = 32)
|
compile(buildTarget, id = 32)
|
||||||
|
|
@ -102,33 +101,31 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
assert(res.statusCode == StatusCode.Success)
|
assert(res.statusCode == StatusCode.Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/compile - reports compilation progress") { _ =>
|
test("buildTarget/compile - reports compilation progress") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||||
|
|
||||||
compile(buildTarget, id = 33)
|
compile(buildTarget, id = 33)
|
||||||
|
|
||||||
// This doesn't always come back in 10s on CI.
|
// This doesn't always come back in 10s on CI.
|
||||||
assert(svr.waitForString(60.seconds) { s =>
|
assert(svr.waitForString(20.seconds) { s =>
|
||||||
s.contains("build/taskStart") &&
|
s.contains("build/taskStart") &&
|
||||||
s.contains(""""message":"Compiling runAndTest"""")
|
s.contains(""""message":"Compiling runAndTest"""")
|
||||||
})
|
})
|
||||||
|
|
||||||
assert(svr.waitForString(60.seconds) { s =>
|
assert(svr.waitForString(20.seconds) { s =>
|
||||||
s.contains("build/taskProgress") &&
|
s.contains("build/taskProgress") &&
|
||||||
s.contains(""""message":"Compiling runAndTest (15%)"""")
|
s.contains(""""message":"Compiling runAndTest (15%)"""")
|
||||||
})
|
})
|
||||||
|
|
||||||
assert(svr.waitForString(60.seconds) { s =>
|
assert(svr.waitForString(20.seconds) { s =>
|
||||||
s.contains("build/taskProgress") &&
|
s.contains("build/taskProgress") &&
|
||||||
s.contains(""""message":"Compiling runAndTest (100%)"""")
|
s.contains(""""message":"Compiling runAndTest (100%)"""")
|
||||||
})
|
})
|
||||||
|
|
||||||
assert(svr.waitForString(60.seconds) { s =>
|
assert(svr.waitForString(20.seconds) { s =>
|
||||||
s.contains("build/publishDiagnostics")
|
s.contains("build/publishDiagnostics")
|
||||||
s.contains(""""diagnostics":[]""")
|
s.contains(""""diagnostics":[]""")
|
||||||
})
|
})
|
||||||
|
|
||||||
assert(svr.waitForString(60.seconds) { s =>
|
assert(svr.waitForString(20.seconds) { s =>
|
||||||
s.contains("build/taskFinish") &&
|
s.contains("build/taskFinish") &&
|
||||||
s.contains(""""message":"Compiled runAndTest"""")
|
s.contains(""""message":"Compiled runAndTest"""")
|
||||||
})
|
})
|
||||||
|
|
@ -136,7 +133,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
|
|
||||||
test(
|
test(
|
||||||
"buildTarget/compile [diagnostics] don't publish unnecessary for successful compilation case"
|
"buildTarget/compile [diagnostics] don't publish unnecessary for successful compilation case"
|
||||||
) { _ =>
|
) {
|
||||||
val buildTarget = buildTargetUri("diagnostics", "Compile")
|
val buildTarget = buildTargetUri("diagnostics", "Compile")
|
||||||
val mainFile = new File(svr.baseDirectory, "diagnostics/src/main/scala/Diagnostics.scala")
|
val mainFile = new File(svr.baseDirectory, "diagnostics/src/main/scala/Diagnostics.scala")
|
||||||
|
|
||||||
|
|
@ -199,7 +196,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/compile [diagnostics] clear stale warnings") { _ =>
|
test("buildTarget/compile [diagnostics] clear stale warnings") {
|
||||||
val buildTarget = buildTargetUri("diagnostics", "Compile")
|
val buildTarget = buildTargetUri("diagnostics", "Compile")
|
||||||
val testFile = new File(svr.baseDirectory, s"diagnostics/src/main/scala/PatternMatch.scala")
|
val testFile = new File(svr.baseDirectory, s"diagnostics/src/main/scala/PatternMatch.scala")
|
||||||
|
|
||||||
|
|
@ -240,7 +237,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/scalacOptions") { _ =>
|
test("buildTarget/scalacOptions") {
|
||||||
val buildTarget = buildTargetUri("util", "Compile")
|
val buildTarget = buildTargetUri("util", "Compile")
|
||||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
|
|
@ -255,20 +252,14 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/cleanCache") { _ =>
|
test("buildTarget/cleanCache") {
|
||||||
def targetDir =
|
def classFile = svr.baseDirectory.toPath.resolve(
|
||||||
Paths
|
"target/out/jvm/scala-2.13.8/runandtest/classes/main/Main.class"
|
||||||
.get(
|
)
|
||||||
svr.baseDirectory.getAbsoluteFile.toString,
|
|
||||||
"run-and-test/target/scala-2.13/classes/main"
|
|
||||||
)
|
|
||||||
.toFile
|
|
||||||
|
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||||
compile(buildTarget, id = 43)
|
compile(buildTarget, id = 43)
|
||||||
svr.waitFor[BspCompileResult](10.seconds)
|
svr.waitFor[BspCompileResult](10.seconds)
|
||||||
assert(targetDir.list().contains("Main.class"))
|
assert(Files.exists(classFile))
|
||||||
|
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
s"""{ "jsonrpc": "2.0", "id": "44", "method": "buildTarget/cleanCache", "params": {
|
s"""{ "jsonrpc": "2.0", "id": "44", "method": "buildTarget/cleanCache", "params": {
|
||||||
| "targets": [{ "uri": "$buildTarget" }]
|
| "targets": [{ "uri": "$buildTarget" }]
|
||||||
|
|
@ -277,10 +268,10 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
assert(processing("buildTarget/cleanCache"))
|
assert(processing("buildTarget/cleanCache"))
|
||||||
val res = svr.waitFor[CleanCacheResult](10.seconds)
|
val res = svr.waitFor[CleanCacheResult](10.seconds)
|
||||||
assert(res.cleaned)
|
assert(res.cleaned)
|
||||||
assert(targetDir.list().isEmpty)
|
assert(Files.notExists(classFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/cleanCache: rebuild project") { _ =>
|
test("buildTarget/cleanCache: rebuild project") {
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
"""{ "jsonrpc": "2.0", "id": "45", "method": "workspace/buildTargets", "params": {} }"""
|
"""{ "jsonrpc": "2.0", "id": "45", "method": "workspace/buildTargets", "params": {} }"""
|
||||||
)
|
)
|
||||||
|
|
@ -300,7 +291,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
assert(res.cleaned)
|
assert(res.cleaned)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("workspace/reload") { _ =>
|
test("workspace/reload") {
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
"""{ "jsonrpc": "2.0", "id": "48", "method": "workspace/reload"}"""
|
"""{ "jsonrpc": "2.0", "id": "48", "method": "workspace/reload"}"""
|
||||||
)
|
)
|
||||||
|
|
@ -311,23 +302,22 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("workspace/reload: send diagnostic and respond with error") { _ =>
|
test("workspace/reload: send diagnostic and respond with error") {
|
||||||
// write an other-build.sbt file that does not compile
|
// write an other-build.sbt file that does not compile
|
||||||
val otherBuildFile = new File(svr.baseDirectory, "other-build.sbt")
|
val otherBuildFile = svr.baseDirectory.toPath.resolve("other-build.sbt")
|
||||||
IO.write(
|
Files.writeString(
|
||||||
otherBuildFile,
|
otherBuildFile,
|
||||||
"""
|
"""|val someSettings = Seq(
|
||||||
|val someSettings = Seq(
|
| scalacOptions ++= "-deprecation"
|
||||||
| scalacOptions ++= "-deprecation"
|
|)
|
||||||
|)
|
|""".stripMargin
|
||||||
|""".stripMargin
|
|
||||||
)
|
)
|
||||||
// reload
|
// reload
|
||||||
reloadWorkspace(id = 52)
|
reloadWorkspace(id = 52)
|
||||||
assert(
|
assert(
|
||||||
svr.waitForString(10.seconds) { s =>
|
svr.waitForString(10.seconds) { s =>
|
||||||
s.contains(s""""buildTarget":{"uri":"$metaBuildTarget"}""") &&
|
s.contains(s""""buildTarget":{"uri":"$metaBuildTarget"}""") &&
|
||||||
s.contains(s""""textDocument":{"uri":"${otherBuildFile.toPath.toUri}"}""") &&
|
s.contains(s""""textDocument":{"uri":"${otherBuildFile.toUri}"}""") &&
|
||||||
s.contains(""""severity":1""") &&
|
s.contains(""""severity":1""") &&
|
||||||
s.contains(""""reset":true""")
|
s.contains(""""reset":true""")
|
||||||
}
|
}
|
||||||
|
|
@ -337,32 +327,31 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
s.contains(""""id":"52"""") &&
|
s.contains(""""id":"52"""") &&
|
||||||
s.contains(""""error"""") &&
|
s.contains(""""error"""") &&
|
||||||
s.contains(s""""code":${ErrorCodes.InternalError}""") &&
|
s.contains(s""""code":${ErrorCodes.InternalError}""") &&
|
||||||
s.contains("Type error in expression")
|
s.contains("No Append.Values[Seq[String], String] found")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// fix the other-build.sbt file and reload again
|
// fix the other-build.sbt file and reload again
|
||||||
IO.write(
|
Files.writeString(
|
||||||
otherBuildFile,
|
otherBuildFile,
|
||||||
"""
|
"""|val someSettings = Seq(
|
||||||
|val someSettings = Seq(
|
| scalacOptions += "-deprecation"
|
||||||
| scalacOptions += "-deprecation"
|
|)
|
||||||
|)
|
|""".stripMargin
|
||||||
|""".stripMargin
|
|
||||||
)
|
)
|
||||||
reloadWorkspace(id = 52)
|
reloadWorkspace(id = 52)
|
||||||
// assert received an empty diagnostic
|
// assert received an empty diagnostic
|
||||||
assert(
|
assert(
|
||||||
svr.waitForString(10.seconds) { s =>
|
svr.waitForString(10.seconds) { s =>
|
||||||
s.contains(s""""buildTarget":{"uri":"$metaBuildTarget"}""") &&
|
s.contains(s""""buildTarget":{"uri":"$metaBuildTarget"}""") &&
|
||||||
s.contains(s""""textDocument":{"uri":"${otherBuildFile.toPath.toUri}"}""") &&
|
s.contains(s""""textDocument":{"uri":"${otherBuildFile.toUri}"}""") &&
|
||||||
s.contains(""""diagnostics":[]""") &&
|
s.contains(""""diagnostics":[]""") &&
|
||||||
s.contains(""""reset":true""")
|
s.contains(""""reset":true""")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
IO.delete(otherBuildFile)
|
Files.delete(otherBuildFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/scalaMainClasses") { _ =>
|
test("buildTarget/scalaMainClasses") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
|
|
@ -377,7 +366,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/run") { _ =>
|
test("buildTarget/run") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
s"""{ "jsonrpc": "2.0", "id": "64", "method": "buildTarget/run", "params": {
|
s"""{ "jsonrpc": "2.0", "id": "64", "method": "buildTarget/run", "params": {
|
||||||
|
|
@ -397,7 +386,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/jvmRunEnvironment") { _ =>
|
test("buildTarget/jvmRunEnvironment") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
val buildTarget = buildTargetUri("runAndTest", "Compile")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
s"""|{ "jsonrpc": "2.0",
|
s"""|{ "jsonrpc": "2.0",
|
||||||
|
|
@ -418,7 +407,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/jvmTestEnvironment") { _ =>
|
test("buildTarget/jvmTestEnvironment") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Test")
|
val buildTarget = buildTargetUri("runAndTest", "Test")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
s"""|{ "jsonrpc": "2.0",
|
s"""|{ "jsonrpc": "2.0",
|
||||||
|
|
@ -441,7 +430,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/scalaTestClasses") { _ =>
|
test("buildTarget/scalaTestClasses") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Test")
|
val buildTarget = buildTargetUri("runAndTest", "Test")
|
||||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Test")
|
val badBuildTarget = buildTargetUri("badBuildTarget", "Test")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
|
|
@ -458,7 +447,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/test: run all tests") { _ =>
|
test("buildTarget/test: run all tests") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Test")
|
val buildTarget = buildTargetUri("runAndTest", "Test")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
s"""{ "jsonrpc": "2.0", "id": "80", "method": "buildTarget/test", "params": {
|
s"""{ "jsonrpc": "2.0", "id": "80", "method": "buildTarget/test", "params": {
|
||||||
|
|
@ -472,7 +461,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/test: run one test class") { _ =>
|
test("buildTarget/test: run one test class") {
|
||||||
val buildTarget = buildTargetUri("runAndTest", "Test")
|
val buildTarget = buildTargetUri("runAndTest", "Test")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
s"""{ "jsonrpc": "2.0", "id": "84", "method": "buildTarget/test", "params": {
|
s"""{ "jsonrpc": "2.0", "id": "84", "method": "buildTarget/test", "params": {
|
||||||
|
|
@ -495,7 +484,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/compile: report error") { _ =>
|
test("buildTarget/compile: report error") {
|
||||||
val buildTarget = buildTargetUri("reportError", "Compile")
|
val buildTarget = buildTargetUri("reportError", "Compile")
|
||||||
compile(buildTarget, id = 88)
|
compile(buildTarget, id = 88)
|
||||||
assert(svr.waitForString(10.seconds) { s =>
|
assert(svr.waitForString(10.seconds) { s =>
|
||||||
|
|
@ -505,7 +494,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/compile: report warning") { _ =>
|
test("buildTarget/compile: report warning") {
|
||||||
val buildTarget = buildTargetUri("reportWarning", "Compile")
|
val buildTarget = buildTargetUri("reportWarning", "Compile")
|
||||||
compile(buildTarget, id = 90)
|
compile(buildTarget, id = 90)
|
||||||
assert(svr.waitForString(10.seconds) { s =>
|
assert(svr.waitForString(10.seconds) { s =>
|
||||||
|
|
@ -515,7 +504,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/compile: respond error") { _ =>
|
test("buildTarget/compile: respond error") {
|
||||||
val buildTarget = buildTargetUri("respondError", "Compile")
|
val buildTarget = buildTargetUri("respondError", "Compile")
|
||||||
compile(buildTarget, id = 92)
|
compile(buildTarget, id = 92)
|
||||||
assert(svr.waitForString(10.seconds) { s =>
|
assert(svr.waitForString(10.seconds) { s =>
|
||||||
|
|
@ -526,7 +515,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/resources") { _ =>
|
test("buildTarget/resources") {
|
||||||
val buildTarget = buildTargetUri("util", "Compile")
|
val buildTarget = buildTargetUri("util", "Compile")
|
||||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
|
|
@ -540,7 +529,7 @@ object BuildServerTest extends AbstractServerTest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test("buildTarget/outputPaths") { _ =>
|
test("buildTarget/outputPaths") {
|
||||||
val buildTarget = buildTargetUri("util", "Compile")
|
val buildTarget = buildTargetUri("util", "Compile")
|
||||||
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
val badBuildTarget = buildTargetUri("badBuildTarget", "Compile")
|
||||||
svr.sendJsonRpc(
|
svr.sendJsonRpc(
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ trait AbstractServerTest extends AnyFunSuite with BeforeAndAfterAll {
|
||||||
def testDirectory: String
|
def testDirectory: String
|
||||||
def testPath: Path = temp.toPath.resolve(testDirectory)
|
def testPath: Path = temp.toPath.resolve(testDirectory)
|
||||||
|
|
||||||
|
def sbtVersion = sys.props
|
||||||
|
.get("sbt.server.version")
|
||||||
|
.getOrElse(throw new IllegalStateException("No server version was specified."))
|
||||||
|
|
||||||
private val targetDir: File = {
|
private val targetDir: File = {
|
||||||
val p0 = new File("..").getAbsoluteFile.getCanonicalFile / "target"
|
val p0 = new File("..").getAbsoluteFile.getCanonicalFile / "target"
|
||||||
val p1 = new File("target").getAbsoluteFile
|
val p1 = new File("target").getAbsoluteFile
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue