begins language server protocol

This is the first cut for the Language Server Protocol on top of server that is still work in progress.

With this change, sbt is able to invoke `compile` task on saving files in VS Code.
This commit is contained in:
Eugene Yokota 2017-10-02 03:33:29 -04:00
parent 21bd7c3a91
commit 0c1c380f71
74 changed files with 5035 additions and 64 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
target/
__pycache__
toolbox.classpath
out
node_modules
vscode-sbt-scala/client/server
npm-debug.log
*.vsix

View File

@ -407,6 +407,41 @@ lazy val sbtProj = (project in file("sbt"))
)
.configure(addSbtCompilerBridge)
lazy val vscodePlugin = (project in file("vscode-sbt-scala"))
.settings(
crossPaths := false,
crossScalaVersions := Seq(baseScalaVersion),
skip in publish := true,
compile in Compile := {
val u = update.value
import sbt.internal.inc.Analysis
import scala.sys.process._
Process(s"npm run compile", Option(baseDirectory.value)).!
Analysis.empty
},
update := {
val old = update.value
val t = target.value / "updated"
val base = baseDirectory.value
if (t.exists) ()
else {
import scala.sys.process._
Process("npm install", Option(base)).!
IO.touch(t)
}
old
},
cleanFiles ++= {
val base = baseDirectory.value
Vector(
target.value / "updated",
base / "node_modules", base / "client" / "node_modules",
base / "client" / "server",
base / "client" / "out",
base / "server" / "node_modules") filter { _.exists }
}
)
lazy val sbtIgnoredProblems = {
Seq(
// Added more items to Import trait.

View File

@ -16,6 +16,7 @@ abstract class CommandChannel {
commandQueue.add(exec)
def poll: Option[Exec] = Option(commandQueue.poll)
def publishEvent[A: JsonFormat](event: A, execId: Option[String]): Unit
def publishEvent[A: JsonFormat](event: A): Unit
def publishEventMessage(event: EventMessage): Unit
def publishBytes(bytes: Array[Byte]): Unit

View File

@ -31,6 +31,8 @@ private[sbt] final class ConsoleChannel(val name: String) extends CommandChannel
def publishBytes(bytes: Array[Byte]): Unit = ()
def publishEvent[A: JsonFormat](event: A, execId: Option[String]): Unit = ()
def publishEvent[A: JsonFormat](event: A): Unit = ()
def publishEventMessage(event: EventMessage): Unit =

View File

@ -23,6 +23,7 @@ import sbt.internal.librarymanagement.mavenint.{
PomExtraDependencyAttributes,
SbtPomExtraProperties
}
import sbt.internal.server.LanguageServerReporter
import sbt.internal.testing.TestLogger
import sbt.internal.util._
import sbt.internal.util.Attributed.data
@ -1402,6 +1403,14 @@ object Defaults extends BuildCommon {
val compilers: Compilers = ci.compilers
val i = ci.withCompilers(onArgs(compilers))
try {
val prev = i.previousResult
prev.analysis.toOption map { analysis =>
i.setup.reporter match {
case r: LanguageServerReporter =>
r.resetPrevious(analysis)
case _ => ()
}
}
incCompiler.compile(i, s.log)
} finally x.close() // workaround for #937
}
@ -1441,7 +1450,7 @@ object Defaults extends BuildCommon {
compileOrder.value
),
compilerReporter := {
new ManagedLoggedReporter(
new LanguageServerReporter(
maxErrors.value,
streams.value.log,
foldMappers(sourcePositionMappers.value)

View File

@ -4,19 +4,21 @@ package internal
import java.net.SocketException
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.atomic.AtomicInteger
import sbt.internal.server._
import sbt.internal.util.StringEvent
import sbt.protocol.{ EventMessage, Serialization }
import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec
import BasicKeys.{ serverHost, serverPort, serverAuthentication }
import java.net.Socket
import sjsonnew.JsonFormat
import sjsonnew.shaded.scalajson.ast.unsafe._
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import scala.util.{ Success, Failure }
import sbt.io.syntax._
import sbt.io.Hash
import sbt.internal.server._
import sbt.internal.util.{ StringEvent, ObjectEvent }
import sbt.internal.util.codec.JValueFormats
import sbt.protocol.{ EventMessage, Serialization, ChannelAcceptedEvent }
/**
* The command exchange merges multiple command channels (e.g. network and console),
@ -34,6 +36,8 @@ private[sbt] final class CommandExchange {
private val commandQueue: ConcurrentLinkedQueue[Exec] = new ConcurrentLinkedQueue()
private val channelBuffer: ListBuffer[CommandChannel] = new ListBuffer()
private val nextChannelId: AtomicInteger = new AtomicInteger(0)
private lazy val jsonFormat = new sjsonnew.BasicJsonProtocol with JValueFormats {}
def channels: List[CommandChannel] = channelBuffer.toList
def subscribe(c: CommandChannel): Unit =
lock.synchronized {
@ -121,9 +125,31 @@ private[sbt] final class CommandExchange {
server = None
}
// This is an interface to directly notify events.
private[sbt] def notifyEvent[A: JsonFormat](method: String, params: A): Unit = {
val toDel: ListBuffer[CommandChannel] = ListBuffer.empty
channels.foreach {
case c: ConsoleChannel =>
// c.publishEvent(event)
case c: NetworkChannel =>
try {
c.notifyEvent(method, params)
} catch {
case e: SocketException =>
toDel += c
}
}
toDel.toList match {
case Nil => // do nothing
case xs =>
lock.synchronized {
channelBuffer --= xs
}
}
}
def publishEvent[A: JsonFormat](event: A): Unit = {
val toDel: ListBuffer[CommandChannel] = ListBuffer.empty
val bytes = Serialization.serializeEvent(event)
event match {
case entry: StringEvent =>
channels.foreach {
@ -134,7 +160,7 @@ private[sbt] final class CommandExchange {
case c: NetworkChannel =>
try {
if (entry.channelName == Some(c.name)) {
c.publishBytes(bytes)
c.publishEvent(event)
}
} catch {
case e: SocketException =>
@ -147,7 +173,7 @@ private[sbt] final class CommandExchange {
c.publishEvent(event)
case c: NetworkChannel =>
try {
c.publishBytes(bytes)
c.publishEvent(event)
} catch {
case e: SocketException =>
toDel += c
@ -163,6 +189,43 @@ private[sbt] final class CommandExchange {
}
}
/**
* This publishes object events. The type information has been
* erased because it went through logging.
*/
private[sbt] def publishObjectEvent(event: ObjectEvent[_]): Unit = {
import jsonFormat._
val toDel: ListBuffer[CommandChannel] = ListBuffer.empty
def json: JValue = JObject(
JField("type", JString(event.contentType)),
(Vector(JField("message", event.json), JField("level", JString(event.level.toString))) ++
(event.channelName.toVector map { channelName =>
JField("channelName", JString(channelName))
}) ++
(event.execId.toVector map { execId =>
JField("execId", JString(execId))
})): _*
)
channels.foreach {
case c: ConsoleChannel =>
c.publishEvent(json)
case c: NetworkChannel =>
try {
c.publishObjectEvent(event)
} catch {
case e: SocketException =>
toDel += c
}
}
toDel.toList match {
case Nil => // do nothing
case xs =>
lock.synchronized {
channelBuffer --= xs
}
}
}
// fanout publishEvent
def publishEventMessage(event: EventMessage): Unit = {
val toDel: ListBuffer[CommandChannel] = ListBuffer.empty
@ -177,14 +240,12 @@ private[sbt] final class CommandExchange {
case c: ConsoleChannel => c.publishEventMessage(e)
}
case _ =>
// TODO do not do this on the calling thread
val bytes = Serialization.serializeEventMessage(event)
channels.foreach {
case c: ConsoleChannel =>
c.publishEventMessage(event)
case c: NetworkChannel =>
try {
c.publishBytes(bytes)
c.publishEventMessage(event)
} catch {
case e: SocketException =>
toDel += c

View File

@ -10,12 +10,10 @@ import sbt.util.Level
import sbt.internal.util._
import sbt.protocol.LogEvent
import sbt.internal.util.codec._
import sjsonnew.shaded.scalajson.ast.unsafe._
class RelayAppender(name: String)
extends AbstractAppender(name, null, PatternLayout.createDefaultLayout(), true) {
lazy val exchange = StandardMain.exchange
lazy val jsonFormat = new sjsonnew.BasicJsonProtocol with JValueFormats {}
def append(event: XLogEvent): Unit = {
val level = ConsoleAppender.toLevel(event.getLevel)
@ -36,20 +34,7 @@ class RelayAppender(name: String)
import JsonProtocol._
exchange.publishEvent(x: AbstractEntry)
}
case x: ObjectEvent[_] => {
import jsonFormat._
val json = JObject(
JField("type", JString(x.contentType)),
(Vector(JField("message", x.json), JField("level", JString(x.level.toString))) ++
(x.channelName.toVector map { channelName =>
JField("channelName", JString(channelName))
}) ++
(x.execId.toVector map { execId =>
JField("execId", JString(execId))
})): _*
)
exchange.publishEvent(json: JValue)
}
case x: ObjectEvent[_] => exchange.publishObjectEvent(x)
case _ =>
println(s"appendEvent: ${event.getClass}")
()

View File

@ -0,0 +1,127 @@
package sbt
package internal
package server
import sjsonnew.JsonFormat
import sjsonnew.support.scalajson.unsafe.Converter
import sbt.protocol.Serialization
import sbt.internal.protocol._
import sbt.internal.protocol.codec._
import sbt.internal.langserver._
import sbt.internal.util.ObjectEvent
private[sbt] case class LangServerError(code: Long, message: String) extends Throwable(message)
/**
* Implements Language Server Protocol <https://github.com/Microsoft/language-server-protocol>.
*/
private[sbt] trait LanguageServerProtocol extends CommandChannel {
lazy val internalJsonProtocol = new InitializeOptionFormats with sjsonnew.BasicJsonProtocol {}
protected def authenticate(token: String): Boolean
protected def authOptions: Set[ServerAuthentication]
protected def setInitialized(value: Boolean): Unit
protected def onRequestMessage(request: JsonRpcRequestMessage): Unit = {
import sbt.internal.langserver.codec.JsonProtocol._
import internalJsonProtocol._
println(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,
"initializationOptions is expected on 'initialize' param."))
val opt = Converter.fromJson[InitializeOption](optionJson).get
val token = opt.token.getOrElse(sys.error("'token' is missing."))
if (authenticate(token)) ()
else throw LangServerError(ErrorCodes.InvalidRequest, "invalid token")
} else ()
setInitialized(true)
langRespond(InitializeResult(serverCapabilities), Option(request.id))
case "textDocument/didSave" =>
append(Exec("compile", Some(request.id), Some(CommandSource(name))))
case _ => ()
}
}
/**
* This reacts to various events that happens inside sbt, sometime
* in response to the previous requests.
* The type information has been erased because it went through logging.
*/
protected def onObjectEvent(event: ObjectEvent[_]): Unit = {
// import sbt.internal.langserver.codec.JsonProtocol._
val msgContentType = event.contentType
msgContentType match {
// LanguageServerReporter sends PublishDiagnosticsParams
case "sbt.internal.langserver.PublishDiagnosticsParams" =>
// val p = event.message.asInstanceOf[PublishDiagnosticsParams]
// langNotify("textDocument/publishDiagnostics", p)
case "xsbti.Problem" =>
() // ignore
case _ =>
// println(event)
()
}
}
/**
* Respond back to Language Server's client.
*/
private[sbt] def langRespond[A: JsonFormat](event: A, execId: Option[String]): Unit = {
val m =
JsonRpcResponseMessage("2.0", execId, Option(Converter.toJson[A](event).get), None)
val bytes = Serialization.serializeResponseMessage(m)
publishBytes(bytes)
}
/**
* Respond back to Language Server's client.
*/
private[sbt] def langError(execId: Option[String], code: Long, message: String): Unit = {
val e = JsonRpcResponseError(code, message, None)
val m = JsonRpcResponseMessage("2.0", execId, None, Option(e))
val bytes = Serialization.serializeResponseMessage(m)
publishBytes(bytes)
}
/**
* Respond back to Language Server's client.
*/
private[sbt] def langError[A: JsonFormat](execId: Option[String],
code: Long,
message: String,
data: A): Unit = {
val e = JsonRpcResponseError(code, message, Option(Converter.toJson[A](data).get))
val m = JsonRpcResponseMessage("2.0", execId, None, Option(e))
val bytes = Serialization.serializeResponseMessage(m)
publishBytes(bytes)
}
/**
* Notify to Language Server's client.
*/
private[sbt] def langNotify[A: JsonFormat](method: String, params: A): Unit = {
val m =
JsonRpcNotificationMessage("2.0", method, Option(Converter.toJson[A](params).get))
println(s"langNotify: $m")
val bytes = Serialization.serializeNotificationMessage(m)
publishBytes(bytes)
}
private[sbt] lazy val serverCapabilities: ServerCapabilities = {
ServerCapabilities(textDocumentSync =
TextDocumentSyncOptions(true, 0, false, false, SaveOptions(false)),
hoverProvider = false)
}
}

View File

@ -0,0 +1,122 @@
package sbt
package internal
package server
import java.io.File
import sbt.internal.inc.ManagedLoggedReporter
import sbt.internal.util.ManagedLogger
import xsbti.{ Problem, Position => XPosition, Severity }
import xsbti.compile.CompileAnalysis
import sbt.internal.langserver.{
PublishDiagnosticsParams,
Position,
Diagnostic,
Range,
DiagnosticSeverity
}
import sbt.internal.inc.JavaInterfaceUtil._
import scala.collection.mutable
import scala.collection.JavaConverters._
/**
* Defines a compiler reporter that uses event logging provided by a [[ManagedLogger]].
*
* @param maximumErrors The maximum errors.
* @param logger The event managed logger.
* @param sourcePositionMapper The position mapper.
*/
class LanguageServerReporter(
maximumErrors: Int,
logger: ManagedLogger,
sourcePositionMapper: XPosition => XPosition = identity[XPosition]
) extends ManagedLoggedReporter(maximumErrors, logger, sourcePositionMapper) {
lazy val exchange = StandardMain.exchange
private[sbt] lazy val problemsByFile = new mutable.HashMap[File, List[Problem]]
override def reset(): Unit = {
super.reset()
problemsByFile.clear()
}
override def log(problem: Problem): Unit = {
val pos = problem.position
pos.sourceFile.toOption foreach { sourceFile: File =>
problemsByFile.get(sourceFile) match {
case Some(xs: List[Problem]) => problemsByFile(sourceFile) = problem :: xs
case _ => problemsByFile(sourceFile) = List(problem)
}
}
super.log(problem)
}
override def logError(problem: Problem): Unit = {
aggregateProblems(problem)
// console channel can keep using the xsbi.Problem
super.logError(problem)
}
override def logWarning(problem: Problem): Unit = {
aggregateProblems(problem)
// console channel can keep using the xsbi.Problem
super.logWarning(problem)
}
override def logInfo(problem: Problem): Unit = {
aggregateProblems(problem)
// console channel can keep using the xsbi.Problem
super.logInfo(problem)
}
private[sbt] def resetPrevious(analysis: CompileAnalysis): Unit = {
import sbt.internal.langserver.codec.JsonProtocol._
val files = analysis.readSourceInfos.getAllSourceInfos.keySet.asScala
println(files)
files foreach { f =>
val params = PublishDiagnosticsParams(f.toURI.toString, Vector())
exchange.notifyEvent("textDocument/publishDiagnostics", params)
}
}
private[sbt] def aggregateProblems(problem: Problem): Unit = {
import sbt.internal.langserver.codec.JsonProtocol._
val pos = problem.position
pos.sourceFile.toOption foreach { sourceFile: File =>
problemsByFile.get(sourceFile) match {
case Some(xs: List[Problem]) =>
val ds = toDiagnostics(xs)
val params = PublishDiagnosticsParams(sourceFile.toURI.toString, ds)
exchange.notifyEvent("textDocument/publishDiagnostics", params)
case _ =>
}
}
}
private[sbt] def toDiagnostics(ps: List[Problem]): Vector[Diagnostic] = {
for {
problem <- ps.toVector
pos = problem.position
line0 <- pos.line.toOption.toVector
pointer0 <- pos.pointer.toOption.toVector
} yield {
val line = line0.toLong - 1L
val pointer = pointer0.toLong
Diagnostic(
Range(start = Position(line, pointer), end = Position(line, pointer + 1)),
Option(toDiagnosticSeverity(problem.severity)),
None,
Option("sbt"),
problem.message
)
}
}
private[sbt] def toDiagnosticSeverity(severity: Severity): Long = severity match {
case Severity.Info => DiagnosticSeverity.Information
case Severity.Warn => DiagnosticSeverity.Warning
case Severity.Error => DiagnosticSeverity.Error
}
}

View File

@ -7,21 +7,58 @@ package server
import java.net.{ Socket, SocketTimeoutException }
import java.util.concurrent.atomic.AtomicBoolean
import sbt.protocol._
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
final class NetworkChannel(val name: String,
connection: Socket,
structure: BuildStructure,
auth: Set[ServerAuthentication],
instance: ServerInstance)
extends CommandChannel {
extends CommandChannel
with LanguageServerProtocol {
import NetworkChannel._
private val running = new AtomicBoolean(true)
private val delimiter: Byte = '\n'.toByte
private val RetByte = '\r'.toByte
private val out = connection.getOutputStream
private var initialized = false
private val Curly = '{'.toByte
private val ContentLength = """^Content\-Length\:\s*(\d+)""".r
private val ContentType = """^Content\-Type\:\s*(.+)""".r
private var _contentType: String = ""
private val SbtX1Protocol = "application/sbt-x1"
private val VsCode = sbt.protocol.Serialization.VsCode
private val VsCodeOld = "application/vscode-jsonrpc; charset=utf8"
private lazy val jsonFormat = new sjsonnew.BasicJsonProtocol with JValueFormats {}
def setContentType(ct: String): Unit = synchronized {
_contentType = ct
}
def contentType: String = _contentType
protected def authenticate(token: String): Boolean = {
instance.authenticate(token)
}
protected def setInitialized(value: Boolean): Unit = {
initialized = value
}
protected def authOptions: Set[ServerAuthentication] = auth
val thread = new Thread(s"sbt-networkchannel-${connection.getPort}") {
var contentLength: Int = 0
var state: ChannelState = SingleLine
override def run(): Unit = {
try {
val readBuffer = new Array[Byte](4096)
@ -29,48 +66,221 @@ final class NetworkChannel(val name: String,
connection.setSoTimeout(5000)
var buffer: Vector[Byte] = Vector.empty
var bytesRead = 0
def resetChannelState(): Unit = {
contentLength = 0
// contentType = ""
state = SingleLine
}
def tillEndOfLine: Option[Vector[Byte]] = {
val delimPos = buffer.indexOf(delimiter)
if (delimPos > 0) {
val chunk0 = buffer.take(delimPos)
buffer = buffer.drop(delimPos + 1)
// remove \r at the end of line.
if (chunk0.size > 0 && chunk0.indexOf(RetByte) == chunk0.size - 1)
Some(chunk0.dropRight(1))
else Some(chunk0)
} else None // no EOL yet, so skip this turn.
}
def tillContentLength: Option[Vector[Byte]] = {
if (contentLength <= buffer.size) {
val chunk = buffer.take(contentLength)
buffer = buffer.drop(contentLength)
resetChannelState()
Some(chunk)
} else None // have not read enough yet, so skip this turn.
}
@tailrec def process(): Unit = {
// handle un-framing
state match {
case SingleLine =>
tillEndOfLine match {
case Some(chunk) =>
chunk.headOption match {
case None => // ignore blank line
case Some(Curly) =>
Serialization
.deserializeCommand(chunk)
.fold(
errorDesc =>
println(
s"Got invalid chunk from client (${new String(chunk.toArray, "UTF-8")}): " + errorDesc),
onCommand
)
resetChannelState()
case Some(_) =>
val str = (new String(chunk.toArray, "UTF-8")).trim
handleHeader(str) match {
case Some(_) =>
state = InHeader
process()
case _ => println("Got invalid chunk from client: " + str)
}
}
case _ => ()
}
case InHeader =>
tillEndOfLine match {
case Some(chunk) =>
val str = (new String(chunk.toArray, "UTF-8")).trim
if (str == "") {
state = InBody
process()
} else
handleHeader(str) match {
case Some(_) => process()
case _ =>
println("Got invalid header from client: " + str)
resetChannelState()
}
case _ => ()
}
case InBody =>
tillContentLength match {
case Some(chunk) =>
handleBody(chunk)
process()
case _ => ()
}
}
}
// keep going unless the socket has closed
while (bytesRead != -1 && running.get) {
try {
bytesRead = in.read(readBuffer)
buffer = buffer ++ readBuffer.toVector.take(bytesRead)
// handle un-framing
var delimPos = buffer.indexOf(delimiter)
while (delimPos > -1) {
val chunk = buffer.take(delimPos)
buffer = buffer.drop(delimPos + 1)
Serialization
.deserializeCommand(chunk)
.fold(
errorDesc => println("Got invalid chunk from client: " + errorDesc),
onCommand
)
delimPos = buffer.indexOf(delimiter)
println(s"bytesRead: $bytesRead")
if (bytesRead > 0) {
buffer = buffer ++ readBuffer.toVector.take(bytesRead)
}
process()
} catch {
case _: SocketTimeoutException => // its ok
}
}
} // while
} finally {
shutdown()
}
}
def handleBody(chunk: Vector[Byte]): Unit = {
if (isLanguageServerProtocol) {
Serialization.deserializeJsonRequest(chunk) match {
case Right(req) =>
try {
onRequestMessage(req)
} catch {
case LangServerError(code, message) =>
println(s"sending error: $code: $message")
langError(Option(req.id), code, message)
}
case Left(errorDesc) =>
val msg = s"Got invalid chunk from client (${new String(chunk.toArray, "UTF-8")}): " + errorDesc
langError(None, ErrorCodes.ParseError, msg)
}
} else {
contentType match {
case SbtX1Protocol =>
Serialization
.deserializeCommand(chunk)
.fold(
errorDesc =>
println(
s"Got invalid chunk from client (${new String(chunk.toArray, "UTF-8")}): " + errorDesc),
onCommand
)
case _ =>
println(s"Unknown Content-Type: $contentType")
}
} // if-else
}
def handleHeader(str: String): Option[Unit] = {
str match {
case ContentLength(len) =>
contentLength = len.toInt
Some(())
case ContentType(ct) =>
setContentType(ct)
Some(())
case _ => None
}
}
}
thread.start()
def publishEvent[A: JsonFormat](event: A): Unit = {
val bytes = Serialization.serializeEvent(event)
publishBytes(bytes)
private[sbt] def isLanguageServerProtocol: Boolean = {
contentType match {
case "" | VsCode | VsCodeOld => true
case _ => false
}
}
private[sbt] def notifyEvent[A: JsonFormat](method: String, params: A): Unit = {
if (isLanguageServerProtocol) {
langNotify(method, params)
} else {
()
}
}
def publishEvent[A: JsonFormat](event: A, execId: Option[String]): Unit = {
if (isLanguageServerProtocol) {
langRespond(event, execId)
} else {
contentType match {
case SbtX1Protocol =>
val bytes = Serialization.serializeEvent(event)
publishBytes(bytes, true)
case _ =>
}
}
}
def publishEvent[A: JsonFormat](event: A): Unit = publishEvent(event, None)
def publishEventMessage(event: EventMessage): Unit = {
val bytes = Serialization.serializeEventMessage(event)
publishBytes(bytes)
contentType match {
case SbtX1Protocol =>
val bytes = Serialization.serializeEventMessage(event)
publishBytes(bytes, true)
case _ =>
}
}
def publishBytes(event: Array[Byte]): Unit = {
/**
* This publishes object events. The type information has been
* erased because it went through logging.
*/
private[sbt] def publishObjectEvent(event: ObjectEvent[_]): Unit = {
import sjsonnew.shaded.scalajson.ast.unsafe._
if (isLanguageServerProtocol) onObjectEvent(event)
else {
import jsonFormat._
val json: JValue = JObject(
JField("type", JString(event.contentType)),
(Vector(JField("message", event.json), JField("level", JString(event.level.toString))) ++
(event.channelName.toVector map { channelName =>
JField("channelName", JString(channelName))
}) ++
(event.execId.toVector map { execId =>
JField("execId", JString(execId))
})): _*
)
publishEvent(json)
}
}
def publishBytes(event: Array[Byte]): Unit = publishBytes(event, false)
def publishBytes(event: Array[Byte], delimit: Boolean): Unit = {
out.write(event)
out.write(delimiter.toInt)
if (delimit) {
out.write(delimiter.toInt)
}
out.flush()
}
@ -84,7 +294,7 @@ final class NetworkChannel(val name: String,
if (auth(ServerAuthentication.Token)) {
cmd.token match {
case Some(x) =>
instance.authenticate(x) match {
authenticate(x) match {
case true =>
initialized = true
publishEventMessage(ChannelAcceptedEvent(name))
@ -120,3 +330,10 @@ final class NetworkChannel(val name: String,
out.close()
}
}
object NetworkChannel {
sealed trait ChannelState
case object SingleLine extends ChannelState
case object InHeader extends ChannelState
case object InBody extends ChannelState
}

View File

@ -13,9 +13,9 @@ object Dependencies {
// sbt modules
private val ioVersion = "1.1.0"
private val utilVersion = "1.0.1"
private val utilVersion = "1.0.2"
private val lmVersion = "1.0.2"
private val zincVersion = "1.0.1"
private val zincVersion = "1.0.2"
private val sbtIO = "org.scala-sbt" %% "io" % ioVersion

View File

@ -8,6 +8,6 @@ addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.17")
// addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "1.2.0")
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.1")
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.0")
addSbtPlugin("org.scala-sbt" % "sbt-contraband" % "0.3.1")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0-M1")
addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.10")

View File

@ -0,0 +1,26 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
trait InitializeResultFormats { self: ServerCapabilitiesFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val InitializeResultFormat: JsonFormat[sbt.internal.langserver.InitializeResult] = new JsonFormat[sbt.internal.langserver.InitializeResult] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.InitializeResult = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val capabilities = unbuilder.readField[Option[sbt.internal.langserver.ServerCapabilities]]("capabilities")
unbuilder.endObject()
sbt.internal.langserver.InitializeResult(capabilities)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.InitializeResult, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("capabilities", obj.capabilities)
builder.endObject()
}
}
}

View File

@ -0,0 +1,26 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
trait ServerCapabilitiesFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val ServerCapabilitiesFormat: JsonFormat[sbt.internal.langserver.ServerCapabilities] = new JsonFormat[sbt.internal.langserver.ServerCapabilities] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.ServerCapabilities = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val hoverProvider = unbuilder.readField[Option[Boolean]]("hoverProvider")
unbuilder.endObject()
sbt.internal.langserver.ServerCapabilities(hoverProvider)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.ServerCapabilities, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("hoverProvider", obj.hoverProvider)
builder.endObject()
}
}
}

View File

@ -0,0 +1,29 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
final class ClientCapabilities private () extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: ClientCapabilities => true
case _ => false
}
override def hashCode: Int = {
37 * (17 + "sbt.internal.langserver.ClientCapabilities".##)
}
override def toString: String = {
"ClientCapabilities()"
}
protected[this] def copy(): ClientCapabilities = {
new ClientCapabilities()
}
}
object ClientCapabilities {
def apply(): ClientCapabilities = new ClientCapabilities()
}

View File

@ -0,0 +1,73 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
/**
* Represents a diagnostic, such as a compiler error or warning.
* Diagnostic objects are only valid in the scope of a resource.
*/
final class Diagnostic private (
/** The range at which the message applies. */
val range: sbt.internal.langserver.Range,
/**
* The diagnostic's severity. Can be omitted. If omitted it is up to the
* client to interpret diagnostics as error, warning, info or hint.
*/
val severity: Option[Long],
/** The diagnostic's code. Can be omitted. */
val code: Option[String],
/**
* A human-readable string describing the source of this
* diagnostic, e.g. 'typescript' or 'super lint'.
*/
val source: Option[String],
/** The diagnostic's message. */
val message: String) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: Diagnostic => (this.range == x.range) && (this.severity == x.severity) && (this.code == x.code) && (this.source == x.source) && (this.message == x.message)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.langserver.Diagnostic".##) + range.##) + severity.##) + code.##) + source.##) + message.##)
}
override def toString: String = {
"Diagnostic(" + range + ", " + severity + ", " + code + ", " + source + ", " + message + ")"
}
protected[this] def copy(range: sbt.internal.langserver.Range = range, severity: Option[Long] = severity, code: Option[String] = code, source: Option[String] = source, message: String = message): Diagnostic = {
new Diagnostic(range, severity, code, source, message)
}
def withRange(range: sbt.internal.langserver.Range): Diagnostic = {
copy(range = range)
}
def withSeverity(severity: Option[Long]): Diagnostic = {
copy(severity = severity)
}
def withSeverity(severity: Long): Diagnostic = {
copy(severity = Option(severity))
}
def withCode(code: Option[String]): Diagnostic = {
copy(code = code)
}
def withCode(code: String): Diagnostic = {
copy(code = Option(code))
}
def withSource(source: Option[String]): Diagnostic = {
copy(source = source)
}
def withSource(source: String): Diagnostic = {
copy(source = Option(source))
}
def withMessage(message: String): Diagnostic = {
copy(message = message)
}
}
object Diagnostic {
def apply(range: sbt.internal.langserver.Range, severity: Option[Long], code: Option[String], source: Option[String], message: String): Diagnostic = new Diagnostic(range, severity, code, source, message)
def apply(range: sbt.internal.langserver.Range, severity: Long, code: String, source: String, message: String): Diagnostic = new Diagnostic(range, Option(severity), Option(code), Option(source), message)
}

View File

@ -0,0 +1,72 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
final class InitializeParams private (
val processId: Option[Long],
/** The rootPath of the workspace. */
val rootPath: Option[String],
val rootUri: Option[String],
val initializationOptions: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue],
val capabilities: Option[sbt.internal.langserver.ClientCapabilities],
val trace: Option[String]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: InitializeParams => (this.processId == x.processId) && (this.rootPath == x.rootPath) && (this.rootUri == x.rootUri) && (this.initializationOptions == x.initializationOptions) && (this.capabilities == x.capabilities) && (this.trace == x.trace)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.langserver.InitializeParams".##) + processId.##) + rootPath.##) + rootUri.##) + initializationOptions.##) + capabilities.##) + trace.##)
}
override def toString: String = {
"InitializeParams(" + processId + ", " + rootPath + ", " + rootUri + ", " + initializationOptions + ", " + capabilities + ", " + trace + ")"
}
protected[this] def copy(processId: Option[Long] = processId, rootPath: Option[String] = rootPath, rootUri: Option[String] = rootUri, initializationOptions: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = initializationOptions, capabilities: Option[sbt.internal.langserver.ClientCapabilities] = capabilities, trace: Option[String] = trace): InitializeParams = {
new InitializeParams(processId, rootPath, rootUri, initializationOptions, capabilities, trace)
}
def withProcessId(processId: Option[Long]): InitializeParams = {
copy(processId = processId)
}
def withProcessId(processId: Long): InitializeParams = {
copy(processId = Option(processId))
}
def withRootPath(rootPath: Option[String]): InitializeParams = {
copy(rootPath = rootPath)
}
def withRootPath(rootPath: String): InitializeParams = {
copy(rootPath = Option(rootPath))
}
def withRootUri(rootUri: Option[String]): InitializeParams = {
copy(rootUri = rootUri)
}
def withRootUri(rootUri: String): InitializeParams = {
copy(rootUri = Option(rootUri))
}
def withInitializationOptions(initializationOptions: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): InitializeParams = {
copy(initializationOptions = initializationOptions)
}
def withInitializationOptions(initializationOptions: sjsonnew.shaded.scalajson.ast.unsafe.JValue): InitializeParams = {
copy(initializationOptions = Option(initializationOptions))
}
def withCapabilities(capabilities: Option[sbt.internal.langserver.ClientCapabilities]): InitializeParams = {
copy(capabilities = capabilities)
}
def withCapabilities(capabilities: sbt.internal.langserver.ClientCapabilities): InitializeParams = {
copy(capabilities = Option(capabilities))
}
def withTrace(trace: Option[String]): InitializeParams = {
copy(trace = trace)
}
def withTrace(trace: String): InitializeParams = {
copy(trace = Option(trace))
}
}
object InitializeParams {
def apply(processId: Option[Long], rootPath: Option[String], rootUri: Option[String], initializationOptions: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue], capabilities: Option[sbt.internal.langserver.ClientCapabilities], trace: Option[String]): InitializeParams = new InitializeParams(processId, rootPath, rootUri, initializationOptions, capabilities, trace)
def apply(processId: Long, rootPath: String, rootUri: String, initializationOptions: sjsonnew.shaded.scalajson.ast.unsafe.JValue, capabilities: sbt.internal.langserver.ClientCapabilities, trace: String): InitializeParams = new InitializeParams(Option(processId), Option(rootPath), Option(rootUri), Option(initializationOptions), Option(capabilities), Option(trace))
}

View File

@ -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
final class InitializeResult private (
/** The capabilities the language server provides. */
val capabilities: sbt.internal.langserver.ServerCapabilities) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: InitializeResult => (this.capabilities == x.capabilities)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + "sbt.internal.langserver.InitializeResult".##) + capabilities.##)
}
override def toString: String = {
"InitializeResult(" + capabilities + ")"
}
protected[this] def copy(capabilities: sbt.internal.langserver.ServerCapabilities = capabilities): InitializeResult = {
new InitializeResult(capabilities)
}
def withCapabilities(capabilities: sbt.internal.langserver.ServerCapabilities): InitializeResult = {
copy(capabilities = capabilities)
}
}
object InitializeResult {
def apply(capabilities: sbt.internal.langserver.ServerCapabilities): InitializeResult = new InitializeResult(capabilities)
}

View File

@ -0,0 +1,37 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
/** Represents a location inside a resource, such as a line inside a text file. */
final class Location private (
val uri: String,
val range: sbt.internal.langserver.Range) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: Location => (this.uri == x.uri) && (this.range == x.range)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (17 + "sbt.internal.langserver.Location".##) + uri.##) + range.##)
}
override def toString: String = {
"Location(" + uri + ", " + range + ")"
}
protected[this] def copy(uri: String = uri, range: sbt.internal.langserver.Range = range): Location = {
new Location(uri, range)
}
def withUri(uri: String): Location = {
copy(uri = uri)
}
def withRange(range: sbt.internal.langserver.Range): Location = {
copy(range = range)
}
}
object Location {
def apply(uri: String, range: sbt.internal.langserver.Range): Location = new Location(uri, range)
}

View File

@ -0,0 +1,42 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
/**
* Position in a text document expressed as zero-based line and zero-based character offset.
* A position is between two characters like an 'insert' cursor in a editor.
*/
final class Position private (
/** Line position in a document (zero-based). */
val line: Long,
/** Character offset on a line in a document (zero-based). */
val character: Long) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: Position => (this.line == x.line) && (this.character == x.character)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (17 + "sbt.internal.langserver.Position".##) + line.##) + character.##)
}
override def toString: String = {
"Position(" + line + ", " + character + ")"
}
protected[this] def copy(line: Long = line, character: Long = character): Position = {
new Position(line, character)
}
def withLine(line: Long): Position = {
copy(line = line)
}
def withCharacter(character: Long): Position = {
copy(character = character)
}
}
object Position {
def apply(line: Long, character: Long): Position = new Position(line, character)
}

View File

@ -0,0 +1,39 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
/** Diagnostics notification are sent from the server to the client to signal results of validation runs. */
final class PublishDiagnosticsParams private (
/** The URI for which diagnostic information is reported. */
val uri: String,
/** An array of diagnostic information items. */
val diagnostics: Vector[sbt.internal.langserver.Diagnostic]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: PublishDiagnosticsParams => (this.uri == x.uri) && (this.diagnostics == x.diagnostics)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (17 + "sbt.internal.langserver.PublishDiagnosticsParams".##) + uri.##) + diagnostics.##)
}
override def toString: String = {
"PublishDiagnosticsParams(" + uri + ", " + diagnostics + ")"
}
protected[this] def copy(uri: String = uri, diagnostics: Vector[sbt.internal.langserver.Diagnostic] = diagnostics): PublishDiagnosticsParams = {
new PublishDiagnosticsParams(uri, diagnostics)
}
def withUri(uri: String): PublishDiagnosticsParams = {
copy(uri = uri)
}
def withDiagnostics(diagnostics: Vector[sbt.internal.langserver.Diagnostic]): PublishDiagnosticsParams = {
copy(diagnostics = diagnostics)
}
}
object PublishDiagnosticsParams {
def apply(uri: String, diagnostics: Vector[sbt.internal.langserver.Diagnostic]): PublishDiagnosticsParams = new PublishDiagnosticsParams(uri, diagnostics)
}

View File

@ -0,0 +1,42 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
/**
* A range in a text document expressed as (zero-based) start and end positions. A range is comparable to a selection in an editor.
* Therefore the end position is exclusive.
*/
final class Range private (
/** The range's start position. */
val start: sbt.internal.langserver.Position,
/** The range's end position. */
val end: sbt.internal.langserver.Position) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: Range => (this.start == x.start) && (this.end == x.end)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (17 + "sbt.internal.langserver.Range".##) + start.##) + end.##)
}
override def toString: String = {
"Range(" + start + ", " + end + ")"
}
protected[this] def copy(start: sbt.internal.langserver.Position = start, end: sbt.internal.langserver.Position = end): Range = {
new Range(start, end)
}
def withStart(start: sbt.internal.langserver.Position): Range = {
copy(start = start)
}
def withEnd(end: sbt.internal.langserver.Position): Range = {
copy(end = end)
}
}
object Range {
def apply(start: sbt.internal.langserver.Position, end: sbt.internal.langserver.Position): Range = new Range(start, end)
}

View File

@ -0,0 +1,37 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
final class SaveOptions private (
/** The client is supposed to include the content on save. */
val includeText: Option[Boolean]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: SaveOptions => (this.includeText == x.includeText)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + "sbt.internal.langserver.SaveOptions".##) + includeText.##)
}
override def toString: String = {
"SaveOptions(" + includeText + ")"
}
protected[this] def copy(includeText: Option[Boolean] = includeText): SaveOptions = {
new SaveOptions(includeText)
}
def withIncludeText(includeText: Option[Boolean]): SaveOptions = {
copy(includeText = includeText)
}
def withIncludeText(includeText: Boolean): SaveOptions = {
copy(includeText = Option(includeText))
}
}
object SaveOptions {
def apply(includeText: Option[Boolean]): SaveOptions = new SaveOptions(includeText)
def apply(includeText: Boolean): SaveOptions = new SaveOptions(Option(includeText))
}

