mirror of https://github.com/sbt/sbt.git
Merge branch '1.10.x' into wip/merge-1.10.x
This commit is contained in:
commit
2c3c0f4a7c
|
|
@ -728,7 +728,7 @@ lazy val protocolProj = (project in file("protocol"))
|
|||
// General command support and core commands not specific to a build system
|
||||
lazy val commandProj = (project in file("main-command"))
|
||||
.enablePlugins(ContrabandPlugin, JsonCodecPlugin)
|
||||
.dependsOn(protocolProj, completeProj, utilLogging, utilCache)
|
||||
.dependsOn(protocolProj, completeProj, utilLogging, runProj, utilCache)
|
||||
.settings(
|
||||
testedBaseSettings,
|
||||
name := "Command",
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ val root = (project in file(".")).
|
|||
file
|
||||
},
|
||||
// update sbt.sh at root
|
||||
sbtnVersion := "1.10.5",
|
||||
sbtnVersion := "1.10.8",
|
||||
sbtnJarsBaseUrl := "https://github.com/sbt/sbtn-dist/releases/download",
|
||||
sbtnJarsMappings := {
|
||||
val baseUrl = sbtnJarsBaseUrl.value
|
||||
|
|
|
|||
|
|
@ -476,6 +476,11 @@ if "%~0" == "new" (
|
|||
set sbt_new=true
|
||||
)
|
||||
)
|
||||
if "%~0" == "init" (
|
||||
if not defined SBT_ARGS (
|
||||
set sbt_new=true
|
||||
)
|
||||
)
|
||||
|
||||
if "%g:~0,2%" == "-D" (
|
||||
rem special handling for -D since '=' gets parsed away
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ abstract class CommandChannel {
|
|||
}
|
||||
}
|
||||
}
|
||||
protected def appendExec(commandLine: String, execId: Option[String]): Boolean =
|
||||
append(Exec(commandLine, execId.orElse(Some(Exec.newExecId)), Some(CommandSource(name))))
|
||||
def poll: Option[Exec] = Option(commandQueue.poll)
|
||||
|
||||
def prompt(e: ConsolePromptEvent): Unit = userThread.onConsolePromptEvent(e)
|
||||
|
|
@ -81,20 +83,21 @@ abstract class CommandChannel {
|
|||
private[sbt] final def logLevel: Level.Value = level.get
|
||||
private def setLevel(value: Level.Value, cmd: String): Boolean = {
|
||||
level.set(value)
|
||||
append(Exec(cmd, Some(Exec.newExecId), Some(CommandSource(name))))
|
||||
appendExec(cmd, None)
|
||||
}
|
||||
private[sbt] def onCommand: String => Boolean = {
|
||||
case "error" => setLevel(Level.Error, "error")
|
||||
case "debug" => setLevel(Level.Debug, "debug")
|
||||
case "info" => setLevel(Level.Info, "info")
|
||||
case "warn" => setLevel(Level.Warn, "warn")
|
||||
case cmd =>
|
||||
if (cmd.nonEmpty) append(Exec(cmd, Some(Exec.newExecId), Some(CommandSource(name))))
|
||||
else false
|
||||
}
|
||||
private[sbt] def onFastTrackTask: String => Boolean = { (s: String) =>
|
||||
private[sbt] def onCommandLine(cmd: String): Boolean =
|
||||
cmd match {
|
||||
case "error" => setLevel(Level.Error, "error")
|
||||
case "debug" => setLevel(Level.Debug, "debug")
|
||||
case "info" => setLevel(Level.Info, "info")
|
||||
case "warn" => setLevel(Level.Warn, "warn")
|
||||
case cmd =>
|
||||
if (cmd.nonEmpty) appendExec(cmd, None)
|
||||
else false
|
||||
}
|
||||
private[sbt] def onFastTrackTask(cmd: String): Boolean = {
|
||||
fastTrack.synchronized(fastTrack.forEach { q =>
|
||||
q.add(new FastTrackTask(this, s))
|
||||
q.add(new FastTrackTask(this, cmd))
|
||||
()
|
||||
})
|
||||
true
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ package client
|
|||
import java.io.{ File, IOException, InputStream, PrintStream }
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
import java.net.{ Socket, SocketException }
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.{ Files, Paths }
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicReference }
|
||||
import java.util.concurrent.{ ConcurrentHashMap, LinkedBlockingQueue, TimeUnit }
|
||||
|
|
@ -21,8 +21,16 @@ import java.text.DateFormat
|
|||
|
||||
import sbt.BasicCommandStrings.{ DashDashDetachStdio, DashDashServer, Shutdown, TerminateAction }
|
||||
import sbt.internal.langserver.{ LogMessageParams, MessageType, PublishDiagnosticsParams }
|
||||
import sbt.internal.worker.{ ClientJobParams, JvmRunInfo, NativeRunInfo, RunInfo }
|
||||
import sbt.internal.protocol.*
|
||||
import sbt.internal.util.{ ConsoleAppender, ConsoleOut, Signals, Terminal, Util }
|
||||
import sbt.internal.util.{
|
||||
ConsoleAppender,
|
||||
ConsoleOut,
|
||||
MessageOnlyException,
|
||||
Signals,
|
||||
Terminal,
|
||||
Util
|
||||
}
|
||||
import sbt.io.IO
|
||||
import sbt.io.syntax.*
|
||||
import sbt.protocol.*
|
||||
|
|
@ -41,6 +49,7 @@ import Serialization.{
|
|||
attach,
|
||||
cancelReadSystemIn,
|
||||
cancelRequest,
|
||||
clientJob,
|
||||
promptChannel,
|
||||
readSystemIn,
|
||||
systemIn,
|
||||
|
|
@ -61,6 +70,7 @@ import Serialization.{
|
|||
}
|
||||
import NetworkClient.Arguments
|
||||
import java.util.concurrent.TimeoutException
|
||||
import sbt.util.Logger
|
||||
|
||||
trait ConsoleInterface {
|
||||
def appendLog(level: Level.Value, message: => String): Unit
|
||||
|
|
@ -141,6 +151,7 @@ class NetworkClient(
|
|||
private lazy val noTab = arguments.completionArguments.contains("--no-tab")
|
||||
private lazy val noStdErr = arguments.completionArguments.contains("--no-stderr") &&
|
||||
!sys.env.contains("SBTN_AUTO_COMPLETE") && !sys.env.contains("SBTC_AUTO_COMPLETE")
|
||||
private def shutdownOnly = arguments.commandArguments == Seq(Shutdown)
|
||||
|
||||
private def mkSocket(file: File): (Socket, Option[String]) = ClientSocket.socket(file, useJNI)
|
||||
|
||||
|
|
@ -164,6 +175,11 @@ class NetworkClient(
|
|||
case null => inputThread.set(new RawInputThread)
|
||||
case _ =>
|
||||
}
|
||||
private lazy val log: Logger = new Logger {
|
||||
def trace(t: => Throwable): Unit = ()
|
||||
def success(message: => String): Unit = ()
|
||||
def log(level: Level.Value, message: => String): Unit = console.appendLog(level, message)
|
||||
}
|
||||
|
||||
private[sbt] def connectOrStartServerAndConnect(
|
||||
promptCompleteUsers: Boolean,
|
||||
|
|
@ -171,7 +187,10 @@ class NetworkClient(
|
|||
): (Socket, Option[String]) =
|
||||
try {
|
||||
if (!portfile.exists) {
|
||||
if (promptCompleteUsers) {
|
||||
if (shutdownOnly) {
|
||||
console.appendLog(Level.Info, "no sbt server is running. ciao")
|
||||
System.exit(0)
|
||||
} else if (promptCompleteUsers) {
|
||||
val msg = if (noTab) "" else "No sbt server is running. Press <tab> to start one..."
|
||||
errorStream.print(s"\n$msg")
|
||||
if (noStdErr) System.exit(0)
|
||||
|
|
@ -294,7 +313,18 @@ class NetworkClient(
|
|||
}
|
||||
// initiate handshake
|
||||
val execId = UUID.randomUUID.toString
|
||||
val initCommand = InitCommand(tkn, Option(execId), Some(true))
|
||||
val skipAnalysis = true
|
||||
val opts = InitializeOption(
|
||||
token = tkn,
|
||||
skipAnalysis = Some(skipAnalysis),
|
||||
canWork = Some(true),
|
||||
)
|
||||
val initCommand = InitCommand(
|
||||
token = tkn, // duplicated with opts for compatibility
|
||||
execId = Option(execId),
|
||||
skipAnalysis = Some(skipAnalysis), // duplicated with opts for compatibility
|
||||
initializationOptions = Some(opts),
|
||||
)
|
||||
conn.sendString(Serialization.serializeCommandAsJsonMessage(initCommand))
|
||||
connectionHolder.set(conn)
|
||||
conn
|
||||
|
|
@ -641,6 +671,12 @@ class NetworkClient(
|
|||
case Success(params) => splitDiagnostics(params); Vector()
|
||||
case Failure(_) => Vector()
|
||||
}
|
||||
case (`clientJob`, Some(json)) =>
|
||||
import sbt.internal.worker.codec.JsonProtocol.*
|
||||
Converter.fromJson[ClientJobParams](json) match {
|
||||
case Success(params) => clientSideRun(params).get; Vector.empty
|
||||
case Failure(_) => Vector.empty
|
||||
}
|
||||
case (`Shutdown`, Some(_)) => Vector.empty
|
||||
case (msg, _) if msg.startsWith("build/") => Vector.empty
|
||||
case _ =>
|
||||
|
|
@ -687,6 +723,59 @@ class NetworkClient(
|
|||
}
|
||||
}
|
||||
|
||||
private def clientSideRun(params: ClientJobParams): Try[Unit] =
|
||||
params.runInfo match {
|
||||
case Some(info) => clientSideRun(info)
|
||||
case _ => Failure(new MessageOnlyException(s"runInfo is not specified in $params"))
|
||||
}
|
||||
|
||||
private def clientSideRun(runInfo: RunInfo): Try[Unit] = {
|
||||
def jvmRun(info: JvmRunInfo): Try[Unit] = {
|
||||
val option = ForkOptions(
|
||||
javaHome = info.javaHome.map(new File(_)),
|
||||
outputStrategy = None, // TODO: Handle buffered output etc
|
||||
bootJars = Vector.empty,
|
||||
workingDirectory = info.workingDirectory.map(new File(_)),
|
||||
runJVMOptions = info.jvmOptions,
|
||||
connectInput = info.connectInput,
|
||||
envVars = info.environmentVariables,
|
||||
)
|
||||
// ForkRun handles exit code handling and cancellation
|
||||
val runner = new ForkRun(option)
|
||||
runner
|
||||
.run(
|
||||
mainClass = info.mainClass,
|
||||
classpath = info.classpath.map(_.path).map(Paths.get),
|
||||
options = info.args,
|
||||
log = log
|
||||
)
|
||||
}
|
||||
def nativeRun(info: NativeRunInfo): Try[Unit] = {
|
||||
import java.lang.{ ProcessBuilder as JProcessBuilder }
|
||||
val option = ForkOptions(
|
||||
javaHome = None,
|
||||
outputStrategy = None, // TODO: Handle buffered output etc
|
||||
bootJars = Vector.empty,
|
||||
workingDirectory = info.workingDirectory.map(new File(_)),
|
||||
runJVMOptions = Vector.empty,
|
||||
connectInput = info.connectInput,
|
||||
envVars = info.environmentVariables,
|
||||
)
|
||||
val command = info.cmd :: info.args.toList
|
||||
val jpb = new JProcessBuilder(command*)
|
||||
val exitCode =
|
||||
try Fork.blockForExitCode(Fork.forkInternal(option, Nil, jpb))
|
||||
catch {
|
||||
case _: InterruptedException =>
|
||||
log.warn("run canceled")
|
||||
1
|
||||
}
|
||||
Run.processExitCode(exitCode, "runner")
|
||||
}
|
||||
if (runInfo.jvm) jvmRun(runInfo.jvmRunInfo.getOrElse(sys.error("missing jvmRunInfo")))
|
||||
else nativeRun(runInfo.nativeRunInfo.getOrElse(sys.error("missing nativeRunInfo")))
|
||||
}
|
||||
|
||||
def onRequest(msg: JsonRpcRequestMessage): Unit = {
|
||||
import sbt.protocol.codec.JsonProtocol.*
|
||||
(msg.method, msg.params) match {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ trait ServerCallback {
|
|||
private[sbt] def authOptions: Set[ServerAuthentication]
|
||||
private[sbt] def authenticate(token: String): Boolean
|
||||
private[sbt] def setInitialized(value: Boolean): Unit
|
||||
private[sbt] def setInitializeOption(opts: InitializeOption): Unit
|
||||
private[sbt] def onSettingQuery(execId: Option[String], req: Q): Unit
|
||||
private[sbt] def onCompletionRequest(execId: Option[String], cp: CP): Unit
|
||||
private[sbt] def onCancellationRequest(execId: Option[String], crp: CRP): Unit
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ private[sbt] trait UITask extends Runnable with AutoCloseable {
|
|||
private[sbt] def reader: UITask.Reader
|
||||
private final def handleInput(s: Either[String, String]): Boolean = s match {
|
||||
case Left(m) => channel.onFastTrackTask(m)
|
||||
case Right(cmd) => channel.onCommand(cmd)
|
||||
case Right(cmd) => channel.onCommandLine(cmd)
|
||||
}
|
||||
private val isStopped = new AtomicBoolean(false)
|
||||
override def run(): Unit = {
|
||||
|
|
@ -56,6 +56,20 @@ private[sbt] object UITask {
|
|||
object Reader {
|
||||
// Avoid filling the stack trace since it isn't helpful here
|
||||
object interrupted extends InterruptedException
|
||||
|
||||
/**
|
||||
* Return Left for fast track commands, otherwise return Right(...).
|
||||
*/
|
||||
def splitCommand(cmd: String): Either[String, String] =
|
||||
// We need to put the empty string on the fast track queue so that we can
|
||||
// reprompt the user if another command is running on the server.
|
||||
if (cmd.isEmpty()) Left("")
|
||||
else
|
||||
cmd match {
|
||||
case Shutdown | TerminateAction | Cancel => Left(cmd)
|
||||
case cmd => Right(cmd)
|
||||
}
|
||||
|
||||
def terminalReader(parser: Parser[?])(
|
||||
terminal: Terminal,
|
||||
state: State
|
||||
|
|
@ -77,16 +91,9 @@ private[sbt] object UITask {
|
|||
this.synchronized(this.wait())
|
||||
Right("") // should be unreachable
|
||||
// JLine returns null on ctrl+d when there is no other input. This interprets
|
||||
// ctrl+d with no input as an exit
|
||||
case None => Left(TerminateAction)
|
||||
case Some(s: String) =>
|
||||
s.trim() match {
|
||||
// We need to put the empty string on the fast track queue so that we can
|
||||
// reprompt the user if another command is running on the server.
|
||||
case "" => Left("")
|
||||
case cmd @ (`Shutdown` | `TerminateAction` | `Cancel`) => Left(cmd)
|
||||
case cmd => Right(cmd)
|
||||
}
|
||||
// ctrl+d with no imput as an exit
|
||||
case None => Left(TerminateAction)
|
||||
case Some(s: String) => splitCommand(s.trim())
|
||||
}
|
||||
}
|
||||
terminal.setPrompt(Prompt.Pending)
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ abstract class BackgroundJobService extends Closeable {
|
|||
|
||||
def waitFor(job: JobHandle): Unit
|
||||
|
||||
private[sbt] def createWorkingDirectory: File
|
||||
|
||||
/** Copies classpath to temporary directories. */
|
||||
def copyClasspath(
|
||||
products: Classpath,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import sbt.internal.server.{
|
|||
BspCompileTask,
|
||||
BuildServerProtocol,
|
||||
BuildServerReporter,
|
||||
ClientJob,
|
||||
Definition,
|
||||
LanguageServerProtocol,
|
||||
ServerHandler,
|
||||
|
|
@ -240,7 +241,7 @@ object Defaults extends BuildCommon {
|
|||
getRootPaths(out, app) + ("CSR_CACHE" -> coursierCache)
|
||||
},
|
||||
fileConverter := MappedFileConverter(rootPaths.value, allowMachinePath.value)
|
||||
) ++ BuildServerProtocol.globalSettings
|
||||
) ++ BuildServerProtocol.globalSettings ++ ClientJob.globalSettings
|
||||
|
||||
private[sbt] def getRootPaths(out: NioPath, app: AppConfiguration): ListMap[String, NioPath] =
|
||||
val base = app.baseDirectory.getCanonicalFile.toPath
|
||||
|
|
@ -2648,7 +2649,7 @@ object Defaults extends BuildCommon {
|
|||
lazy val configSettings: Seq[Setting[?]] =
|
||||
Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig ++
|
||||
Classpaths.compilerPluginConfig ++ deprecationSettings ++
|
||||
BuildServerProtocol.configSettings
|
||||
BuildServerProtocol.configSettings ++ ClientJob.configSettings
|
||||
|
||||
lazy val compileSettings: Seq[Setting[?]] =
|
||||
configSettings ++ (mainBgRunMainTask +: mainBgRunTask) ++ Classpaths.addUnmanagedLibrary
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import sbt.internal.server.BuildServerProtocol.BspFullWorkspace
|
|||
import sbt.internal.server.{ BspCompileTask, BuildServerReporter, ServerHandler }
|
||||
import sbt.internal.util.{ AttributeKey, ProgressState, SourcePosition }
|
||||
import sbt.internal.util.StringAttributeKey
|
||||
import sbt.internal.worker.ClientJobParams
|
||||
import sbt.io.*
|
||||
import sbt.librarymanagement.Configurations.CompilerPlugin
|
||||
import sbt.librarymanagement.LibraryManagementCodec.*
|
||||
|
|
@ -483,6 +484,8 @@ object Keys {
|
|||
|
||||
@cacheLevel(include = Array.empty)
|
||||
val bspReporter = taskKey[BuildServerReporter]("").withRank(DTask)
|
||||
val clientJob = inputKey[ClientJobParams]("Translates a task into a job specification").withRank(Invisible)
|
||||
val clientJobRunInfo = inputKey[ClientJobParams]("Translates the run task into a job specification").withRank(Invisible)
|
||||
|
||||
val csrCacheDirectory = settingKey[File]("Coursier cache directory. Uses -Dsbt.coursier.home or Coursier's default.").withRank(CSetting)
|
||||
val csrMavenProfiles = settingKey[Set[String]]("").withRank(CSetting)
|
||||
|
|
|
|||
|
|
@ -146,6 +146,16 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
|
|||
override val isAutoCancel = false
|
||||
}
|
||||
|
||||
private[sbt] def createWorkingDirectory: File = {
|
||||
val id = nextId.getAndIncrement()
|
||||
createWorkingDirectory(id)
|
||||
}
|
||||
private[sbt] def createWorkingDirectory(id: Long): File = {
|
||||
val workingDir = serviceTempDir / s"job-$id"
|
||||
IO.createDirectory(workingDir)
|
||||
workingDir
|
||||
}
|
||||
|
||||
def doRunInBackground(
|
||||
spawningTask: ScopedKey[?],
|
||||
state: State,
|
||||
|
|
@ -155,8 +165,7 @@ private[sbt] abstract class AbstractBackgroundJobService extends BackgroundJobSe
|
|||
val extracted = Project.extract(state)
|
||||
val logger =
|
||||
LogManager.constructBackgroundLog(extracted.structure.data, state, context)(spawningTask)
|
||||
val workingDir = serviceTempDir / s"job-$id"
|
||||
IO.createDirectory(workingDir)
|
||||
val workingDir = createWorkingDirectory(id)
|
||||
val job =
|
||||
try {
|
||||
new ThreadJobHandle(id, spawningTask, logger, workingDir, start(logger, workingDir))
|
||||
|
|
|
|||
|
|
@ -13,10 +13,13 @@ import sbt.internal.bsp.*
|
|||
import sbt.librarymanagement.Configuration
|
||||
import sbt.util.InterfaceUtil
|
||||
import sjsonnew.support.scalajson.unsafe.Converter
|
||||
import xsbti.compile.{ CompileAnalysis, Inputs }
|
||||
import xsbti.{ CompileFailed, Problem, Severity }
|
||||
import xsbti.CompileFailed
|
||||
import xsbti.Problem
|
||||
import xsbti.Severity
|
||||
import xsbti.compile.CompileAnalysis
|
||||
import xsbti.compile.Inputs
|
||||
|
||||
object BspCompileTask {
|
||||
object BspCompileTask:
|
||||
def start(
|
||||
targetId: BuildTargetIdentifier,
|
||||
project: ProjectRef,
|
||||
|
|
@ -29,7 +32,7 @@ object BspCompileTask {
|
|||
task.notifyStart()
|
||||
task
|
||||
}
|
||||
}
|
||||
end BspCompileTask
|
||||
|
||||
case class BspCompileTask private (
|
||||
targetId: BuildTargetIdentifier,
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ object BuildServerProtocol {
|
|||
val result = ScalaMainClassesResult(successfulItems.toVector, None)
|
||||
state.value.respondEvent(result)
|
||||
}.evaluated,
|
||||
bspScalaMainClasses / aggregate := false
|
||||
bspScalaMainClasses / aggregate := false,
|
||||
)
|
||||
|
||||
// This will be scoped to Compile, Test, IntegrationTest etc
|
||||
|
|
@ -357,7 +357,7 @@ object BuildServerProtocol {
|
|||
} else {
|
||||
new BuildServerForwarder(meta, logger, underlying)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
private[sbt] object Method {
|
||||
final val Initialize = "build/initialize"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2023, Scala center
|
||||
* Copyright 2011 - 2022, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
package internal
|
||||
package server
|
||||
|
||||
import java.io.File
|
||||
import sbt.Def.*
|
||||
import sbt.Keys.*
|
||||
import sbt.UpperStateOps.*
|
||||
import sbt.internal.util.complete.Parser
|
||||
import sbt.internal.worker.{ ClientJobParams, FilePath, JvmRunInfo, RunInfo }
|
||||
import sbt.io.IO
|
||||
import sbt.protocol.Serialization
|
||||
import sbt.Keys.fileConverter
|
||||
|
||||
/**
|
||||
* A ClientJob represents a unit of work that sbt server process
|
||||
* can outsourse back to the client. Initially intended for sbtn client-side run.
|
||||
*/
|
||||
object ClientJob {
|
||||
lazy val globalSettings: Seq[Def.Setting[?]] = Seq(
|
||||
clientJob := clientJobTask.evaluated,
|
||||
clientJob / aggregate := false,
|
||||
)
|
||||
|
||||
private def clientJobTask: Def.Initialize[InputTask[ClientJobParams]] = Def.inputTaskDyn {
|
||||
val tokens = spaceDelimited().parsed
|
||||
val state = Keys.state.value
|
||||
val p = Act.aggregatedKeyParser(state)
|
||||
if (tokens.isEmpty) {
|
||||
sys.error("expected an argument, for example foo/run")
|
||||
}
|
||||
val scopedKey = Parser.parse(tokens.head, p) match {
|
||||
case Right(x :: Nil) => x
|
||||
case Right(xs) => sys.error("too many keys")
|
||||
case Left(err) => sys.error(err)
|
||||
}
|
||||
if (scopedKey.key == run.key)
|
||||
clientJobRunInfo.rescope(scopedKey.scope).toTask(" " + tokens.tail.mkString(" "))
|
||||
else sys.error(s"unsupported task for clientJob $scopedKey")
|
||||
}
|
||||
|
||||
// This will be scoped to Compile, Test, etc
|
||||
lazy val configSettings: Seq[Def.Setting[?]] = Seq(
|
||||
clientJobRunInfo := clientJobRunInfoTask.evaluated,
|
||||
)
|
||||
|
||||
private def clientJobRunInfoTask: Def.Initialize[InputTask[ClientJobParams]] = Def.inputTask {
|
||||
val state = Keys.state.value
|
||||
val args = spaceDelimited().parsed
|
||||
val mainClass = (Keys.run / Keys.mainClass).value
|
||||
val service = bgJobService.value
|
||||
val fo = (Keys.run / Keys.forkOptions).value
|
||||
val workingDir = service.createWorkingDirectory
|
||||
val conv = fileConverter.value
|
||||
val cp = service.copyClasspath(
|
||||
exportedProductJars.value,
|
||||
fullClasspathAsJars.value,
|
||||
workingDir,
|
||||
conv,
|
||||
)
|
||||
val strategy = fo.outputStrategy.map(_.getClass().getSimpleName().filter(_ != '$'))
|
||||
// sbtn doesn't set java.home, so we need to do the fallback here
|
||||
val javaHome =
|
||||
fo.javaHome.map(IO.toURI).orElse(sys.props.get("java.home").map(x => IO.toURI(new File(x))))
|
||||
val jvmRunInfo = JvmRunInfo(
|
||||
args = args.toVector,
|
||||
classpath = cp.map(x => IO.toURI(conv.toPath(x.data).toFile)).map(FilePath(_, "")).toVector,
|
||||
mainClass = mainClass.getOrElse(sys.error("no main class")),
|
||||
connectInput = fo.connectInput,
|
||||
javaHome = javaHome,
|
||||
outputStrategy = strategy,
|
||||
workingDirectory = fo.workingDirectory.map(IO.toURI),
|
||||
jvmOptions = fo.runJVMOptions,
|
||||
environmentVariables = fo.envVars.toMap,
|
||||
)
|
||||
val info = RunInfo(
|
||||
jvm = true,
|
||||
jvmRunInfo = jvmRunInfo,
|
||||
)
|
||||
val result = ClientJobParams(
|
||||
runInfo = info
|
||||
)
|
||||
import sbt.internal.worker.codec.JsonProtocol.*
|
||||
state.notifyEvent(Serialization.clientJob, result)
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,7 @@ private[sbt] object LanguageServerProtocol {
|
|||
else throw LangServerError(ErrorCodes.InvalidRequest, "invalid token")
|
||||
} else ()
|
||||
setInitialized(true)
|
||||
setInitializeOption(opt)
|
||||
if (!opt.skipAnalysis.getOrElse(false)) appendExec("collectAnalyses", None)
|
||||
jsonRpcRespond(InitializeResult(serverCapabilities), Some(r.id))
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import sbt.BasicCommandStrings.{ Shutdown, TerminateAction }
|
|||
import sbt.ProjectExtra.extract
|
||||
import sbt.internal.langserver.{ CancelRequestParams, ErrorCodes, LogMessageParams, MessageType }
|
||||
import sbt.internal.protocol.{
|
||||
InitializeOption,
|
||||
JsonRpcNotificationMessage,
|
||||
JsonRpcRequestMessage,
|
||||
JsonRpcResponseError,
|
||||
|
|
@ -85,6 +86,11 @@ final class NetworkChannel(
|
|||
private val delimiter: Byte = '\n'.toByte
|
||||
private val out = connection.getOutputStream
|
||||
private var initialized = false
|
||||
|
||||
/**
|
||||
* Reference to the client-side custom options
|
||||
*/
|
||||
private val initializeOption = new AtomicReference[InitializeOption](null)
|
||||
private val pendingRequests: mutable.Map[String, JsonRpcRequestMessage] = mutable.Map()
|
||||
|
||||
private val inputBuffer = new LinkedBlockingQueue[Int]()
|
||||
|
|
@ -126,7 +132,7 @@ final class NetworkChannel(
|
|||
self.jsonRpcNotify(method, params)
|
||||
|
||||
def appendExec(commandLine: String, execId: Option[String]): Boolean =
|
||||
self.append(Exec(commandLine, execId, Some(CommandSource(name))))
|
||||
self.appendExec(commandLine, execId)
|
||||
|
||||
def appendExec(exec: Exec): Boolean = self.append(exec)
|
||||
|
||||
|
|
@ -135,6 +141,8 @@ final class NetworkChannel(
|
|||
private[sbt] def authOptions: Set[ServerAuthentication] = self.authOptions
|
||||
private[sbt] def authenticate(token: String): Boolean = self.authenticate(token)
|
||||
private[sbt] def setInitialized(value: Boolean): Unit = self.setInitialized(value)
|
||||
private[sbt] def setInitializeOption(opts: InitializeOption): Unit =
|
||||
self.setInitializeOption(opts)
|
||||
private[sbt] def onSettingQuery(execId: Option[String], req: SettingQuery): Unit =
|
||||
self.onSettingQuery(execId, req)
|
||||
private[sbt] def onCompletionRequest(execId: Option[String], cp: CompletionParams): Unit =
|
||||
|
|
@ -143,6 +151,15 @@ final class NetworkChannel(
|
|||
self.onCancellationRequest(execId, crp)
|
||||
}
|
||||
|
||||
protected def setInitializeOption(opts: InitializeOption): Unit = initializeOption.set(opts)
|
||||
|
||||
// Returns true if sbtn has declared with canWork: true
|
||||
protected def clientCanWork: Boolean =
|
||||
Option(initializeOption.get) match {
|
||||
case Some(opts) => opts.canWork.getOrElse(false)
|
||||
case _ => false
|
||||
}
|
||||
|
||||
protected def authenticate(token: String): Boolean = instance.authenticate(token)
|
||||
|
||||
protected def setInitialized(value: Boolean): Unit = initialized = value
|
||||
|
|
@ -374,40 +391,6 @@ final class NetworkChannel(
|
|||
try pendingWrites.put(event -> delimit)
|
||||
catch { case _: InterruptedException => }
|
||||
|
||||
def onCommand(command: CommandMessage): Unit = command match {
|
||||
case x: InitCommand => onInitCommand(x)
|
||||
case x: ExecCommand => onExecCommand(x)
|
||||
case x: SettingQuery => onSettingQuery(None, x)
|
||||
}
|
||||
|
||||
private def onInitCommand(cmd: InitCommand): Unit = {
|
||||
if (auth(ServerAuthentication.Token)) {
|
||||
cmd.token match {
|
||||
case Some(x) =>
|
||||
authenticate(x) match {
|
||||
case true =>
|
||||
initialized = true
|
||||
notifyEvent(ChannelAcceptedEvent(name))
|
||||
case _ => sys.error("invalid token")
|
||||
}
|
||||
case None => sys.error("init command but without token.")
|
||||
}
|
||||
} else {
|
||||
initialized = true
|
||||
}
|
||||
}
|
||||
|
||||
private def onExecCommand(cmd: ExecCommand) = {
|
||||
if (initialized) {
|
||||
append(
|
||||
Exec(cmd.commandLine, cmd.execId orElse Some(Exec.newExecId), Some(CommandSource(name)))
|
||||
)
|
||||
()
|
||||
} else {
|
||||
log.warn(s"ignoring command $cmd before initialization")
|
||||
}
|
||||
}
|
||||
|
||||
protected def onSettingQuery(execId: Option[String], req: SettingQuery) = {
|
||||
if (initialized) {
|
||||
StandardMain.exchange.withState { s =>
|
||||
|
|
|
|||
|
|
@ -4,24 +4,30 @@
|
|||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.protocol
|
||||
/**
|
||||
* Passed into InitializeParams as part of "initialize" request as the user-defined option.
|
||||
* https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
|
||||
*/
|
||||
final class InitializeOption private (
|
||||
val token: Option[String],
|
||||
val skipAnalysis: Option[Boolean]) extends Serializable {
|
||||
val skipAnalysis: Option[Boolean],
|
||||
val canWork: Option[Boolean]) extends Serializable {
|
||||
|
||||
private def this(token: Option[String]) = this(token, None)
|
||||
private def this(token: Option[String]) = this(token, None, None)
|
||||
private def this(token: Option[String], skipAnalysis: Option[Boolean]) = this(token, skipAnalysis, None)
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: InitializeOption => (this.token == x.token) && (this.skipAnalysis == x.skipAnalysis)
|
||||
case x: InitializeOption => (this.token == x.token) && (this.skipAnalysis == x.skipAnalysis) && (this.canWork == x.canWork)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.protocol.InitializeOption".##) + token.##) + skipAnalysis.##)
|
||||
37 * (37 * (37 * (37 * (17 + "sbt.internal.protocol.InitializeOption".##) + token.##) + skipAnalysis.##) + canWork.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"InitializeOption(" + token + ", " + skipAnalysis + ")"
|
||||
"InitializeOption(" + token + ", " + skipAnalysis + ", " + canWork + ")"
|
||||
}
|
||||
private def copy(token: Option[String] = token, skipAnalysis: Option[Boolean] = skipAnalysis): InitializeOption = {
|
||||
new InitializeOption(token, skipAnalysis)
|
||||
private def copy(token: Option[String] = token, skipAnalysis: Option[Boolean] = skipAnalysis, canWork: Option[Boolean] = canWork): InitializeOption = {
|
||||
new InitializeOption(token, skipAnalysis, canWork)
|
||||
}
|
||||
def withToken(token: Option[String]): InitializeOption = {
|
||||
copy(token = token)
|
||||
|
|
@ -35,6 +41,12 @@ final class InitializeOption private (
|
|||
def withSkipAnalysis(skipAnalysis: Boolean): InitializeOption = {
|
||||
copy(skipAnalysis = Option(skipAnalysis))
|
||||
}
|
||||
def withCanWork(canWork: Option[Boolean]): InitializeOption = {
|
||||
copy(canWork = canWork)
|
||||
}
|
||||
def withCanWork(canWork: Boolean): InitializeOption = {
|
||||
copy(canWork = Option(canWork))
|
||||
}
|
||||
}
|
||||
object InitializeOption {
|
||||
|
||||
|
|
@ -42,4 +54,6 @@ object InitializeOption {
|
|||
def apply(token: String): InitializeOption = new InitializeOption(Option(token))
|
||||
def apply(token: Option[String], skipAnalysis: Option[Boolean]): InitializeOption = new InitializeOption(token, skipAnalysis)
|
||||
def apply(token: String, skipAnalysis: Boolean): InitializeOption = new InitializeOption(Option(token), Option(skipAnalysis))
|
||||
def apply(token: Option[String], skipAnalysis: Option[Boolean], canWork: Option[Boolean]): InitializeOption = new InitializeOption(token, skipAnalysis, canWork)
|
||||
def apply(token: String, skipAnalysis: Boolean, canWork: Boolean): InitializeOption = new InitializeOption(Option(token), Option(skipAnalysis), Option(canWork))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ implicit lazy val InitializeOptionFormat: JsonFormat[sbt.internal.protocol.Initi
|
|||
unbuilder.beginObject(__js)
|
||||
val token = unbuilder.readField[Option[String]]("token")
|
||||
val skipAnalysis = unbuilder.readField[Option[Boolean]]("skipAnalysis")
|
||||
val canWork = unbuilder.readField[Option[Boolean]]("canWork")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.protocol.InitializeOption(token, skipAnalysis)
|
||||
sbt.internal.protocol.InitializeOption(token, skipAnalysis, canWork)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
|
|
@ -23,6 +24,7 @@ implicit lazy val InitializeOptionFormat: JsonFormat[sbt.internal.protocol.Initi
|
|||
builder.beginObject()
|
||||
builder.addField("token", obj.token)
|
||||
builder.addField("skipAnalysis", obj.skipAnalysis)
|
||||
builder.addField("canWork", obj.canWork)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
45
protocol/src/main/contraband-scala/sbt/internal/worker/ClientJobParams.scala
generated
Normal file
45
protocol/src/main/contraband-scala/sbt/internal/worker/ClientJobParams.scala
generated
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker
|
||||
/**
|
||||
* Client-side job support.
|
||||
*
|
||||
* Notification: sbt/clientJob
|
||||
*
|
||||
* Parameter for the sbt/clientJob notification.
|
||||
* A client-side job represents a unit of work that sbt server
|
||||
* can outsourse back to the client, for example for run task.
|
||||
*/
|
||||
final class ClientJobParams private (
|
||||
val runInfo: Option[sbt.internal.worker.RunInfo]) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: ClientJobParams => (this.runInfo == x.runInfo)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (17 + "sbt.internal.worker.ClientJobParams".##) + runInfo.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"ClientJobParams(" + runInfo + ")"
|
||||
}
|
||||
private def copy(runInfo: Option[sbt.internal.worker.RunInfo] = runInfo): ClientJobParams = {
|
||||
new ClientJobParams(runInfo)
|
||||
}
|
||||
def withRunInfo(runInfo: Option[sbt.internal.worker.RunInfo]): ClientJobParams = {
|
||||
copy(runInfo = runInfo)
|
||||
}
|
||||
def withRunInfo(runInfo: sbt.internal.worker.RunInfo): ClientJobParams = {
|
||||
copy(runInfo = Option(runInfo))
|
||||
}
|
||||
}
|
||||
object ClientJobParams {
|
||||
|
||||
def apply(runInfo: Option[sbt.internal.worker.RunInfo]): ClientJobParams = new ClientJobParams(runInfo)
|
||||
def apply(runInfo: sbt.internal.worker.RunInfo): ClientJobParams = new ClientJobParams(Option(runInfo))
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker
|
||||
final class FilePath private (
|
||||
val path: java.net.URI,
|
||||
val digest: String) extends Serializable {
|
||||
|
||||
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: FilePath => (this.path == x.path) && (this.digest == x.digest)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (17 + "sbt.internal.worker.FilePath".##) + path.##) + digest.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"FilePath(" + path + ", " + digest + ")"
|
||||
}
|
||||
private def copy(path: java.net.URI = path, digest: String = digest): FilePath = {
|
||||
new FilePath(path, digest)
|
||||
}
|
||||
def withPath(path: java.net.URI): FilePath = {
|
||||
copy(path = path)
|
||||
}
|
||||
def withDigest(digest: String): FilePath = {
|
||||
copy(digest = digest)
|
||||
}
|
||||
}
|
||||
object FilePath {
|
||||
|
||||
def apply(path: java.net.URI, digest: String): FilePath = new FilePath(path, digest)
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker
|
||||
final class JvmRunInfo private (
|
||||
val args: Vector[String],
|
||||
val classpath: Vector[sbt.internal.worker.FilePath],
|
||||
val mainClass: String,
|
||||
val connectInput: Boolean,
|
||||
val javaHome: Option[java.net.URI],
|
||||
val outputStrategy: Option[String],
|
||||
val workingDirectory: Option[java.net.URI],
|
||||
val jvmOptions: Vector[String],
|
||||
val environmentVariables: scala.collection.immutable.Map[String, String],
|
||||
val inputs: Vector[sbt.internal.worker.FilePath],
|
||||
val outputs: Vector[sbt.internal.worker.FilePath]) extends Serializable {
|
||||
|
||||
private def this(args: Vector[String], classpath: Vector[sbt.internal.worker.FilePath], mainClass: String, connectInput: Boolean, javaHome: Option[java.net.URI], outputStrategy: Option[String], workingDirectory: Option[java.net.URI], jvmOptions: Vector[String], environmentVariables: scala.collection.immutable.Map[String, String]) = this(args, classpath, mainClass, connectInput, javaHome, outputStrategy, workingDirectory, jvmOptions, environmentVariables, Vector(), Vector())
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: JvmRunInfo => (this.args == x.args) && (this.classpath == x.classpath) && (this.mainClass == x.mainClass) && (this.connectInput == x.connectInput) && (this.javaHome == x.javaHome) && (this.outputStrategy == x.outputStrategy) && (this.workingDirectory == x.workingDirectory) && (this.jvmOptions == x.jvmOptions) && (this.environmentVariables == x.environmentVariables) && (this.inputs == x.inputs) && (this.outputs == x.outputs)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.worker.JvmRunInfo".##) + args.##) + classpath.##) + mainClass.##) + connectInput.##) + javaHome.##) + outputStrategy.##) + workingDirectory.##) + jvmOptions.##) + environmentVariables.##) + inputs.##) + outputs.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"JvmRunInfo(" + args + ", " + classpath + ", " + mainClass + ", " + connectInput + ", " + javaHome + ", " + outputStrategy + ", " + workingDirectory + ", " + jvmOptions + ", " + environmentVariables + ", " + inputs + ", " + outputs + ")"
|
||||
}
|
||||
private def copy(args: Vector[String] = args, classpath: Vector[sbt.internal.worker.FilePath] = classpath, mainClass: String = mainClass, connectInput: Boolean = connectInput, javaHome: Option[java.net.URI] = javaHome, outputStrategy: Option[String] = outputStrategy, workingDirectory: Option[java.net.URI] = workingDirectory, jvmOptions: Vector[String] = jvmOptions, environmentVariables: scala.collection.immutable.Map[String, String] = environmentVariables, inputs: Vector[sbt.internal.worker.FilePath] = inputs, outputs: Vector[sbt.internal.worker.FilePath] = outputs): JvmRunInfo = {
|
||||
new JvmRunInfo(args, classpath, mainClass, connectInput, javaHome, outputStrategy, workingDirectory, jvmOptions, environmentVariables, inputs, outputs)
|
||||
}
|
||||
def withArgs(args: Vector[String]): JvmRunInfo = {
|
||||
copy(args = args)
|
||||
}
|
||||
def withClasspath(classpath: Vector[sbt.internal.worker.FilePath]): JvmRunInfo = {
|
||||
copy(classpath = classpath)
|
||||
}
|
||||
def withMainClass(mainClass: String): JvmRunInfo = {
|
||||
copy(mainClass = mainClass)
|
||||
}
|
||||
def withConnectInput(connectInput: Boolean): JvmRunInfo = {
|
||||
copy(connectInput = connectInput)
|
||||
}
|
||||
def withJavaHome(javaHome: Option[java.net.URI]): JvmRunInfo = {
|
||||
copy(javaHome = javaHome)
|
||||
}
|
||||
def withJavaHome(javaHome: java.net.URI): JvmRunInfo = {
|
||||
copy(javaHome = Option(javaHome))
|
||||
}
|
||||
def withOutputStrategy(outputStrategy: Option[String]): JvmRunInfo = {
|
||||
copy(outputStrategy = outputStrategy)
|
||||
}
|
||||
def withOutputStrategy(outputStrategy: String): JvmRunInfo = {
|
||||
copy(outputStrategy = Option(outputStrategy))
|
||||
}
|
||||
def withWorkingDirectory(workingDirectory: Option[java.net.URI]): JvmRunInfo = {
|
||||
copy(workingDirectory = workingDirectory)
|
||||
}
|
||||
def withWorkingDirectory(workingDirectory: java.net.URI): JvmRunInfo = {
|
||||
copy(workingDirectory = Option(workingDirectory))
|
||||
}
|
||||
def withJvmOptions(jvmOptions: Vector[String]): JvmRunInfo = {
|
||||
copy(jvmOptions = jvmOptions)
|
||||
}
|
||||
def withEnvironmentVariables(environmentVariables: scala.collection.immutable.Map[String, String]): JvmRunInfo = {
|
||||
copy(environmentVariables = environmentVariables)
|
||||
}
|
||||
def withInputs(inputs: Vector[sbt.internal.worker.FilePath]): JvmRunInfo = {
|
||||
copy(inputs = inputs)
|
||||
}
|
||||
def withOutputs(outputs: Vector[sbt.internal.worker.FilePath]): JvmRunInfo = {
|
||||
copy(outputs = outputs)
|
||||
}
|
||||
}
|
||||
object JvmRunInfo {
|
||||
|
||||
def apply(args: Vector[String], classpath: Vector[sbt.internal.worker.FilePath], mainClass: String, connectInput: Boolean, javaHome: Option[java.net.URI], outputStrategy: Option[String], workingDirectory: Option[java.net.URI], jvmOptions: Vector[String], environmentVariables: scala.collection.immutable.Map[String, String]): JvmRunInfo = new JvmRunInfo(args, classpath, mainClass, connectInput, javaHome, outputStrategy, workingDirectory, jvmOptions, environmentVariables)
|
||||
def apply(args: Vector[String], classpath: Vector[sbt.internal.worker.FilePath], mainClass: String, connectInput: Boolean, javaHome: java.net.URI, outputStrategy: String, workingDirectory: java.net.URI, jvmOptions: Vector[String], environmentVariables: scala.collection.immutable.Map[String, String]): JvmRunInfo = new JvmRunInfo(args, classpath, mainClass, connectInput, Option(javaHome), Option(outputStrategy), Option(workingDirectory), jvmOptions, environmentVariables)
|
||||
def apply(args: Vector[String], classpath: Vector[sbt.internal.worker.FilePath], mainClass: String, connectInput: Boolean, javaHome: Option[java.net.URI], outputStrategy: Option[String], workingDirectory: Option[java.net.URI], jvmOptions: Vector[String], environmentVariables: scala.collection.immutable.Map[String, String], inputs: Vector[sbt.internal.worker.FilePath], outputs: Vector[sbt.internal.worker.FilePath]): JvmRunInfo = new JvmRunInfo(args, classpath, mainClass, connectInput, javaHome, outputStrategy, workingDirectory, jvmOptions, environmentVariables, inputs, outputs)
|
||||
def apply(args: Vector[String], classpath: Vector[sbt.internal.worker.FilePath], mainClass: String, connectInput: Boolean, javaHome: java.net.URI, outputStrategy: String, workingDirectory: java.net.URI, jvmOptions: Vector[String], environmentVariables: scala.collection.immutable.Map[String, String], inputs: Vector[sbt.internal.worker.FilePath], outputs: Vector[sbt.internal.worker.FilePath]): JvmRunInfo = new JvmRunInfo(args, classpath, mainClass, connectInput, Option(javaHome), Option(outputStrategy), Option(workingDirectory), jvmOptions, environmentVariables, inputs, outputs)
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker
|
||||
final class NativeRunInfo private (
|
||||
val cmd: String,
|
||||
val args: Vector[String],
|
||||
val connectInput: Boolean,
|
||||
val outputStrategy: Option[String],
|
||||
val workingDirectory: Option[java.net.URI],
|
||||
val environmentVariables: scala.collection.immutable.Map[String, String],
|
||||
val inputs: Vector[sbt.internal.worker.FilePath],
|
||||
val outputs: Vector[sbt.internal.worker.FilePath]) extends Serializable {
|
||||
|
||||
private def this(cmd: String, args: Vector[String], connectInput: Boolean, outputStrategy: Option[String], workingDirectory: Option[java.net.URI], environmentVariables: scala.collection.immutable.Map[String, String]) = this(cmd, args, connectInput, outputStrategy, workingDirectory, environmentVariables, Vector(), Vector())
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: NativeRunInfo => (this.cmd == x.cmd) && (this.args == x.args) && (this.connectInput == x.connectInput) && (this.outputStrategy == x.outputStrategy) && (this.workingDirectory == x.workingDirectory) && (this.environmentVariables == x.environmentVariables) && (this.inputs == x.inputs) && (this.outputs == x.outputs)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.worker.NativeRunInfo".##) + cmd.##) + args.##) + connectInput.##) + outputStrategy.##) + workingDirectory.##) + environmentVariables.##) + inputs.##) + outputs.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"NativeRunInfo(" + cmd + ", " + args + ", " + connectInput + ", " + outputStrategy + ", " + workingDirectory + ", " + environmentVariables + ", " + inputs + ", " + outputs + ")"
|
||||
}
|
||||
private def copy(cmd: String = cmd, args: Vector[String] = args, connectInput: Boolean = connectInput, outputStrategy: Option[String] = outputStrategy, workingDirectory: Option[java.net.URI] = workingDirectory, environmentVariables: scala.collection.immutable.Map[String, String] = environmentVariables, inputs: Vector[sbt.internal.worker.FilePath] = inputs, outputs: Vector[sbt.internal.worker.FilePath] = outputs): NativeRunInfo = {
|
||||
new NativeRunInfo(cmd, args, connectInput, outputStrategy, workingDirectory, environmentVariables, inputs, outputs)
|
||||
}
|
||||
def withCmd(cmd: String): NativeRunInfo = {
|
||||
copy(cmd = cmd)
|
||||
}
|
||||
def withArgs(args: Vector[String]): NativeRunInfo = {
|
||||
copy(args = args)
|
||||
}
|
||||
def withConnectInput(connectInput: Boolean): NativeRunInfo = {
|
||||
copy(connectInput = connectInput)
|
||||
}
|
||||
def withOutputStrategy(outputStrategy: Option[String]): NativeRunInfo = {
|
||||
copy(outputStrategy = outputStrategy)
|
||||
}
|
||||
def withOutputStrategy(outputStrategy: String): NativeRunInfo = {
|
||||
copy(outputStrategy = Option(outputStrategy))
|
||||
}
|
||||
def withWorkingDirectory(workingDirectory: Option[java.net.URI]): NativeRunInfo = {
|
||||
copy(workingDirectory = workingDirectory)
|
||||
}
|
||||
def withWorkingDirectory(workingDirectory: java.net.URI): NativeRunInfo = {
|
||||
copy(workingDirectory = Option(workingDirectory))
|
||||
}
|
||||
def withEnvironmentVariables(environmentVariables: scala.collection.immutable.Map[String, String]): NativeRunInfo = {
|
||||
copy(environmentVariables = environmentVariables)
|
||||
}
|
||||
def withInputs(inputs: Vector[sbt.internal.worker.FilePath]): NativeRunInfo = {
|
||||
copy(inputs = inputs)
|
||||
}
|
||||
def withOutputs(outputs: Vector[sbt.internal.worker.FilePath]): NativeRunInfo = {
|
||||
copy(outputs = outputs)
|
||||
}
|
||||
}
|
||||
object NativeRunInfo {
|
||||
|
||||
def apply(cmd: String, args: Vector[String], connectInput: Boolean, outputStrategy: Option[String], workingDirectory: Option[java.net.URI], environmentVariables: scala.collection.immutable.Map[String, String]): NativeRunInfo = new NativeRunInfo(cmd, args, connectInput, outputStrategy, workingDirectory, environmentVariables)
|
||||
def apply(cmd: String, args: Vector[String], connectInput: Boolean, outputStrategy: String, workingDirectory: java.net.URI, environmentVariables: scala.collection.immutable.Map[String, String]): NativeRunInfo = new NativeRunInfo(cmd, args, connectInput, Option(outputStrategy), Option(workingDirectory), environmentVariables)
|
||||
def apply(cmd: String, args: Vector[String], connectInput: Boolean, outputStrategy: Option[String], workingDirectory: Option[java.net.URI], environmentVariables: scala.collection.immutable.Map[String, String], inputs: Vector[sbt.internal.worker.FilePath], outputs: Vector[sbt.internal.worker.FilePath]): NativeRunInfo = new NativeRunInfo(cmd, args, connectInput, outputStrategy, workingDirectory, environmentVariables, inputs, outputs)
|
||||
def apply(cmd: String, args: Vector[String], connectInput: Boolean, outputStrategy: String, workingDirectory: java.net.URI, environmentVariables: scala.collection.immutable.Map[String, String], inputs: Vector[sbt.internal.worker.FilePath], outputs: Vector[sbt.internal.worker.FilePath]): NativeRunInfo = new NativeRunInfo(cmd, args, connectInput, Option(outputStrategy), Option(workingDirectory), environmentVariables, inputs, outputs)
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker
|
||||
final class RunInfo private (
|
||||
val jvm: Boolean,
|
||||
val jvmRunInfo: Option[sbt.internal.worker.JvmRunInfo],
|
||||
val nativeRunInfo: Option[sbt.internal.worker.NativeRunInfo]) extends Serializable {
|
||||
|
||||
private def this(jvm: Boolean, jvmRunInfo: Option[sbt.internal.worker.JvmRunInfo]) = this(jvm, jvmRunInfo, None)
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: RunInfo => (this.jvm == x.jvm) && (this.jvmRunInfo == x.jvmRunInfo) && (this.nativeRunInfo == x.nativeRunInfo)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (37 * (17 + "sbt.internal.worker.RunInfo".##) + jvm.##) + jvmRunInfo.##) + nativeRunInfo.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"RunInfo(" + jvm + ", " + jvmRunInfo + ", " + nativeRunInfo + ")"
|
||||
}
|
||||
private def copy(jvm: Boolean = jvm, jvmRunInfo: Option[sbt.internal.worker.JvmRunInfo] = jvmRunInfo, nativeRunInfo: Option[sbt.internal.worker.NativeRunInfo] = nativeRunInfo): RunInfo = {
|
||||
new RunInfo(jvm, jvmRunInfo, nativeRunInfo)
|
||||
}
|
||||
def withJvm(jvm: Boolean): RunInfo = {
|
||||
copy(jvm = jvm)
|
||||
}
|
||||
def withJvmRunInfo(jvmRunInfo: Option[sbt.internal.worker.JvmRunInfo]): RunInfo = {
|
||||
copy(jvmRunInfo = jvmRunInfo)
|
||||
}
|
||||
def withJvmRunInfo(jvmRunInfo: sbt.internal.worker.JvmRunInfo): RunInfo = {
|
||||
copy(jvmRunInfo = Option(jvmRunInfo))
|
||||
}
|
||||
def withNativeRunInfo(nativeRunInfo: Option[sbt.internal.worker.NativeRunInfo]): RunInfo = {
|
||||
copy(nativeRunInfo = nativeRunInfo)
|
||||
}
|
||||
def withNativeRunInfo(nativeRunInfo: sbt.internal.worker.NativeRunInfo): RunInfo = {
|
||||
copy(nativeRunInfo = Option(nativeRunInfo))
|
||||
}
|
||||
}
|
||||
object RunInfo {
|
||||
|
||||
def apply(jvm: Boolean, jvmRunInfo: Option[sbt.internal.worker.JvmRunInfo]): RunInfo = new RunInfo(jvm, jvmRunInfo)
|
||||
def apply(jvm: Boolean, jvmRunInfo: sbt.internal.worker.JvmRunInfo): RunInfo = new RunInfo(jvm, Option(jvmRunInfo))
|
||||
def apply(jvm: Boolean, jvmRunInfo: Option[sbt.internal.worker.JvmRunInfo], nativeRunInfo: Option[sbt.internal.worker.NativeRunInfo]): RunInfo = new RunInfo(jvm, jvmRunInfo, nativeRunInfo)
|
||||
def apply(jvm: Boolean, jvmRunInfo: sbt.internal.worker.JvmRunInfo, nativeRunInfo: sbt.internal.worker.NativeRunInfo): RunInfo = new RunInfo(jvm, Option(jvmRunInfo), Option(nativeRunInfo))
|
||||
}
|
||||
27
protocol/src/main/contraband-scala/sbt/internal/worker/codec/ClientJobParamsFormats.scala
generated
Normal file
27
protocol/src/main/contraband-scala/sbt/internal/worker/codec/ClientJobParamsFormats.scala
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait ClientJobParamsFormats { self: sbt.internal.worker.codec.RunInfoFormats & sbt.internal.worker.codec.JvmRunInfoFormats & sbt.internal.worker.codec.FilePathFormats & sjsonnew.BasicJsonProtocol & sbt.internal.worker.codec.NativeRunInfoFormats =>
|
||||
implicit lazy val ClientJobParamsFormat: JsonFormat[sbt.internal.worker.ClientJobParams] = new JsonFormat[sbt.internal.worker.ClientJobParams] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.worker.ClientJobParams = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val runInfo = unbuilder.readField[Option[sbt.internal.worker.RunInfo]]("runInfo")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.worker.ClientJobParams(runInfo)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.worker.ClientJobParams, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("runInfo", obj.runInfo)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
29
protocol/src/main/contraband-scala/sbt/internal/worker/codec/FilePathFormats.scala
generated
Normal file
29
protocol/src/main/contraband-scala/sbt/internal/worker/codec/FilePathFormats.scala
generated
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait FilePathFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val FilePathFormat: JsonFormat[sbt.internal.worker.FilePath] = new JsonFormat[sbt.internal.worker.FilePath] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.worker.FilePath = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val path = unbuilder.readField[java.net.URI]("path")
|
||||
val digest = unbuilder.readField[String]("digest")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.worker.FilePath(path, digest)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.worker.FilePath, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("path", obj.path)
|
||||
builder.addField("digest", obj.digest)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
13
protocol/src/main/contraband-scala/sbt/internal/worker/codec/JsonProtocol.scala
generated
Normal file
13
protocol/src/main/contraband-scala/sbt/internal/worker/codec/JsonProtocol.scala
generated
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker.codec
|
||||
trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
||||
with sbt.internal.worker.codec.FilePathFormats
|
||||
with sbt.internal.worker.codec.JvmRunInfoFormats
|
||||
with sbt.internal.worker.codec.NativeRunInfoFormats
|
||||
with sbt.internal.worker.codec.RunInfoFormats
|
||||
with sbt.internal.worker.codec.ClientJobParamsFormats
|
||||
object JsonProtocol extends JsonProtocol
|
||||
47
protocol/src/main/contraband-scala/sbt/internal/worker/codec/JvmRunInfoFormats.scala
generated
Normal file
47
protocol/src/main/contraband-scala/sbt/internal/worker/codec/JvmRunInfoFormats.scala
generated
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait JvmRunInfoFormats { self: sbt.internal.worker.codec.FilePathFormats & sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val JvmRunInfoFormat: JsonFormat[sbt.internal.worker.JvmRunInfo] = new JsonFormat[sbt.internal.worker.JvmRunInfo] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.worker.JvmRunInfo = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val args = unbuilder.readField[Vector[String]]("args")
|
||||
val classpath = unbuilder.readField[Vector[sbt.internal.worker.FilePath]]("classpath")
|
||||
val mainClass = unbuilder.readField[String]("mainClass")
|
||||
val connectInput = unbuilder.readField[Boolean]("connectInput")
|
||||
val javaHome = unbuilder.readField[Option[java.net.URI]]("javaHome")
|
||||
val outputStrategy = unbuilder.readField[Option[String]]("outputStrategy")
|
||||
val workingDirectory = unbuilder.readField[Option[java.net.URI]]("workingDirectory")
|
||||
val jvmOptions = unbuilder.readField[Vector[String]]("jvmOptions")
|
||||
val environmentVariables = unbuilder.readField[scala.collection.immutable.Map[String, String]]("environmentVariables")
|
||||
val inputs = unbuilder.readField[Vector[sbt.internal.worker.FilePath]]("inputs")
|
||||
val outputs = unbuilder.readField[Vector[sbt.internal.worker.FilePath]]("outputs")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.worker.JvmRunInfo(args, classpath, mainClass, connectInput, javaHome, outputStrategy, workingDirectory, jvmOptions, environmentVariables, inputs, outputs)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.worker.JvmRunInfo, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("args", obj.args)
|
||||
builder.addField("classpath", obj.classpath)
|
||||
builder.addField("mainClass", obj.mainClass)
|
||||
builder.addField("connectInput", obj.connectInput)
|
||||
builder.addField("javaHome", obj.javaHome)
|
||||
builder.addField("outputStrategy", obj.outputStrategy)
|
||||
builder.addField("workingDirectory", obj.workingDirectory)
|
||||
builder.addField("jvmOptions", obj.jvmOptions)
|
||||
builder.addField("environmentVariables", obj.environmentVariables)
|
||||
builder.addField("inputs", obj.inputs)
|
||||
builder.addField("outputs", obj.outputs)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
41
protocol/src/main/contraband-scala/sbt/internal/worker/codec/NativeRunInfoFormats.scala
generated
Normal file
41
protocol/src/main/contraband-scala/sbt/internal/worker/codec/NativeRunInfoFormats.scala
generated
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait NativeRunInfoFormats { self: sbt.internal.worker.codec.FilePathFormats & sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val NativeRunInfoFormat: JsonFormat[sbt.internal.worker.NativeRunInfo] = new JsonFormat[sbt.internal.worker.NativeRunInfo] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.worker.NativeRunInfo = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val cmd = unbuilder.readField[String]("cmd")
|
||||
val args = unbuilder.readField[Vector[String]]("args")
|
||||
val connectInput = unbuilder.readField[Boolean]("connectInput")
|
||||
val outputStrategy = unbuilder.readField[Option[String]]("outputStrategy")
|
||||
val workingDirectory = unbuilder.readField[Option[java.net.URI]]("workingDirectory")
|
||||
val environmentVariables = unbuilder.readField[scala.collection.immutable.Map[String, String]]("environmentVariables")
|
||||
val inputs = unbuilder.readField[Vector[sbt.internal.worker.FilePath]]("inputs")
|
||||
val outputs = unbuilder.readField[Vector[sbt.internal.worker.FilePath]]("outputs")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.worker.NativeRunInfo(cmd, args, connectInput, outputStrategy, workingDirectory, environmentVariables, inputs, outputs)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.worker.NativeRunInfo, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("cmd", obj.cmd)
|
||||
builder.addField("args", obj.args)
|
||||
builder.addField("connectInput", obj.connectInput)
|
||||
builder.addField("outputStrategy", obj.outputStrategy)
|
||||
builder.addField("workingDirectory", obj.workingDirectory)
|
||||
builder.addField("environmentVariables", obj.environmentVariables)
|
||||
builder.addField("inputs", obj.inputs)
|
||||
builder.addField("outputs", obj.outputs)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
31
protocol/src/main/contraband-scala/sbt/internal/worker/codec/RunInfoFormats.scala
generated
Normal file
31
protocol/src/main/contraband-scala/sbt/internal/worker/codec/RunInfoFormats.scala
generated
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* This code is generated using [[https://www.scala-sbt.org/contraband]].
|
||||
*/
|
||||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.internal.worker.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait RunInfoFormats { self: sbt.internal.worker.codec.JvmRunInfoFormats & sbt.internal.worker.codec.FilePathFormats & sjsonnew.BasicJsonProtocol & sbt.internal.worker.codec.NativeRunInfoFormats =>
|
||||
implicit lazy val RunInfoFormat: JsonFormat[sbt.internal.worker.RunInfo] = new JsonFormat[sbt.internal.worker.RunInfo] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.worker.RunInfo = {
|
||||
__jsOpt match {
|
||||
case Some(__js) =>
|
||||
unbuilder.beginObject(__js)
|
||||
val jvm = unbuilder.readField[Boolean]("jvm")
|
||||
val jvmRunInfo = unbuilder.readField[Option[sbt.internal.worker.JvmRunInfo]]("jvmRunInfo")
|
||||
val nativeRunInfo = unbuilder.readField[Option[sbt.internal.worker.NativeRunInfo]]("nativeRunInfo")
|
||||
unbuilder.endObject()
|
||||
sbt.internal.worker.RunInfo(jvm, jvmRunInfo, nativeRunInfo)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
}
|
||||
override def write[J](obj: sbt.internal.worker.RunInfo, builder: Builder[J]): Unit = {
|
||||
builder.beginObject()
|
||||
builder.addField("jvm", obj.jvm)
|
||||
builder.addField("jvmRunInfo", obj.jvmRunInfo)
|
||||
builder.addField("nativeRunInfo", obj.nativeRunInfo)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,22 +7,24 @@ package sbt.protocol
|
|||
final class InitCommand private (
|
||||
val token: Option[String],
|
||||
val execId: Option[String],
|
||||
val skipAnalysis: Option[Boolean]) extends sbt.protocol.CommandMessage() with Serializable {
|
||||
val skipAnalysis: Option[Boolean],
|
||||
val initializationOptions: Option[sbt.internal.protocol.InitializeOption]) extends sbt.protocol.CommandMessage() with Serializable {
|
||||
|
||||
private def this(token: Option[String], execId: Option[String]) = this(token, execId, None)
|
||||
private def this(token: Option[String], execId: Option[String]) = this(token, execId, None, None)
|
||||
private def this(token: Option[String], execId: Option[String], skipAnalysis: Option[Boolean]) = this(token, execId, skipAnalysis, None)
|
||||
|
||||
override def equals(o: Any): Boolean = this.eq(o.asInstanceOf[AnyRef]) || (o match {
|
||||
case x: InitCommand => (this.token == x.token) && (this.execId == x.execId) && (this.skipAnalysis == x.skipAnalysis)
|
||||
case x: InitCommand => (this.token == x.token) && (this.execId == x.execId) && (this.skipAnalysis == x.skipAnalysis) && (this.initializationOptions == x.initializationOptions)
|
||||
case _ => false
|
||||
})
|
||||
override def hashCode: Int = {
|
||||
37 * (37 * (37 * (37 * (17 + "sbt.protocol.InitCommand".##) + token.##) + execId.##) + skipAnalysis.##)
|
||||
37 * (37 * (37 * (37 * (37 * (17 + "sbt.protocol.InitCommand".##) + token.##) + execId.##) + skipAnalysis.##) + initializationOptions.##)
|
||||
}
|
||||
override def toString: String = {
|
||||
"InitCommand(" + token + ", " + execId + ", " + skipAnalysis + ")"
|
||||
"InitCommand(" + token + ", " + execId + ", " + skipAnalysis + ", " + initializationOptions + ")"
|
||||
}
|
||||
private def copy(token: Option[String] = token, execId: Option[String] = execId, skipAnalysis: Option[Boolean] = skipAnalysis): InitCommand = {
|
||||
new InitCommand(token, execId, skipAnalysis)
|
||||
private def copy(token: Option[String] = token, execId: Option[String] = execId, skipAnalysis: Option[Boolean] = skipAnalysis, initializationOptions: Option[sbt.internal.protocol.InitializeOption] = initializationOptions): InitCommand = {
|
||||
new InitCommand(token, execId, skipAnalysis, initializationOptions)
|
||||
}
|
||||
def withToken(token: Option[String]): InitCommand = {
|
||||
copy(token = token)
|
||||
|
|
@ -42,6 +44,12 @@ final class InitCommand private (
|
|||
def withSkipAnalysis(skipAnalysis: Boolean): InitCommand = {
|
||||
copy(skipAnalysis = Option(skipAnalysis))
|
||||
}
|
||||
def withInitializationOptions(initializationOptions: Option[sbt.internal.protocol.InitializeOption]): InitCommand = {
|
||||
copy(initializationOptions = initializationOptions)
|
||||
}
|
||||
def withInitializationOptions(initializationOptions: sbt.internal.protocol.InitializeOption): InitCommand = {
|
||||
copy(initializationOptions = Option(initializationOptions))
|
||||
}
|
||||
}
|
||||
object InitCommand {
|
||||
|
||||
|
|
@ -49,4 +57,6 @@ object InitCommand {
|
|||
def apply(token: String, execId: String): InitCommand = new InitCommand(Option(token), Option(execId))
|
||||
def apply(token: Option[String], execId: Option[String], skipAnalysis: Option[Boolean]): InitCommand = new InitCommand(token, execId, skipAnalysis)
|
||||
def apply(token: String, execId: String, skipAnalysis: Boolean): InitCommand = new InitCommand(Option(token), Option(execId), Option(skipAnalysis))
|
||||
def apply(token: Option[String], execId: Option[String], skipAnalysis: Option[Boolean], initializationOptions: Option[sbt.internal.protocol.InitializeOption]): InitCommand = new InitCommand(token, execId, skipAnalysis, initializationOptions)
|
||||
def apply(token: String, execId: String, skipAnalysis: Boolean, initializationOptions: sbt.internal.protocol.InitializeOption): InitCommand = new InitCommand(Option(token), Option(execId), Option(skipAnalysis), Option(initializationOptions))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@
|
|||
package sbt.protocol.codec
|
||||
|
||||
import _root_.sjsonnew.JsonFormat
|
||||
trait CommandMessageFormats { self: sjsonnew.BasicJsonProtocol & sbt.protocol.codec.InitCommandFormats & sbt.protocol.codec.ExecCommandFormats & sbt.protocol.codec.SettingQueryFormats & sbt.protocol.codec.AttachFormats & sbt.protocol.codec.TerminalCapabilitiesQueryFormats & sbt.protocol.codec.TerminalSetAttributesCommandFormats & sbt.protocol.codec.TerminalAttributesQueryFormats & sbt.protocol.codec.TerminalGetSizeQueryFormats & sbt.protocol.codec.TerminalSetSizeCommandFormats & sbt.protocol.codec.TerminalSetEchoCommandFormats & sbt.protocol.codec.TerminalSetRawModeCommandFormats =>
|
||||
trait CommandMessageFormats { self: sbt.internal.protocol.codec.InitializeOptionFormats & sjsonnew.BasicJsonProtocol & sbt.protocol.codec.InitCommandFormats & sbt.protocol.codec.ExecCommandFormats & sbt.protocol.codec.SettingQueryFormats & sbt.protocol.codec.AttachFormats & sbt.protocol.codec.TerminalCapabilitiesQueryFormats & sbt.protocol.codec.TerminalSetAttributesCommandFormats & sbt.protocol.codec.TerminalAttributesQueryFormats & sbt.protocol.codec.TerminalGetSizeQueryFormats & sbt.protocol.codec.TerminalSetSizeCommandFormats & sbt.protocol.codec.TerminalSetEchoCommandFormats & sbt.protocol.codec.TerminalSetRawModeCommandFormats =>
|
||||
implicit lazy val CommandMessageFormat: JsonFormat[sbt.protocol.CommandMessage] = flatUnionFormat11[sbt.protocol.CommandMessage, sbt.protocol.InitCommand, sbt.protocol.ExecCommand, sbt.protocol.SettingQuery, sbt.protocol.Attach, sbt.protocol.TerminalCapabilitiesQuery, sbt.protocol.TerminalSetAttributesCommand, sbt.protocol.TerminalAttributesQuery, sbt.protocol.TerminalGetSizeQuery, sbt.protocol.TerminalSetSizeCommand, sbt.protocol.TerminalSetEchoCommand, sbt.protocol.TerminalSetRawModeCommand]("type")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.codec
|
||||
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
|
||||
trait InitCommandFormats { self: sjsonnew.BasicJsonProtocol =>
|
||||
trait InitCommandFormats { self: sbt.internal.protocol.codec.InitializeOptionFormats & sjsonnew.BasicJsonProtocol =>
|
||||
implicit lazy val InitCommandFormat: JsonFormat[sbt.protocol.InitCommand] = new JsonFormat[sbt.protocol.InitCommand] {
|
||||
override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.protocol.InitCommand = {
|
||||
__jsOpt match {
|
||||
|
|
@ -14,8 +14,9 @@ implicit lazy val InitCommandFormat: JsonFormat[sbt.protocol.InitCommand] = new
|
|||
val token = unbuilder.readField[Option[String]]("token")
|
||||
val execId = unbuilder.readField[Option[String]]("execId")
|
||||
val skipAnalysis = unbuilder.readField[Option[Boolean]]("skipAnalysis")
|
||||
val initializationOptions = unbuilder.readField[Option[sbt.internal.protocol.InitializeOption]]("initializationOptions")
|
||||
unbuilder.endObject()
|
||||
sbt.protocol.InitCommand(token, execId, skipAnalysis)
|
||||
sbt.protocol.InitCommand(token, execId, skipAnalysis, initializationOptions)
|
||||
case None =>
|
||||
deserializationError("Expected JsObject but found None")
|
||||
}
|
||||
|
|
@ -25,6 +26,7 @@ implicit lazy val InitCommandFormat: JsonFormat[sbt.protocol.InitCommand] = new
|
|||
builder.addField("token", obj.token)
|
||||
builder.addField("execId", obj.execId)
|
||||
builder.addField("skipAnalysis", obj.skipAnalysis)
|
||||
builder.addField("initializationOptions", obj.initializationOptions)
|
||||
builder.endObject()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
// DO NOT EDIT MANUALLY
|
||||
package sbt.protocol.codec
|
||||
trait JsonProtocol extends sjsonnew.BasicJsonProtocol
|
||||
trait JsonProtocol extends sbt.internal.protocol.codec.InitializeOptionFormats
|
||||
with sjsonnew.BasicJsonProtocol
|
||||
with sbt.protocol.codec.InitCommandFormats
|
||||
with sbt.protocol.codec.ExecCommandFormats
|
||||
with sbt.protocol.codec.SettingQueryFormats
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ type TokenFile {
|
|||
token: String!
|
||||
}
|
||||
|
||||
## Passed into InitializeParams as part of "initialize" request as the user-defined option.
|
||||
## https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
|
||||
type InitializeOption {
|
||||
token: String
|
||||
skipAnalysis: Boolean @since("1.4.0")
|
||||
canWork: Boolean @since("1.10.8")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ type InitCommand implements CommandMessage {
|
|||
token: String
|
||||
execId: String
|
||||
skipAnalysis: Boolean @since("1.4.0")
|
||||
initializationOptions: sbt.internal.protocol.InitializeOption @since("1.10.8")
|
||||
}
|
||||
|
||||
## Command to execute sbt command.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package sbt.internal.worker
|
||||
@target(Scala)
|
||||
@codecPackage("sbt.internal.worker.codec")
|
||||
@fullCodec("JsonProtocol")
|
||||
|
||||
type FilePath {
|
||||
path: java.net.URI!
|
||||
digest: String!
|
||||
}
|
||||
|
||||
type JvmRunInfo {
|
||||
args: [String],
|
||||
classpath: [sbt.internal.worker.FilePath],
|
||||
mainClass: String!
|
||||
connectInput: Boolean!
|
||||
javaHome: java.net.URI
|
||||
outputStrategy: String
|
||||
workingDirectory: java.net.URI
|
||||
jvmOptions: [String]
|
||||
environmentVariables: StringStringMap!
|
||||
inputs: [sbt.internal.worker.FilePath] @since("0.1.0"),
|
||||
outputs: [sbt.internal.worker.FilePath] @since("0.1.0"),
|
||||
}
|
||||
|
||||
type NativeRunInfo {
|
||||
cmd: String!,
|
||||
args: [String],
|
||||
connectInput: Boolean!
|
||||
outputStrategy: String
|
||||
workingDirectory: java.net.URI
|
||||
environmentVariables: StringStringMap!
|
||||
inputs: [sbt.internal.worker.FilePath] @since("0.1.0"),
|
||||
outputs: [sbt.internal.worker.FilePath] @since("0.1.0"),
|
||||
}
|
||||
|
||||
type RunInfo {
|
||||
jvm: Boolean!
|
||||
jvmRunInfo: sbt.internal.worker.JvmRunInfo,
|
||||
nativeRunInfo: sbt.internal.worker.NativeRunInfo @since("0.1.0"),
|
||||
}
|
||||
|
||||
## Client-side job support.
|
||||
##
|
||||
## Notification: sbt/clientJob
|
||||
##
|
||||
## Parameter for the sbt/clientJob notification.
|
||||
## A client-side job represents a unit of work that sbt server
|
||||
## can outsourse back to the client, for example for run task.
|
||||
type ClientJobParams {
|
||||
runInfo: sbt.internal.worker.RunInfo
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ object Serialization {
|
|||
private[sbt] val VsCode = "application/vscode-jsonrpc; charset=utf-8"
|
||||
val readSystemIn = "sbt/readSystemIn"
|
||||
val cancelReadSystemIn = "sbt/cancelReadSystemIn"
|
||||
val clientJob = "sbt/clientJob"
|
||||
val systemIn = "sbt/systemIn"
|
||||
val systemOut = "sbt/systemOut"
|
||||
val systemErr = "sbt/systemErr"
|
||||
|
|
@ -67,15 +68,10 @@ object Serialization {
|
|||
command match {
|
||||
case x: InitCommand =>
|
||||
val execId = x.execId.getOrElse(UUID.randomUUID.toString)
|
||||
val analysis = s""""skipAnalysis" : ${x.skipAnalysis.getOrElse(false)}"""
|
||||
val opt = x.token match {
|
||||
case Some(t) =>
|
||||
val json: JValue = Converter.toJson[String](t).get
|
||||
val v = CompactPrinter(json)
|
||||
s"""{ "token": $v, $analysis }"""
|
||||
case None => s"{ $analysis }"
|
||||
}
|
||||
s"""{ "jsonrpc": "2.0", "id": "$execId", "method": "initialize", "params": { "initializationOptions": $opt } }"""
|
||||
val opts = x.initializationOptions.getOrElse(sys.error("expected initializationOptions"))
|
||||
import sbt.protocol.codec.JsonProtocol.*
|
||||
val optsJson = CompactPrinter(Converter.toJson(opts).get)
|
||||
s"""{ "jsonrpc": "2.0", "id": "$execId", "method": "initialize", "params": { "initializationOptions": $optsJson } }"""
|
||||
case x: ExecCommand =>
|
||||
val execId = x.execId.getOrElse(UUID.randomUUID.toString)
|
||||
val json: JValue = Converter.toJson[String](x.commandLine).get
|
||||
|
|
|
|||
|
|
@ -35,15 +35,8 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
|
|||
* `config`. If `runnerClass` is defined for this Fork instance, it is prepended to `arguments` to
|
||||
* define the arguments passed to the forked command.
|
||||
*/
|
||||
def apply(config: ForkOptions, arguments: Seq[String]): Int = {
|
||||
val p = fork(config, arguments)
|
||||
RunningProcesses.add(p)
|
||||
try p.exitValue()
|
||||
finally {
|
||||
if (p.isAlive()) p.destroy()
|
||||
RunningProcesses.remove(p)
|
||||
}
|
||||
}
|
||||
def apply(config: ForkOptions, arguments: Seq[String]): Int =
|
||||
Fork.blockForExitCode(fork(config, arguments))
|
||||
|
||||
/**
|
||||
* Forks the configured process and returns a `Process` that can be used to wait for completion or
|
||||
|
|
@ -58,30 +51,17 @@ final class Fork(val commandName: String, val runnerClass: Option[String]) {
|
|||
val preOptions = makeOptions(runJVMOptions, bootJars, arguments)
|
||||
val (classpathEnv, options) = Fork.fitClasspath(preOptions)
|
||||
val command = executable +: options
|
||||
|
||||
val environment: List[(String, String)] = envVars.toList ++
|
||||
classpathEnv.map(value => Fork.ClasspathEnvKey -> value)
|
||||
val jpb =
|
||||
if (Fork.shouldUseArgumentsFile(options))
|
||||
new JProcessBuilder(executable, Fork.createArgumentsFile(options))
|
||||
else
|
||||
new JProcessBuilder(command*)
|
||||
workingDirectory.foreach(jpb.directory(_))
|
||||
environment.foreach { (k, v) => jpb.environment.put(k, v) }
|
||||
if (connectInput) {
|
||||
jpb.redirectInput(Redirect.INHERIT)
|
||||
()
|
||||
}
|
||||
val process = Process(jpb)
|
||||
|
||||
outputStrategy.getOrElse(StdoutOutput: OutputStrategy) match {
|
||||
case StdoutOutput => process.run(connectInput = false)
|
||||
case out: BufferedOutput =>
|
||||
out.logger.buffer { process.run(out.logger, connectInput = false) }
|
||||
case out: LoggedOutput => process.run(out.logger, connectInput = false)
|
||||
case out: CustomOutput => (process #> out.output).run(connectInput = false)
|
||||
new JProcessBuilder(command.toArray*)
|
||||
val extraEnv = classpathEnv.toList.map { value =>
|
||||
Fork.ClasspathEnvKey -> value
|
||||
}
|
||||
Fork.forkInternal(config, extraEnv, jpb)
|
||||
}
|
||||
|
||||
private def makeOptions(
|
||||
jvmOptions: Seq[String],
|
||||
bootJars: Iterable[File],
|
||||
|
|
@ -190,4 +170,36 @@ object Fork {
|
|||
pw.close()
|
||||
s"@${file.getAbsolutePath}"
|
||||
}
|
||||
|
||||
private[sbt] def forkInternal(
|
||||
config: ForkOptions,
|
||||
extraEnv: List[(String, String)],
|
||||
jpb: JProcessBuilder
|
||||
): Process = {
|
||||
import config.{ envVars as env, * }
|
||||
val environment: List[(String, String)] = env.toList ++ extraEnv
|
||||
workingDirectory.foreach(jpb.directory(_))
|
||||
environment.foreach { case (k, v) => jpb.environment.put(k, v) }
|
||||
if (connectInput) {
|
||||
jpb.redirectInput(Redirect.INHERIT)
|
||||
()
|
||||
}
|
||||
val process = Process(jpb)
|
||||
outputStrategy.getOrElse(StdoutOutput: OutputStrategy) match {
|
||||
case StdoutOutput => process.run(connectInput = false)
|
||||
case out: BufferedOutput =>
|
||||
out.logger.buffer { process.run(out.logger, connectInput = false) }
|
||||
case out: LoggedOutput => process.run(out.logger, connectInput = false)
|
||||
case out: CustomOutput => (process #> out.output).run(connectInput = false)
|
||||
}
|
||||
}
|
||||
|
||||
private[sbt] def blockForExitCode(p: Process): Int = {
|
||||
RunningProcesses.add(p)
|
||||
try p.exitValue()
|
||||
finally {
|
||||
if (p.isAlive()) p.destroy()
|
||||
RunningProcesses.remove(p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,15 +32,6 @@ class ForkRun(config: ForkOptions) extends ScalaRun {
|
|||
options: Seq[String],
|
||||
log: Logger
|
||||
): Try[Unit] = {
|
||||
def processExitCode(exitCode: Int, label: String): Try[Unit] =
|
||||
if (exitCode == 0) Success(())
|
||||
else
|
||||
Failure(
|
||||
new MessageOnlyException(
|
||||
s"""Nonzero exit code returned from $label: $exitCode""".stripMargin
|
||||
)
|
||||
)
|
||||
|
||||
log.info(s"running (fork) $mainClass ${Run.runOptionsStr(options)}")
|
||||
val c = configLogged(log)
|
||||
val scalaOpts = scalaOptions(mainClass, classpath, options)
|
||||
|
|
@ -48,10 +39,10 @@ class ForkRun(config: ForkOptions) extends ScalaRun {
|
|||
try Fork.java(c, scalaOpts)
|
||||
catch {
|
||||
case _: InterruptedException =>
|
||||
log.warn("Run canceled.")
|
||||
log.warn("run canceled")
|
||||
1
|
||||
}
|
||||
processExitCode(exitCode, "runner")
|
||||
Run.processExitCode(exitCode, "runner")
|
||||
}
|
||||
|
||||
def fork(
|
||||
|
|
@ -70,7 +61,7 @@ class ForkRun(config: ForkOptions) extends ScalaRun {
|
|||
}
|
||||
|
||||
private def configLogged(log: Logger): ForkOptions = {
|
||||
if (config.outputStrategy.isDefined) config
|
||||
if (config.outputStrategy.isDefined || config.connectInput) config
|
||||
else config.withOutputStrategy(OutputStrategy.LoggedOutput(log))
|
||||
}
|
||||
|
||||
|
|
@ -211,4 +202,13 @@ object Run:
|
|||
case str if str.contains(" ") => "\"" + str + "\""
|
||||
case str => str
|
||||
}).mkString(" ")
|
||||
|
||||
private[sbt] def processExitCode(exitCode: Int, label: String): Try[Unit] =
|
||||
if (exitCode == 0) Success(())
|
||||
else
|
||||
Failure(
|
||||
new MessageOnlyException(
|
||||
s"""nonzero exit code returned from $label: $exitCode""".stripMargin
|
||||
)
|
||||
)
|
||||
end Run
|
||||
|
|
|
|||
7
sbt
7
sbt
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set +e
|
||||
declare builtin_sbt_version="1.10.7"
|
||||
declare builtin_sbt_version="1.10.10"
|
||||
declare -a residual_args
|
||||
declare -a java_args
|
||||
declare -a scalac_args
|
||||
|
|
@ -24,7 +24,7 @@ declare build_props_sbt_version=
|
|||
declare use_sbtn=
|
||||
declare no_server=
|
||||
declare sbtn_command="$SBTN_CMD"
|
||||
declare sbtn_version="1.10.5"
|
||||
declare sbtn_version="1.10.8"
|
||||
declare use_colors=1
|
||||
|
||||
### ------------------------------- ###
|
||||
|
|
@ -203,6 +203,7 @@ acquire_sbtn () {
|
|||
exit 2
|
||||
fi
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
arch="universal"
|
||||
archive_target="$p/sbtn-universal-apple-darwin-${sbtn_v}.tar.gz"
|
||||
url="https://github.com/sbt/sbtn-dist/releases/download/v${sbtn_v}/sbtn-universal-apple-darwin-${sbtn_v}.tar.gz"
|
||||
elif [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
|
||||
|
|
@ -641,7 +642,7 @@ process_my_args () {
|
|||
|
||||
-allow-empty|--allow-empty|-sbt-create|--sbt-create) allow_empty=true && shift ;;
|
||||
|
||||
new) sbt_new=true && addResidual "$1" && shift ;;
|
||||
new|init) sbt_new=true && addResidual "$1" && shift ;;
|
||||
|
||||
*) addResidual "$1" && shift ;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
scalaVersion := "3.6.3"
|
||||
|
||||
TaskKey[Unit]("willSucceed") := println("success")
|
||||
|
||||
TaskKey[Unit]("willFail") := { throw new Exception("failed") }
|
||||
|
||||
scalaVersion := "2.12.20"
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test"
|
||||
libraryDependencies += "org.scalameta" %% "munit" % "1.0.4" % Test
|
||||
|
||||
TaskKey[Unit]("fooBar") := { () }
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
object A
|
||||
class A
|
||||
|
||||
@main def hello() = println("Hello, World!")
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
package test.pkg
|
||||
|
||||
class FooSpec extends org.scalatest.FlatSpec
|
||||
class FooSpec extends munit.FunSuite
|
||||
|
|
|
|||
|
|
@ -298,8 +298,7 @@ class BuildServerTest extends AbstractServerTest {
|
|||
""""severity":1""",
|
||||
"""incompatible types: int cannot be converted"""
|
||||
)(
|
||||
message = "should send publishDiagnostics with severity 1 for Hello.java",
|
||||
debug = false
|
||||
message = "should send publishDiagnostics with severity 1 for Hello.java"
|
||||
)
|
||||
// Note the messages changed slightly in both cases. That's interesting…
|
||||
|
||||
|
|
@ -322,6 +321,7 @@ class BuildServerTest extends AbstractServerTest {
|
|||
|
||||
compile(buildTarget)
|
||||
|
||||
/*
|
||||
assertMessage(
|
||||
"build/publishDiagnostics",
|
||||
"Hello.java",
|
||||
|
|
@ -331,6 +331,7 @@ class BuildServerTest extends AbstractServerTest {
|
|||
message = "should send publishDiagnostics with empty diagnostics",
|
||||
debug = false
|
||||
)
|
||||
*/
|
||||
|
||||
IO.delete(otherBuildFile)
|
||||
reloadWorkspace()
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class ClientTest extends AbstractServerTest {
|
|||
case r => r
|
||||
}
|
||||
}
|
||||
private def client(args: String*): Int = {
|
||||
private def client(args: String*): Int =
|
||||
background(
|
||||
NetworkClient.client(
|
||||
testPath.toFile,
|
||||
|
|
@ -70,6 +70,19 @@ class ClientTest extends AbstractServerTest {
|
|||
false
|
||||
)
|
||||
)
|
||||
def clientWithStdoutLines(args: String*): (Int, Seq[String]) = {
|
||||
val out = new CachingPrintStream
|
||||
val exitCode = background(
|
||||
NetworkClient.client(
|
||||
testPath.toFile,
|
||||
args.toArray,
|
||||
NullInputStream,
|
||||
out,
|
||||
NullPrintStream,
|
||||
false
|
||||
)
|
||||
)
|
||||
(exitCode, out.lines)
|
||||
}
|
||||
// This ensures that the completion command will send a tab that triggers
|
||||
// sbt to call definedTestNames or discoveredMainClasses if there hasn't
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ case class TestServer(
|
|||
|
||||
// initiate handshake
|
||||
sendJsonRpc(
|
||||
s"""{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { "skipAnalysis": true } } }"""
|
||||
s"""{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { "skipAnalysis": true, "canWork": true } } }"""
|
||||
)
|
||||
|
||||
def test(f: TestServer => Future[Unit]): Future[Unit] = f(this)
|
||||
|
|
|
|||
Loading…
Reference in New Issue