diff --git a/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala b/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala index ea84fbed7..ba713c631 100644 --- a/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala @@ -30,14 +30,14 @@ private[sbt] trait LanguageServerProtocol extends CommandChannel { import sbt.internal.langserver.codec.JsonProtocol._ import internalJsonProtocol._ + def json = + request.params.getOrElse( + throw LangServerError(ErrorCodes.InvalidParams, + s"param is expected on '${request.method}' method.")) log.debug(s"onRequestMessage: $request") request.method match { case "initialize" => if (authOptions(ServerAuthentication.Token)) { - val json = - request.params.getOrElse( - throw LangServerError(ErrorCodes.InvalidParams, - "param is expected on 'initialize' method.")) val param = Converter.fromJson[InitializeParams](json).get val optionJson = param.initializationOptions.getOrElse( throw LangServerError(ErrorCodes.InvalidParams, @@ -51,6 +51,9 @@ private[sbt] trait LanguageServerProtocol extends CommandChannel { langRespond(InitializeResult(serverCapabilities), Option(request.id)) case "textDocument/didSave" => append(Exec("compile", Some(request.id), Some(CommandSource(name)))) + case "sbt/exec" => + val param = Converter.fromJson[SbtExecParams](json).get + append(Exec(param.commandLine, Some(request.id), Some(CommandSource(name)))) case _ => () } } diff --git a/main/src/main/scala/sbt/internal/server/NetworkChannel.scala b/main/src/main/scala/sbt/internal/server/NetworkChannel.scala index 43c01e343..12d9b33d8 100644 --- a/main/src/main/scala/sbt/internal/server/NetworkChannel.scala +++ b/main/src/main/scala/sbt/internal/server/NetworkChannel.scala @@ -102,17 +102,11 @@ final class NetworkChannel(val name: String, tillEndOfLine match { case Some(chunk) => chunk.headOption match { - case None => // ignore blank line + case None => // ignore blank line case Some(Curly) => - Serialization - .deserializeCommand(chunk) - .fold( - errorDesc => - log.error( - s"Got invalid chunk from client (${new String(chunk.toArray, "UTF-8")}): " + errorDesc), - onCommand - ) - resetChannelState() + // When Content-Length header is not found, interpret the line as JSON message. + handleBody(chunk) + process() case Some(_) => val str = (new String(chunk.toArray, "UTF-8")).trim handleHeader(str) match { diff --git a/protocol/src/main/contraband-scala/sbt/internal/langserver/SbtExecParams.scala b/protocol/src/main/contraband-scala/sbt/internal/langserver/SbtExecParams.scala new file mode 100644 index 000000000..d60cc441b --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/langserver/SbtExecParams.scala @@ -0,0 +1,33 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.langserver +/** Command to execute sbt command. */ +final class SbtExecParams private ( + val commandLine: String) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: SbtExecParams => (this.commandLine == x.commandLine) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (17 + "sbt.internal.langserver.SbtExecParams".##) + commandLine.##) + } + override def toString: String = { + "SbtExecParams(" + commandLine + ")" + } + protected[this] def copy(commandLine: String = commandLine): SbtExecParams = { + new SbtExecParams(commandLine) + } + def withCommandLine(commandLine: String): SbtExecParams = { + copy(commandLine = commandLine) + } +} +object SbtExecParams { + + def apply(commandLine: String): SbtExecParams = new SbtExecParams(commandLine) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/JsonProtocol.scala b/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/JsonProtocol.scala index 24ca637e4..a40a00bbe 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/JsonProtocol.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/JsonProtocol.scala @@ -17,4 +17,5 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.langserver.codec.ServerCapabilitiesFormats with sbt.internal.langserver.codec.InitializeResultFormats with sbt.internal.langserver.codec.PublishDiagnosticsParamsFormats + with sbt.internal.langserver.codec.SbtExecParamsFormats object JsonProtocol extends JsonProtocol \ No newline at end of file diff --git a/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/SbtExecParamsFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/SbtExecParamsFormats.scala new file mode 100644 index 000000000..9447f9180 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/langserver/codec/SbtExecParamsFormats.scala @@ -0,0 +1,27 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.langserver.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait SbtExecParamsFormats { self: sjsonnew.BasicJsonProtocol => +implicit lazy val SbtExecParamsFormat: JsonFormat[sbt.internal.langserver.SbtExecParams] = new JsonFormat[sbt.internal.langserver.SbtExecParams] { + override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.SbtExecParams = { + jsOpt match { + case Some(js) => + unbuilder.beginObject(js) + val commandLine = unbuilder.readField[String]("commandLine") + unbuilder.endObject() + sbt.internal.langserver.SbtExecParams(commandLine) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.langserver.SbtExecParams, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("commandLine", obj.commandLine) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband/lsp.contra b/protocol/src/main/contraband/lsp.contra index cfc43ae69..49853a2f4 100644 --- a/protocol/src/main/contraband/lsp.contra +++ b/protocol/src/main/contraband/lsp.contra @@ -110,3 +110,10 @@ type PublishDiagnosticsParams { ## An array of diagnostic information items. diagnostics: [sbt.internal.langserver.Diagnostic] } + +# sbt extension + +## Command to execute sbt command. +type SbtExecParams { + commandLine: String! +} diff --git a/server.md b/server.md index 20c55f508..a172eb5fd 100644 --- a/server.md +++ b/server.md @@ -1,11 +1,13 @@ +### initialize + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { "token": "************" } } } +``` ### ExecCommand ```json -{ "type": "ExecCommand", "commandLine": "compile" } +{ "jsonrpc": "2.0", "id": 1, "method": "sbt/exec", "params": { "commandLine": "compile" } } ``` -```json -{ "type": "ExecCommand", "commandLine": "eval Thread.sleep(10000)" } -```