View File

@ -0,0 +1,44 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
final class ServerCapabilities private (
val textDocumentSync: Option[sbt.internal.langserver.TextDocumentSyncOptions],
/** The server provides hover support. */
val hoverProvider: Option[Boolean]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: ServerCapabilities => (this.textDocumentSync == x.textDocumentSync) && (this.hoverProvider == x.hoverProvider)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (17 + "sbt.internal.langserver.ServerCapabilities".##) + textDocumentSync.##) + hoverProvider.##)
}
override def toString: String = {
"ServerCapabilities(" + textDocumentSync + ", " + hoverProvider + ")"
}
protected[this] def copy(textDocumentSync: Option[sbt.internal.langserver.TextDocumentSyncOptions] = textDocumentSync, hoverProvider: Option[Boolean] = hoverProvider): ServerCapabilities = {
new ServerCapabilities(textDocumentSync, hoverProvider)
}
def withTextDocumentSync(textDocumentSync: Option[sbt.internal.langserver.TextDocumentSyncOptions]): ServerCapabilities = {
copy(textDocumentSync = textDocumentSync)
}
def withTextDocumentSync(textDocumentSync: sbt.internal.langserver.TextDocumentSyncOptions): ServerCapabilities = {
copy(textDocumentSync = Option(textDocumentSync))
}
def withHoverProvider(hoverProvider: Option[Boolean]): ServerCapabilities = {
copy(hoverProvider = hoverProvider)
}
def withHoverProvider(hoverProvider: Boolean): ServerCapabilities = {
copy(hoverProvider = Option(hoverProvider))
}
}
object ServerCapabilities {
def apply(textDocumentSync: Option[sbt.internal.langserver.TextDocumentSyncOptions], hoverProvider: Option[Boolean]): ServerCapabilities = new ServerCapabilities(textDocumentSync, hoverProvider)
def apply(textDocumentSync: sbt.internal.langserver.TextDocumentSyncOptions, hoverProvider: Boolean): ServerCapabilities = new ServerCapabilities(Option(textDocumentSync), Option(hoverProvider))
}

