diff --git a/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala b/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala index ba713c631..ad585d6f4 100644 --- a/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/LanguageServerProtocol.scala @@ -5,6 +5,7 @@ package server import sjsonnew.JsonFormat import sjsonnew.support.scalajson.unsafe.Converter import sbt.protocol.Serialization +import sbt.protocol.{ SettingQuery => Q } import sbt.internal.protocol._ import sbt.internal.protocol.codec._ import sbt.internal.langserver._ @@ -24,6 +25,7 @@ private[sbt] trait LanguageServerProtocol extends CommandChannel { protected def authOptions: Set[ServerAuthentication] protected def setInitialized(value: Boolean): Unit protected def log: Logger + protected def onSettingQuery(execId: Option[String], req: Q): Unit protected def onRequestMessage(request: JsonRpcRequestMessage): Unit = { @@ -54,6 +56,11 @@ private[sbt] trait LanguageServerProtocol extends CommandChannel { case "sbt/exec" => val param = Converter.fromJson[SbtExecParams](json).get append(Exec(param.commandLine, Some(request.id), Some(CommandSource(name)))) + case "sbt/setting" => { + import sbt.protocol.codec.JsonProtocol._ + val param = Converter.fromJson[Q](json).get + onSettingQuery(Option(request.id), param) + } case _ => () } } diff --git a/main/src/main/scala/sbt/internal/server/NetworkChannel.scala b/main/src/main/scala/sbt/internal/server/NetworkChannel.scala index 12d9b33d8..7044cd9a2 100644 --- a/main/src/main/scala/sbt/internal/server/NetworkChannel.scala +++ b/main/src/main/scala/sbt/internal/server/NetworkChannel.scala @@ -9,11 +9,9 @@ import java.net.{ Socket, SocketTimeoutException } import java.util.concurrent.atomic.AtomicBoolean import sjsonnew._ -import sjsonnew.support.scalajson.unsafe.Converter import scala.annotation.tailrec import sbt.protocol._ import sbt.internal.langserver.ErrorCodes -import sbt.internal.protocol.JsonRpcResponseMessage import sbt.internal.util.ObjectEvent import sbt.internal.util.codec.JValueFormats import sbt.util.Logger @@ -283,7 +281,7 @@ final class NetworkChannel(val name: String, def onCommand(command: CommandMessage): Unit = command match { case x: InitCommand => onInitCommand(x) case x: ExecCommand => onExecCommand(x) - case x: SettingQuery => onSettingQuery(x) + case x: SettingQuery => onSettingQuery(None, x) } private def onInitCommand(cmd: InitCommand): Unit = { @@ -312,9 +310,13 @@ final class NetworkChannel(val name: String, } } - private def onSettingQuery(req: SettingQuery) = { + protected def onSettingQuery(execId: Option[String], req: SettingQuery) = { if (initialized) { - StandardMain.exchange publishEventMessage SettingQuery.handleSettingQuery(req, structure) + import sbt.protocol.codec.JsonProtocol._ + SettingQuery.handleSettingQueryEither(req, structure) match { + case Right(x) => langRespond(x, execId) + case Left(s) => langError(execId, ErrorCodes.InvalidParams, s) + } } else { log.warn(s"ignoring query $req before initialization") } diff --git a/main/src/main/scala/sbt/internal/server/SettingQuery.scala b/main/src/main/scala/sbt/internal/server/SettingQuery.scala index e8c585c18..9b3cd3859 100644 --- a/main/src/main/scala/sbt/internal/server/SettingQuery.scala +++ b/main/src/main/scala/sbt/internal/server/SettingQuery.scala @@ -110,18 +110,19 @@ object SettingQuery { toJson(value) }) - def handleSettingQuery(req: SettingQuery, structure: BuildStructure): SettingQueryResponse = { + def handleSettingQueryEither(req: SettingQuery, + structure: BuildStructure): Either[String, SettingQuerySuccess] = { val key = Parser.parse(req.setting, scopedKeyParser(structure)) - val result = - for { - key <- key - json <- getSettingJsonValue(structure, key) - } yield SettingQuerySuccess(json, key.key.manifest.toString) + for { + key <- key + json <- getSettingJsonValue(structure, key) + } yield SettingQuerySuccess(json, key.key.manifest.toString) + } - result match { + def handleSettingQuery(req: SettingQuery, structure: BuildStructure): SettingQueryResponse = + handleSettingQueryEither(req, structure) match { case Right(x) => x case Left(s) => SettingQueryFailure(s) } - } } diff --git a/server.md b/server.md index a172eb5fd..5afbb6f4f 100644 --- a/server.md +++ b/server.md @@ -1,13 +1,34 @@ +$ cat ~/.sbt/1.0/server/0845deda85cb41abdb9f/token.json + ### initialize ```json { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "initializationOptions": { "token": "************" } } } ``` -### ExecCommand +### sbt/exec ```json { "jsonrpc": "2.0", "id": 1, "method": "sbt/exec", "params": { "commandLine": "compile" } } ``` +### sbt/setting + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "sbt/setting", "params": { "setting": "root/name" } } +``` + +Here's an example of a bad query: + +```json +{ "jsonrpc": "2.0", "id": 1, "method": "sbt/setting", "params": { "setting": "name" } } +``` + + +``` +Content-Length: 104 +Content-Type: application/vscode-jsonrpc; charset=utf-8 + +{"jsonrpc":"2.0","id":"1","error":{"code":-32602,"message":"Not a valid project ID: name\nname\n ^"}} +```