View File

@ -0,0 +1,64 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver
final class TextDocumentSyncOptions private (
val openClose: Option[Boolean],
val change: Option[Long],
val willSave: Option[Boolean],
val willSaveWaitUntil: Option[Boolean],
val save: Option[sbt.internal.langserver.SaveOptions]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: TextDocumentSyncOptions => (this.openClose == x.openClose) && (this.change == x.change) && (this.willSave == x.willSave) && (this.willSaveWaitUntil == x.willSaveWaitUntil) && (this.save == x.save)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.langserver.TextDocumentSyncOptions".##) + openClose.##) + change.##) + willSave.##) + willSaveWaitUntil.##) + save.##)
}
override def toString: String = {
"TextDocumentSyncOptions(" + openClose + ", " + change + ", " + willSave + ", " + willSaveWaitUntil + ", " + save + ")"
}
protected[this] def copy(openClose: Option[Boolean] = openClose, change: Option[Long] = change, willSave: Option[Boolean] = willSave, willSaveWaitUntil: Option[Boolean] = willSaveWaitUntil, save: Option[sbt.internal.langserver.SaveOptions] = save): TextDocumentSyncOptions = {
new TextDocumentSyncOptions(openClose, change, willSave, willSaveWaitUntil, save)
}
def withOpenClose(openClose: Option[Boolean]): TextDocumentSyncOptions = {
copy(openClose = openClose)
}
def withOpenClose(openClose: Boolean): TextDocumentSyncOptions = {
copy(openClose = Option(openClose))
}
def withChange(change: Option[Long]): TextDocumentSyncOptions = {
copy(change = change)
}
def withChange(change: Long): TextDocumentSyncOptions = {
copy(change = Option(change))
}
def withWillSave(willSave: Option[Boolean]): TextDocumentSyncOptions = {
copy(willSave = willSave)
}
def withWillSave(willSave: Boolean): TextDocumentSyncOptions = {
copy(willSave = Option(willSave))
}
def withWillSaveWaitUntil(willSaveWaitUntil: Option[Boolean]): TextDocumentSyncOptions = {
copy(willSaveWaitUntil = willSaveWaitUntil)
}
def withWillSaveWaitUntil(willSaveWaitUntil: Boolean): TextDocumentSyncOptions = {
copy(willSaveWaitUntil = Option(willSaveWaitUntil))
}
def withSave(save: Option[sbt.internal.langserver.SaveOptions]): TextDocumentSyncOptions = {
copy(save = save)
}
def withSave(save: sbt.internal.langserver.SaveOptions): TextDocumentSyncOptions = {
copy(save = Option(save))
}
}
object TextDocumentSyncOptions {
def apply(openClose: Option[Boolean], change: Option[Long], willSave: Option[Boolean], willSaveWaitUntil: Option[Boolean], save: Option[sbt.internal.langserver.SaveOptions]): TextDocumentSyncOptions = new TextDocumentSyncOptions(openClose, change, willSave, willSaveWaitUntil, save)
def apply(openClose: Boolean, change: Long, willSave: Boolean, willSaveWaitUntil: Boolean, save: sbt.internal.langserver.SaveOptions): TextDocumentSyncOptions = new TextDocumentSyncOptions(Option(openClose), Option(change), Option(willSave), Option(willSaveWaitUntil), Option(save))
}

View File

@ -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 ClientCapabilitiesFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val ClientCapabilitiesFormat: JsonFormat[sbt.internal.langserver.ClientCapabilities] = new JsonFormat[sbt.internal.langserver.ClientCapabilities] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.ClientCapabilities = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
unbuilder.endObject()
sbt.internal.langserver.ClientCapabilities()
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.ClientCapabilities, builder: Builder[J]): Unit = {
builder.beginObject()
builder.endObject()
}
}
}

View File

@ -0,0 +1,35 @@
/**
* 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 DiagnosticFormats { self: sbt.internal.langserver.codec.RangeFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val DiagnosticFormat: JsonFormat[sbt.internal.langserver.Diagnostic] = new JsonFormat[sbt.internal.langserver.Diagnostic] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.Diagnostic = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val range = unbuilder.readField[sbt.internal.langserver.Range]("range")
val severity = unbuilder.readField[Option[Long]]("severity")
val code = unbuilder.readField[Option[String]]("code")
val source = unbuilder.readField[Option[String]]("source")
val message = unbuilder.readField[String]("message")
unbuilder.endObject()
sbt.internal.langserver.Diagnostic(range, severity, code, source, message)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.Diagnostic, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("range", obj.range)
builder.addField("severity", obj.severity)
builder.addField("code", obj.code)
builder.addField("source", obj.source)
builder.addField("message", obj.message)
builder.endObject()
}
}
}

View File

@ -0,0 +1,37 @@
/**
* 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 InitializeParamsFormats { self: sbt.internal.util.codec.JValueFormats with sbt.internal.langserver.codec.ClientCapabilitiesFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val InitializeParamsFormat: JsonFormat[sbt.internal.langserver.InitializeParams] = new JsonFormat[sbt.internal.langserver.InitializeParams] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.InitializeParams = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val processId = unbuilder.readField[Option[Long]]("processId")
val rootPath = unbuilder.readField[Option[String]]("rootPath")
val rootUri = unbuilder.readField[Option[String]]("rootUri")
val initializationOptions = unbuilder.readField[Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]]("initializationOptions")
val capabilities = unbuilder.readField[Option[sbt.internal.langserver.ClientCapabilities]]("capabilities")
val trace = unbuilder.readField[Option[String]]("trace")
unbuilder.endObject()
sbt.internal.langserver.InitializeParams(processId, rootPath, rootUri, initializationOptions, capabilities, trace)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.InitializeParams, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("processId", obj.processId)
builder.addField("rootPath", obj.rootPath)
builder.addField("rootUri", obj.rootUri)
builder.addField("initializationOptions", obj.initializationOptions)
builder.addField("capabilities", obj.capabilities)
builder.addField("trace", obj.trace)
builder.endObject()
}
}
}

View File

@ -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 InitializeResultFormats { self: sbt.internal.langserver.codec.ServerCapabilitiesFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val InitializeResultFormat: JsonFormat[sbt.internal.langserver.InitializeResult] = new JsonFormat[sbt.internal.langserver.InitializeResult] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.InitializeResult = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val capabilities = unbuilder.readField[sbt.internal.langserver.ServerCapabilities]("capabilities")
unbuilder.endObject()
sbt.internal.langserver.InitializeResult(capabilities)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.InitializeResult, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("capabilities", obj.capabilities)
builder.endObject()
}
}
}

View File

@ -0,0 +1,20 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.langserver.codec
trait JsonProtocol extends sjsonnew.BasicJsonProtocol
with sbt.internal.langserver.codec.PositionFormats
with sbt.internal.langserver.codec.RangeFormats
with sbt.internal.langserver.codec.LocationFormats
with sbt.internal.langserver.codec.DiagnosticFormats
with sbt.internal.util.codec.JValueFormats
with sbt.internal.langserver.codec.ClientCapabilitiesFormats
with sbt.internal.langserver.codec.InitializeParamsFormats
with sbt.internal.langserver.codec.SaveOptionsFormats
with sbt.internal.langserver.codec.TextDocumentSyncOptionsFormats
with sbt.internal.langserver.codec.ServerCapabilitiesFormats
with sbt.internal.langserver.codec.InitializeResultFormats
with sbt.internal.langserver.codec.PublishDiagnosticsParamsFormats
object JsonProtocol extends JsonProtocol

View File

@ -0,0 +1,29 @@
/**
* 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 LocationFormats { self: sbt.internal.langserver.codec.RangeFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val LocationFormat: JsonFormat[sbt.internal.langserver.Location] = new JsonFormat[sbt.internal.langserver.Location] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.Location = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val uri = unbuilder.readField[String]("uri")
val range = unbuilder.readField[sbt.internal.langserver.Range]("range")
unbuilder.endObject()
sbt.internal.langserver.Location(uri, range)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.Location, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("uri", obj.uri)
builder.addField("range", obj.range)
builder.endObject()
}
}
}

View File

@ -0,0 +1,29 @@
/**
* 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 PositionFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val PositionFormat: JsonFormat[sbt.internal.langserver.Position] = new JsonFormat[sbt.internal.langserver.Position] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.Position = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val line = unbuilder.readField[Long]("line")
val character = unbuilder.readField[Long]("character")
unbuilder.endObject()
sbt.internal.langserver.Position(line, character)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.Position, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("line", obj.line)
builder.addField("character", obj.character)
builder.endObject()
}
}
}

View File

@ -0,0 +1,29 @@
/**
* 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 PublishDiagnosticsParamsFormats { self: sbt.internal.langserver.codec.DiagnosticFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val PublishDiagnosticsParamsFormat: JsonFormat[sbt.internal.langserver.PublishDiagnosticsParams] = new JsonFormat[sbt.internal.langserver.PublishDiagnosticsParams] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.PublishDiagnosticsParams = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val uri = unbuilder.readField[String]("uri")
val diagnostics = unbuilder.readField[Vector[sbt.internal.langserver.Diagnostic]]("diagnostics")
unbuilder.endObject()
sbt.internal.langserver.PublishDiagnosticsParams(uri, diagnostics)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.PublishDiagnosticsParams, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("uri", obj.uri)
builder.addField("diagnostics", obj.diagnostics)
builder.endObject()
}
}
}

View File

@ -0,0 +1,29 @@
/**
* 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 RangeFormats { self: sbt.internal.langserver.codec.PositionFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val RangeFormat: JsonFormat[sbt.internal.langserver.Range] = new JsonFormat[sbt.internal.langserver.Range] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.Range = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val start = unbuilder.readField[sbt.internal.langserver.Position]("start")
val end = unbuilder.readField[sbt.internal.langserver.Position]("end")
unbuilder.endObject()
sbt.internal.langserver.Range(start, end)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.Range, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("start", obj.start)
builder.addField("end", obj.end)
builder.endObject()
}
}
}

View File

@ -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 SaveOptionsFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val SaveOptionsFormat: JsonFormat[sbt.internal.langserver.SaveOptions] = new JsonFormat[sbt.internal.langserver.SaveOptions] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.SaveOptions = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val includeText = unbuilder.readField[Option[Boolean]]("includeText")
unbuilder.endObject()
sbt.internal.langserver.SaveOptions(includeText)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.SaveOptions, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("includeText", obj.includeText)
builder.endObject()
}
}
}

View File

@ -0,0 +1,29 @@
/**
* 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 ServerCapabilitiesFormats { self: sbt.internal.langserver.codec.TextDocumentSyncOptionsFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val ServerCapabilitiesFormat: JsonFormat[sbt.internal.langserver.ServerCapabilities] = new JsonFormat[sbt.internal.langserver.ServerCapabilities] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.ServerCapabilities = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val textDocumentSync = unbuilder.readField[Option[sbt.internal.langserver.TextDocumentSyncOptions]]("textDocumentSync")
val hoverProvider = unbuilder.readField[Option[Boolean]]("hoverProvider")
unbuilder.endObject()
sbt.internal.langserver.ServerCapabilities(textDocumentSync, hoverProvider)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.ServerCapabilities, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("textDocumentSync", obj.textDocumentSync)
builder.addField("hoverProvider", obj.hoverProvider)
builder.endObject()
}
}
}

View File

@ -0,0 +1,35 @@
/**
* 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 TextDocumentSyncOptionsFormats { self: sbt.internal.langserver.codec.SaveOptionsFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val TextDocumentSyncOptionsFormat: JsonFormat[sbt.internal.langserver.TextDocumentSyncOptions] = new JsonFormat[sbt.internal.langserver.TextDocumentSyncOptions] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.langserver.TextDocumentSyncOptions = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val openClose = unbuilder.readField[Option[Boolean]]("openClose")
val change = unbuilder.readField[Option[Long]]("change")
val willSave = unbuilder.readField[Option[Boolean]]("willSave")
val willSaveWaitUntil = unbuilder.readField[Option[Boolean]]("willSaveWaitUntil")
val save = unbuilder.readField[Option[sbt.internal.langserver.SaveOptions]]("save")
unbuilder.endObject()
sbt.internal.langserver.TextDocumentSyncOptions(openClose, change, willSave, willSaveWaitUntil, save)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.langserver.TextDocumentSyncOptions, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("openClose", obj.openClose)
builder.addField("change", obj.change)
builder.addField("willSave", obj.willSave)
builder.addField("willSaveWaitUntil", obj.willSaveWaitUntil)
builder.addField("save", obj.save)
builder.endObject()
}
}
}

View File

@ -0,0 +1,36 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol
final class InitializeOption private (
val token: Option[String]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: InitializeOption => (this.token == x.token)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + "sbt.internal.protocol.InitializeOption".##) + token.##)
}
override def toString: String = {
"InitializeOption(" + token + ")"
}
protected[this] def copy(token: Option[String] = token): InitializeOption = {
new InitializeOption(token)
}
def withToken(token: Option[String]): InitializeOption = {
copy(token = token)
}
def withToken(token: String): InitializeOption = {
copy(token = Option(token))
}
}
object InitializeOption {
def apply(token: Option[String]): InitializeOption = new InitializeOption(token)
def apply(token: String): InitializeOption = new InitializeOption(Option(token))
}

View File

@ -0,0 +1,27 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol
/** A general message as defined by JSON-RPC. */
abstract class JsonRpcMessage(
val jsonrpc: String) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: JsonRpcMessage => (this.jsonrpc == x.jsonrpc)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + "sbt.internal.protocol.JsonRpcMessage".##) + jsonrpc.##)
}
override def toString: String = {
"JsonRpcMessage(" + jsonrpc + ")"
}
}
object JsonRpcMessage {
}

View File

@ -0,0 +1,46 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol
final class JsonRpcNotificationMessage private (
jsonrpc: String,
/** The method to be invoked. */
val method: String,
/** The method's params. */
val params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends sbt.internal.protocol.JsonRpcMessage(jsonrpc) with Serializable {
override def equals(o: Any): Boolean = o match {
case x: JsonRpcNotificationMessage => (this.jsonrpc == x.jsonrpc) && (this.method == x.method) && (this.params == x.params)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (17 + "sbt.internal.protocol.JsonRpcNotificationMessage".##) + jsonrpc.##) + method.##) + params.##)
}
override def toString: String = {
s"""JsonRpcNotificationMessage($jsonrpc, $method, ${sbt.protocol.Serialization.compactPrintJsonOpt(params)})"""
}
protected[this] def copy(jsonrpc: String = jsonrpc, method: String = method, params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = params): JsonRpcNotificationMessage = {
new JsonRpcNotificationMessage(jsonrpc, method, params)
}
def withJsonrpc(jsonrpc: String): JsonRpcNotificationMessage = {
copy(jsonrpc = jsonrpc)
}
def withMethod(method: String): JsonRpcNotificationMessage = {
copy(method = method)
}
def withParams(params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcNotificationMessage = {
copy(params = params)
}
def withParams(params: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcNotificationMessage = {
copy(params = Option(params))
}
}
object JsonRpcNotificationMessage {
def apply(jsonrpc: String, method: String, params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcNotificationMessage = new JsonRpcNotificationMessage(jsonrpc, method, params)
def apply(jsonrpc: String, method: String, params: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcNotificationMessage = new JsonRpcNotificationMessage(jsonrpc, method, Option(params))
}

View File

@ -0,0 +1,51 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol
final class JsonRpcRequestMessage private (
jsonrpc: String,
/** The request id. */
val id: String,
/** The method to be invoked. */
val method: String,
/** The method's params. */
val params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends sbt.internal.protocol.JsonRpcMessage(jsonrpc) with Serializable {
override def equals(o: Any): Boolean = o match {
case x: JsonRpcRequestMessage => (this.jsonrpc == x.jsonrpc) && (this.id == x.id) && (this.method == x.method) && (this.params == x.params)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.protocol.JsonRpcRequestMessage".##) + jsonrpc.##) + id.##) + method.##) + params.##)
}
override def toString: String = {
s"""JsonRpcRequestMessage($jsonrpc, $id, $method, ${sbt.protocol.Serialization.compactPrintJsonOpt(params)}})"""
}
protected[this] def copy(jsonrpc: String = jsonrpc, id: String = id, method: String = method, params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = params): JsonRpcRequestMessage = {
new JsonRpcRequestMessage(jsonrpc, id, method, params)
}
def withJsonrpc(jsonrpc: String): JsonRpcRequestMessage = {
copy(jsonrpc = jsonrpc)
}
def withId(id: String): JsonRpcRequestMessage = {
copy(id = id)
}
def withMethod(method: String): JsonRpcRequestMessage = {
copy(method = method)
}
def withParams(params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcRequestMessage = {
copy(params = params)
}
def withParams(params: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcRequestMessage = {
copy(params = Option(params))
}
}
object JsonRpcRequestMessage {
def apply(jsonrpc: String, id: String, method: String, params: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcRequestMessage = new JsonRpcRequestMessage(jsonrpc, id, method, params)
def apply(jsonrpc: String, id: String, method: String, params: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcRequestMessage = new JsonRpcRequestMessage(jsonrpc, id, method, Option(params))
}

View File

@ -0,0 +1,50 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol
final class JsonRpcResponseError private (
/** A number indicating the error type that occurred. */
val code: Long,
/** A string providing a short description of the error. */
val message: String,
/**
* A Primitive or Structured value that contains additional
* information about the error. Can be omitted.
*/
val data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: JsonRpcResponseError => (this.code == x.code) && (this.message == x.message) && (this.data == x.data)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (17 + "sbt.internal.protocol.JsonRpcResponseError".##) + code.##) + message.##) + data.##)
}
override def toString: String = {
s"""JsonRpcResponseError($code, $message, ${sbt.protocol.Serialization.compactPrintJsonOpt(data)})"""
}
protected[this] def copy(code: Long = code, message: String = message, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = data): JsonRpcResponseError = {
new JsonRpcResponseError(code, message, data)
}
def withCode(code: Long): JsonRpcResponseError = {
copy(code = code)
}
def withMessage(message: String): JsonRpcResponseError = {
copy(message = message)
}
def withData(data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcResponseError = {
copy(data = data)
}
def withData(data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcResponseError = {
copy(data = Option(data))
}
}
object JsonRpcResponseError {
def apply(code: Long, message: String, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcResponseError = new JsonRpcResponseError(code, message, data)
def apply(code: Long, message: String, data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcResponseError = new JsonRpcResponseError(code, message, Option(data))
}

View File

@ -0,0 +1,60 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol
final class JsonRpcResponseMessage private (
jsonrpc: String,
/** The request id. */
val id: Option[String],
/**
* The result of a request. This can be omitted in
* the case of an error.
*/
val result: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue],
/** The error object in case a request fails. */
val error: Option[sbt.internal.protocol.JsonRpcResponseError]) extends sbt.internal.protocol.JsonRpcMessage(jsonrpc) with Serializable {
override def equals(o: Any): Boolean = o match {
case x: JsonRpcResponseMessage => (this.jsonrpc == x.jsonrpc) && (this.id == x.id) && (this.result == x.result) && (this.error == x.error)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.protocol.JsonRpcResponseMessage".##) + jsonrpc.##) + id.##) + result.##) + error.##)
}
override def toString: String = {
s"""JsonRpcResponseMessage($jsonrpc, $id, ${sbt.protocol.Serialization.compactPrintJsonOpt(result)}, $error)"""
}
protected[this] def copy(jsonrpc: String = jsonrpc, id: Option[String] = id, result: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = result, error: Option[sbt.internal.protocol.JsonRpcResponseError] = error): JsonRpcResponseMessage = {
new JsonRpcResponseMessage(jsonrpc, id, result, error)
}
def withJsonrpc(jsonrpc: String): JsonRpcResponseMessage = {
copy(jsonrpc = jsonrpc)
}
def withId(id: Option[String]): JsonRpcResponseMessage = {
copy(id = id)
}
def withId(id: String): JsonRpcResponseMessage = {
copy(id = Option(id))
}
def withResult(result: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): JsonRpcResponseMessage = {
copy(result = result)
}
def withResult(result: sjsonnew.shaded.scalajson.ast.unsafe.JValue): JsonRpcResponseMessage = {
copy(result = Option(result))
}
def withError(error: Option[sbt.internal.protocol.JsonRpcResponseError]): JsonRpcResponseMessage = {
copy(error = error)
}
def withError(error: sbt.internal.protocol.JsonRpcResponseError): JsonRpcResponseMessage = {
copy(error = Option(error))
}
}
object JsonRpcResponseMessage {
def apply(jsonrpc: String, id: Option[String], result: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue], error: Option[sbt.internal.protocol.JsonRpcResponseError]): JsonRpcResponseMessage = new JsonRpcResponseMessage(jsonrpc, id, result, error)
def apply(jsonrpc: String, id: String, result: sjsonnew.shaded.scalajson.ast.unsafe.JValue, error: sbt.internal.protocol.JsonRpcResponseError): JsonRpcResponseMessage = new JsonRpcResponseMessage(jsonrpc, Option(id), Option(result), Option(error))
}

View File

@ -0,0 +1,27 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package sbt.internal.protocol.codec
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
trait InitializeOptionFormats { self: sjsonnew.BasicJsonProtocol =>
implicit lazy val InitializeOptionFormat: JsonFormat[sbt.internal.protocol.InitializeOption] = new JsonFormat[sbt.internal.protocol.InitializeOption] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.protocol.InitializeOption = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val token = unbuilder.readField[Option[String]]("token")
unbuilder.endObject()
sbt.internal.protocol.InitializeOption(token)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.protocol.InitializeOption, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("token", obj.token)
builder.endObject()
}
}
}

View File

@ -0,0 +1,74 @@
package sbt.internal.protocol
@target(Scala)
## A general message as defined by JSON-RPC.
interface JsonRpcMessage
@generateCodec(false)
{
jsonrpc: String!
}
type JsonRpcRequestMessage implements JsonRpcMessage
@generateCodec(false)
{
jsonrpc: String!
## The request id.
id: String!
## The method to be invoked.
method: String!
## The method's params.
params: sjsonnew.shaded.scalajson.ast.unsafe.JValue
#xtostring s"""JsonRpcRequestMessage($jsonrpc, $id, $method, ${sbt.protocol.Serialization.compactPrintJsonOpt(params)}})"""
}
type JsonRpcResponseMessage implements JsonRpcMessage
@generateCodec(false)
{
jsonrpc: String!
## The request id.
id: String
## The result of a request. This can be omitted in
## the case of an error.
result: sjsonnew.shaded.scalajson.ast.unsafe.JValue
## The error object in case a request fails.
error: sbt.internal.protocol.JsonRpcResponseError
#xtostring s"""JsonRpcResponseMessage($jsonrpc, $id, ${sbt.protocol.Serialization.compactPrintJsonOpt(result)}, $error)"""
}
type JsonRpcResponseError
@generateCodec(false)
{
## A number indicating the error type that occurred.
code: Long!
## A string providing a short description of the error.
message: String!
## A Primitive or Structured value that contains additional
## information about the error. Can be omitted.
data: sjsonnew.shaded.scalajson.ast.unsafe.JValue
#xtostring s"""JsonRpcResponseError($code, $message, ${sbt.protocol.Serialization.compactPrintJsonOpt(data)})"""
}
type JsonRpcNotificationMessage implements JsonRpcMessage
@generateCodec(false)
{
jsonrpc: String!
## The method to be invoked.
method: String!
## The method's params.
params: sjsonnew.shaded.scalajson.ast.unsafe.JValue
#xtostring s"""JsonRpcNotificationMessage($jsonrpc, $method, ${sbt.protocol.Serialization.compactPrintJsonOpt(params)})"""
}

View File

@ -0,0 +1,112 @@
package sbt.internal.langserver
@target(Scala)
@codecPackage("sbt.internal.langserver.codec")
@fullCodec("JsonProtocol")
# Basic structure
## Position in a text document expressed as zero-based line and zero-based character offset.
## A position is between two characters like an 'insert' cursor in a editor.
type Position {
## Line position in a document (zero-based).
line: Long!
## Character offset on a line in a document (zero-based).
character: Long!
}
## A range in a text document expressed as (zero-based) start and end positions. A range is comparable to a selection in an editor.
## Therefore the end position is exclusive.
type Range {
## The range's start position.
start: sbt.internal.langserver.Position!
## The range's end position.
end: sbt.internal.langserver.Position!
}
## Represents a location inside a resource, such as a line inside a text file.
type Location {
uri: String!
range: sbt.internal.langserver.Range!
}
## Represents a diagnostic, such as a compiler error or warning.
## Diagnostic objects are only valid in the scope of a resource.
type Diagnostic {
## The range at which the message applies.
range: sbt.internal.langserver.Range!
## The diagnostic's severity. Can be omitted. If omitted it is up to the
## client to interpret diagnostics as error, warning, info or hint.
severity: Long
## The diagnostic's code. Can be omitted.
code: String
## A human-readable string describing the source of this
## diagnostic, e.g. 'typescript' or 'super lint'.
source: String
## The diagnostic's message.
message: String!
}
# initialize request
# https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#initialize-request
type InitializeParams {
processId: Long
## The rootPath of the workspace.
rootPath: String
rootUri: String
initializationOptions: sjsonnew.shaded.scalajson.ast.unsafe.JValue
capabilities: sbt.internal.langserver.ClientCapabilities
trace: String
}
type ClientCapabilities {
}
type InitializeResult {
## The capabilities the language server provides.
capabilities: sbt.internal.langserver.ServerCapabilities!
}
type ServerCapabilities {
textDocumentSync: sbt.internal.langserver.TextDocumentSyncOptions
## The server provides hover support.
hoverProvider: Boolean
}
type TextDocumentSyncOptions {
openClose: Boolean
change: Long
willSave: Boolean
willSaveWaitUntil: Boolean
save: sbt.internal.langserver.SaveOptions
}
type SaveOptions {
## The client is supposed to include the content on save.
includeText: Boolean
}
# Document
# PublishDiagnostics Notification https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#textDocument_publishDiagnostics
## Diagnostics notification are sent from the server to the client to signal results of validation runs.
type PublishDiagnosticsParams {
## The URI for which diagnostic information is reported.
uri: String!
## An array of diagnostic information items.
diagnostics: [sbt.internal.langserver.Diagnostic]
}

View File

@ -15,3 +15,7 @@ type TokenFile {
uri: String!
token: String!
}
type InitializeOption {
token: String
}

View File

@ -0,0 +1,26 @@
package sbt
package internal
package langserver
object DiagnosticSeverity {
/**
* Reports an error.
*/
val Error = 1L
/**
* Reports a warning.
*/
val Warning = 2L
/**
* Reports an information.
*/
val Information = 3L
/**
* Reports a hint.
*/
val Hint = 4L
}

View File

@ -0,0 +1,19 @@
package sbt
package internal
package langserver
object ErrorCodes {
// Defined by JSON RPC
val ParseError = -32700L
val InvalidRequest = -32600L
val MethodNotFound = -32601L
val InvalidParams = -32602L
val InternalError = -32603L
val serverErrorStart = -32099L
val serverErrorEnd = -32000L
val ServerNotInitialized = -32002L
val UnknownErrorCode = -32001L
// Defined by the protocol.
val RequestCancelled = -32800L
}

View File

@ -0,0 +1,13 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
package sbt.internal.protocol.codec
trait JsonRPCProtocol
extends sbt.internal.util.codec.JValueFormats
with sjsonnew.BasicJsonProtocol
with sbt.internal.protocol.codec.JsonRpcRequestMessageFormats
with sbt.internal.protocol.codec.JsonRpcResponseErrorFormats
with sbt.internal.protocol.codec.JsonRpcResponseMessageFormats
with sbt.internal.protocol.codec.JsonRpcNotificationMessageFormats
object JsonRPCProtocol extends JsonRPCProtocol

View File

@ -0,0 +1,40 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
package sbt.internal.protocol.codec
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
import sjsonnew.shaded.scalajson.ast.unsafe.JValue
trait JsonRpcNotificationMessageFormats {
self: sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val JsonRpcNotificationMessageFormat
: JsonFormat[sbt.internal.protocol.JsonRpcNotificationMessage] =
new JsonFormat[sbt.internal.protocol.JsonRpcNotificationMessage] {
override def read[J](
jsOpt: Option[J],
unbuilder: Unbuilder[J]): sbt.internal.protocol.JsonRpcNotificationMessage = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val jsonrpc = unbuilder.readField[String]("jsonrpc")
val method = unbuilder.readField[String]("method")
val params = unbuilder.lookupField("params") map {
case x: JValue => x
}
unbuilder.endObject()
sbt.internal.protocol.JsonRpcNotificationMessage(jsonrpc, method, params)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.protocol.JsonRpcNotificationMessage,
builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("jsonrpc", obj.jsonrpc)
builder.addField("method", obj.method)
builder.addField("params", obj.params)
builder.endObject()
}
}
}

View File

@ -0,0 +1,45 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
package sbt.internal.protocol.codec
import sjsonnew.shaded.scalajson.ast.unsafe.JValue
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
trait JsonRpcRequestMessageFormats {
self: sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val JsonRpcRequestMessageFormat
: JsonFormat[sbt.internal.protocol.JsonRpcRequestMessage] =
new JsonFormat[sbt.internal.protocol.JsonRpcRequestMessage] {
override def read[J](jsOpt: Option[J],
unbuilder: Unbuilder[J]): sbt.internal.protocol.JsonRpcRequestMessage = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val jsonrpc = unbuilder.readField[String]("jsonrpc")
val id = try {
unbuilder.readField[String]("id")
} catch {
case _ => unbuilder.readField[Long]("id").toString
}
val method = unbuilder.readField[String]("method")
val params = unbuilder.lookupField("params") map {
case x: JValue => x
}
unbuilder.endObject()
sbt.internal.protocol.JsonRpcRequestMessage(jsonrpc, id, method, params)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.protocol.JsonRpcRequestMessage,
builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("jsonrpc", obj.jsonrpc)
builder.addField("id", obj.id)
builder.addField("method", obj.method)
builder.addField("params", obj.params)
builder.endObject()
}
}
}

View File

@ -0,0 +1,39 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
package sbt.internal.protocol.codec
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
import sjsonnew.shaded.scalajson.ast.unsafe.JValue
trait JsonRpcResponseErrorFormats {
self: sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol =>
implicit lazy val JsonRpcResponseErrorFormat
: JsonFormat[sbt.internal.protocol.JsonRpcResponseError] =
new JsonFormat[sbt.internal.protocol.JsonRpcResponseError] {
override def read[J](jsOpt: Option[J],
unbuilder: Unbuilder[J]): sbt.internal.protocol.JsonRpcResponseError = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val code = unbuilder.readField[Long]("code")
val message = unbuilder.readField[String]("message")
val data = unbuilder.lookupField("data") map {
case x: JValue => x
}
unbuilder.endObject()
sbt.internal.protocol.JsonRpcResponseError(code, message, data)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.protocol.JsonRpcResponseError,
builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("code", obj.code)
builder.addField("message", obj.message)
builder.addField("data", obj.data)
builder.endObject()
}
}
}

View File

@ -0,0 +1,52 @@
/**
* This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]].
*/
package sbt.internal.protocol.codec
import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError }
import sjsonnew.shaded.scalajson.ast.unsafe.JValue
trait JsonRpcResponseMessageFormats {
self: sbt.internal.util.codec.JValueFormats
with sbt.internal.protocol.codec.JsonRpcResponseErrorFormats
with sjsonnew.BasicJsonProtocol =>
implicit lazy val JsonRpcResponseMessageFormat
: JsonFormat[sbt.internal.protocol.JsonRpcResponseMessage] =
new JsonFormat[sbt.internal.protocol.JsonRpcResponseMessage] {
override def read[J](
jsOpt: Option[J],
unbuilder: Unbuilder[J]): sbt.internal.protocol.JsonRpcResponseMessage = {
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val jsonrpc = unbuilder.readField[String]("jsonrpc")
val id = try {
unbuilder.readField[Option[String]]("id")
} catch {
case _ => unbuilder.readField[Option[Long]]("id") map { _.toString }
}
val result = unbuilder.lookupField("result") map {
case x: JValue => x
}
val error =
unbuilder.readField[Option[sbt.internal.protocol.JsonRpcResponseError]]("error")
unbuilder.endObject()
sbt.internal.protocol.JsonRpcResponseMessage(jsonrpc, id, result, error)
case None =>
deserializationError("Expected JsObject but found None")
}
}
override def write[J](obj: sbt.internal.protocol.JsonRpcResponseMessage,
builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("jsonrpc", obj.jsonrpc)
builder.addField("id", obj.id)
builder.addField("result", obj.result)
builder.addField("error", obj.error)
builder.endObject()
}
}
}

View File

@ -10,8 +10,15 @@ import sjsonnew.shaded.scalajson.ast.unsafe.{ JValue, JObject, JString }
import java.nio.ByteBuffer
import scala.util.{ Success, Failure }
import sbt.internal.util.StringEvent
import sbt.internal.protocol.{
JsonRpcRequestMessage,
JsonRpcResponseMessage,
JsonRpcNotificationMessage
}
object Serialization {
private[sbt] val VsCode = "application/vscode-jsonrpc; charset=utf-8"
def serializeEvent[A: JsonFormat](event: A): Array[Byte] = {
val json: JValue = Converter.toJson[A](event).get
CompactPrinter(json).getBytes("UTF-8")
@ -29,6 +36,39 @@ object Serialization {
CompactPrinter(json).getBytes("UTF-8")
}
/**
* This formats the message according to JSON-RPC.
* http://www.jsonrpc.org/specification
*/
private[sbt] def serializeResponseMessage(message: JsonRpcResponseMessage): Array[Byte] = {
import sbt.internal.protocol.codec.JsonRPCProtocol._
val json: JValue = Converter.toJson[JsonRpcResponseMessage](message).get
val body = CompactPrinter(json)
val bodyBytes = body.getBytes("UTF-8")
(s"Content-Length: ${bodyBytes.size}\r\n" +
s"Content-Type: $VsCode\r\n" +
"\r\n" +
body).getBytes("UTF-8")
}
/**
* This formats the message according to JSON-RPC.
* http://www.jsonrpc.org/specification
*/
private[sbt] def serializeNotificationMessage(
message: JsonRpcNotificationMessage): Array[Byte] = {
import sbt.internal.protocol.codec.JsonRPCProtocol._
val json: JValue = Converter.toJson[JsonRpcNotificationMessage](message).get
val body = CompactPrinter(json)
val bodyBytes = body.getBytes("UTF-8")
(s"Content-Length: ${bodyBytes.size}\r\n" +
s"Content-Type: $VsCode\r\n" +
"\r\n" +
body).getBytes("UTF-8")
}
/**
* @return A command or an invalid input description
*/
@ -98,4 +138,26 @@ object Serialization {
Left(s"Parse error: ${e.getMessage}")
}
}
private[sbt] def deserializeJsonRequest(
bytes: Seq[Byte]): Either[String, JsonRpcRequestMessage] = {
val buffer = ByteBuffer.wrap(bytes.toArray)
Parser.parseFromByteBuffer(buffer) match {
case Success(json) =>
import sbt.internal.protocol.codec.JsonRPCProtocol._
Converter.fromJson[JsonRpcRequestMessage](json) match {
case Success(msg) => Right(msg)
case Failure(e) => throw e
}
case Failure(e) =>
Left(s"Parse error: ${e.getMessage}")
}
}
private[sbt] def compactPrintJsonOpt(jsonOpt: Option[JValue]): String = {
jsonOpt match {
case Some(x) => CompactPrinter(x)
case _ => ""
}
}
}

View File

@ -11,19 +11,25 @@ object Client extends App {
val host = "127.0.0.1"
val delimiter: Byte = '\n'.toByte
println("hello")
Thread.sleep(1000)
lazy val connection = getConnection
lazy val out = connection.getOutputStream
lazy val in = connection.getInputStream
val connection = getConnection
val out = connection.getOutputStream
val in = connection.getInputStream
val t = getToken
val msg0 = s"""{ "type": "InitCommand", "token": "$t" }"""
out.write(s"""{ "type": "InitCommand", "token": "$getToken" }""".getBytes("utf-8"))
out.write(delimiter.toInt)
writeLine(s"Content-Length: ${ msg0.size + 2 }")
writeLine("Content-Type: application/sbt-x1")
writeLine("")
writeLine(msg0)
out.flush
out.write("""{ "type": "ExecCommand", "commandLine": "exit" }""".getBytes("utf-8"))
out.write(delimiter.toInt)
writeLine("Content-Length: 49")
writeLine("Content-Type: application/sbt-x1")
writeLine("")
// 12345678901234567890123456789012345678901234567890
writeLine("""{ "type": "ExecCommand", "commandLine": "exit" }""")
writeLine("")
out.flush
val baseDirectory = new File(args(0))
@ -81,4 +87,20 @@ object Client extends App {
Thread.sleep(1000)
getConnection
}
def writeLine(s: String): Unit = {
if (s != "") {
out.write(s.getBytes("UTF-8"))
}
writeEndLine
}
def writeEndLine(): Unit = {
val retByte: Byte = '\r'.toByte
val delimiter: Byte = '\n'.toByte
out.write(retByte.toInt)
out.write(delimiter.toInt)
out.flush
}
}

View File

@ -1,6 +1,6 @@
> show serverPort
> runClient
-> shell
$ sleep 1000
$ exists ok.txt

33
vscode-sbt-scala/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,33 @@
{
"version": "0.2.0",
// List of configurations. Add new configurations or edit existing ones.
"configurations": [
{
"name": "Launch Client",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceRoot}/client"
],
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/client/out/**/*.js"
]
// "preLaunchTask": "Client Watch"
},
{
"name": "Attach to Server",
"type": "node",
"request": "attach",
"port": 6009,
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/client/server/**/*.js"
],
"protocol": "legacy"
// "preLaunchTask": "Server Watch"
}
]
}

10
vscode-sbt-scala/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
"typescript.tsdk": "./node_modules/typescript/lib",
"typescript.tsc.autoDetect": "off"
}

79
vscode-sbt-scala/.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,79 @@
{
"version": "2.0.0",
"tasks": [
{
"taskName": "compile",
"dependsOn": [
"compile:client",
"compile:server"
],
"problemMatcher": []
},
{
"label": "compile:client",
"type": "npm",
"script": "compile:client",
"group": "build",
"presentation": {
"panel": "dedicated",
"reveal": "never"
},
"problemMatcher": [
"$tsc"
]
},
{
"label": "compile:server",
"type": "npm",
"script": "compile:server",
"group": "build",
"presentation": {
"panel": "dedicated",
"reveal": "never"
},
"problemMatcher": [
"$tsc"
]
},
{
"taskName": "watch",
"dependsOn": [
"watch:client",
"watch:server"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
},
{
"label": "watch:client",
"type": "npm",
"script": "watch:client",
"isBackground": true,
"group": "build",
"presentation": {
"panel": "dedicated",
"reveal": "never"
},
"problemMatcher": [
"$tsc-watch"
]
},
{
"label": "watch:server",
"type": "npm",
"script": "watch:server",
"isBackground": true,
"group": "build",
"presentation": {
"panel": "dedicated",
"reveal": "never"
},
"problemMatcher": [
"$tsc-watch"
]
}
]
}

View File

@ -0,0 +1,9 @@
.vscode/**
typings/**
out/test/**
test/**
src/**
**/*.map
.gitignore
tsconfig.json
vsc-extension-quickstart.md

View File

@ -0,0 +1,6 @@
Scala language support using sbt
================================
This is an experimental Scala language support using sbt as the language server.
To try this, use sbt 1.1.0-M1 and above. Saving `*.scala` will trigger `compile` task.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="257.333px" height="147.833px" viewBox="0 0 257.333 147.833" enable-background="new 0 0 257.333 147.833"
xml:space="preserve">
<g id="guidelines" display="none">
<line display="inline" fill="none" stroke="#FF2D00" x1="160.833" y1="21.833" x2="126.958" y2="159.208"/>
<line display="inline" fill="none" stroke="#FF2D00" x1="181.25" y1="28.875" x2="147.375" y2="166.25"/>
</g>
<g id="Layer_3">
<path fill="#380D09" d="M17.417,106.458l-13.25,12c0,0,6.5,8.125,15.125,13s13.381,4.508,23.065,4.379
c9.31,0,18.81-1.754,26.435-8.504s9.066-8.6,9.033-17.112c-0.016-3.994-1.075-12.813-5.908-18.513
c-5.466-6.445-14.781-9.566-14.781-9.566s-28.53-7.155-25.594-17.059c1.232-4.156,7.818-5.726,14.292-4.583
c8.192,1.444,16.474,6.371,16.474,6.371l11.577-11.33c0,0-5.274-6.198-13.468-10.208c-6.064-2.967-14.428-4.059-19.783-4.078
c-12.592-0.047-28.335,11.197-30.217,22.828c-1.375,8.5,1.383,15.676,7.625,21.125c7.875,6.875,13.478,7.771,13.478,7.771
s25.123,6.469,25.123,14.286s-6.101,10.692-15.851,10.817S17.417,106.458,17.417,106.458z"/>
<path fill="#380D09" d="M198.508,45.484l0.2,18.199h10.4l0.1,53.9c0,0,1.801,6.2,6.5,10.8c6.065,5.937,12.4,7.454,12.4,7.454
h20.399l0.101-18.554l-11-0.1c0,0-2.401,0.101-5.1-2.5c-2.801-2.7-2.7-6.2-2.7-6.2l0.2-44.9h20l0.1-18.2l-20-0.1l-0.2-35.2h-20.8
l0.2,35.4H198.508z"/>
<path fill="#380D09" d="M156.667,49.833c-12.529-2.767-25.25-1.375-33.375,3.375l10.625-43.125l-21.188-5.188L82.604,126.333
l21,6.062L106.5,120.5c6.167,11.666,13.194,17.279,26.667,20.333c25,5.667,47.312-11.762,53.334-38.667
C191.667,79.083,175.917,54.083,156.667,49.833z M162.756,117.094l-30.152,8.302l-22.49-22.776l7.666-31.077l30.155-8.302
l22.487,22.776L162.756,117.094z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

2256
vscode-sbt-scala/client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
{
"name": "vscode-sbt-scala",
"displayName": "Scala (sbt)",
"version": "0.0.1",
"author": "Lightbend, Inc.",
"license": "BSD-3-Clause",
"publisher": "lightbend",
"repository": {
"type": "git",
"url": "https://github.com/sbt/sbt"
},
"description": "Scala language support using sbt",
"icon": "images/sbt-logo-455x262.png",
"engines": {
"vscode": "^1.16.0"
},
"categories": [
"Languages"
],
"activationEvents": [
"workspaceContains:build.sbt"
],
"main": "./out/src/extension",
"scripts": {
"vscode:prepublish": "tsc -p ./",
"compile": "tsc -p ./",
"watch": "tsc -w -p ./",
"update-vscode": "node ./node_modules/vscode/bin/install",
"postinstall": "node ./node_modules/vscode/bin/install"
},
"dependencies": {
"vscode": "^1.1.5",
"vscode-languageclient": "^3.4.2"
}
}

View File

@ -0,0 +1,45 @@
'use strict';
import * as path from 'path';
let fs = require('fs');
import { ExtensionContext, workspace } from 'vscode'; // workspace,
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient';
export function activate(context: ExtensionContext) {
// The server is implemented in node
let serverModule = context.asAbsolutePath(path.join('server', 'server.js'));
// The debug options for the server
// let debugOptions = { execArgv: ["--nolazy", "--debug=6009"] };
// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
let serverOptions: ServerOptions = {
run : { module: serverModule, transport: TransportKind.stdio },
debug: { module: serverModule, transport: TransportKind.stdio }
}
// Options to control the language client
let clientOptions: LanguageClientOptions = {
documentSelector: [{ language: 'scala', scheme: 'file' }, { language: 'java', scheme: 'file' }],
initializationOptions: () => {
return {
token: discoverToken()
};
}
}
// the port file is hardcoded to a particular location relative to the build.
function discoverToken(): String {
let pf = path.join(workspace.rootPath, 'project', 'target', 'active.json');
let portfile = JSON.parse(fs.readFileSync(pf));
let tf = portfile.tokenfilePath;
let tokenfile = JSON.parse(fs.readFileSync(tf));
return tokenfile.token;
}
// Create the language client and start the client.
let disposable = new LanguageClient('lspSbtScala', 'sbt Scala Language Server', serverOptions, clientOptions).start();
context.subscriptions.push(disposable);
}

View File

@ -0,0 +1,19 @@
{
"compilerOptions": {
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"rootDir": ".",
"outDir": "out",
"lib": [ "es2016" ],
"sourceMap": true
},
"exclude": [
"node_modules",
"server"
]
}

26
vscode-sbt-scala/package-lock.json generated Normal file
View File

@ -0,0 +1,26 @@
{
"name": "vscode-sbt-scala",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@types/mocha": {
"version": "2.2.43",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.43.tgz",
"integrity": "sha512-xNlAmH+lRJdUMXClMTI9Y0pRqIojdxfm7DHsIxoB2iTzu3fnPmSMEN8SsSx0cdwV36d02PWCWaDUoZPDSln+xw==",
"dev": true
},
"@types/node": {
"version": "6.0.88",
"resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.88.tgz",
"integrity": "sha512-bYDPZTX0/s1aihdjLuAgogUAT5M+TpoWChEMea2p0yOcfn5bu3k6cJb9cp6nw268XeSNIGGr+4+/8V5K6BGzLQ==",
"dev": true
},
"typescript": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.5.2.tgz",
"integrity": "sha1-A4qV99m7tCCxvzW6MdTFwd0//jQ=",
"dev": true
}
}
}

View File

@ -0,0 +1,26 @@
{
"name": "vscode-sbt-scala",
"displayName": "Scala (sbt)",
"version": "0.0.1",
"author": "Lightbend, Inc.",
"license": "BSD-3-Clause",
"publisher": "lightbend",
"description": "Scala language support for Visual Studio Code using sbt",
"repository": {
"type": "git",
"url": "https://github.com/sbt/sbt"
},
"scripts": {
"postinstall": "cd server && npm install && cd ../client && npm install && cd ..",
"compile": "tsc -p client/tsconfig.json && cd server && npm run installServer && cd .. && tsc -p server/tsconfig.json",
"compile:client": "tsc -p client/tsconfig.json",
"watch:client": "tsc -w -p client/tsconfig.json",
"compile:server": "cd server && npm run installServer && cd .. && tsc -p server/tsconfig.json",
"watch:server": "cd server && npm run installServer && cd .. && tsc -w -p server/tsconfig.json"
},
"devDependencies": {
"@types/mocha": "^2.2.42",
"@types/node": "^6.0.88",
"typescript": "^2.5.2"
}
}

View File

@ -0,0 +1,41 @@
{
"name": "vscode-sbt-scala",
"version": "0.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"vscode-jsonrpc": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.4.0.tgz",
"integrity": "sha1-qpWsWDvzHYD3JdV8J8CfTCz+n6k="
},
"vscode-languageserver": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.4.2.tgz",
"integrity": "sha1-CMvlDuJpAdN91LXcUsJbkJNjwfE=",
"requires": {
"vscode-languageserver-protocol": "3.4.1",
"vscode-uri": "1.0.1"
}
},
"vscode-languageserver-protocol": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.4.1.tgz",
"integrity": "sha1-lrfIo+1opOvTCkB7BCenY3k1/h8=",
"requires": {
"vscode-jsonrpc": "3.4.0",
"vscode-languageserver-types": "3.4.0"
}
},
"vscode-languageserver-types": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.4.0.tgz",
"integrity": "sha1-UEOuR+5KwWrwe7PQylYSNeDA0vo="
},
"vscode-uri": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.1.tgz",
"integrity": "sha1-Eahr7+rDxKo+wIYjZRo8gabQu8g="
}
}
}

View File

@ -0,0 +1,24 @@
{
"name": "vscode-sbt-scala",
"displayName": "Scala (sbt)",
"version": "0.0.1",
"author": "Lightbend, Inc.",
"license": "BSD-3-Clause",
"publisher": "lightbend",
"description": "Relay server to sbt server.",
"repository": {
"type": "git",
"url": "https://github.com/sbt/sbt"
},
"engines": {
"node": "*"
},
"dependencies": {
"vscode-languageserver": "^3.4.2"
},
"scripts": {
"installServer": "installServerIntoExtension ../client ./package.json ./tsconfig.json",
"compile": "installServerIntoExtension ../client ./package.json ./tsconfig.json && tsc -p .",
"watch": "installServerIntoExtension ../client ./package.json ./tsconfig.json && tsc -w -p ."
}
}

View File

@ -0,0 +1,33 @@
'use strict';
import * as path from 'path';
import * as url from 'url';
let net = require('net'),
fs = require('fs'),
stdin = process.stdin,
stdout = process.stdout;
let u = discoverUrl();
let socket = net.Socket();
socket.on('data', (chunk: any) => {
// send it back to stdout
stdout.write(chunk);
}).on('end', () => {
stdin.pause();
});
socket.connect(u.port, '127.0.0.1');
stdin.resume();
stdin.on('data', (chunk: any) => {
socket.write(chunk);
}).on('end', () => {
socket.end();
});
// the port file is hardcoded to a particular location relative to the build.
function discoverUrl(): url.Url {
let pf = path.join(process.cwd(), 'project', 'target', 'active.json');
let portfile = JSON.parse(fs.readFileSync(pf));
return url.parse(portfile.uri);
}

View File

@ -0,0 +1,17 @@
{
"compilerOptions": {
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"lib" : [ "es2016" ],
"outDir": "../client/server"
},
"exclude": [
"node_modules"
]
}