From a415cd0cfc502861fa392171b41e4723fdb8e232 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Fri, 1 May 2020 13:41:13 +0200 Subject: [PATCH] replace LSP compiler reporter by BSP one --- build.sbt | 2 +- main/src/main/scala/sbt/Defaults.scala | 11 +-- ...porter.scala => BuildServerReporter.scala} | 66 ++++++++-------- .../sbt/internal/bsp/Diagnostic.scala | 69 +++++++++++++++++ .../sbt/internal/bsp/Position.scala | 42 ++++++++++ .../bsp/PublishDiagnosticsParams.scala | 63 +++++++++++++++ .../sbt/internal/bsp/Range.scala | 42 ++++++++++ .../internal/bsp/TextDocumentIdentifier.scala | 33 ++++++++ .../bsp/codec/DiagnosticFormats.scala | 35 +++++++++ .../sbt/internal/bsp/codec/JsonProtocol.scala | 5 ++ .../internal/bsp/codec/PositionFormats.scala | 29 +++++++ .../PublishDiagnosticsParamsFormats.scala | 35 +++++++++ .../sbt/internal/bsp/codec/RangeFormats.scala | 29 +++++++ .../codec/TextDocumentIdentifierFormats.scala | 27 +++++++ protocol/src/main/contraband/bsp.contra | 77 +++++++++++++++++-- .../sbt/internal/bsp/DiagnosticSeverity.scala | 31 ++++++++ 16 files changed, 553 insertions(+), 43 deletions(-) rename main/src/main/scala/sbt/internal/server/{LanguageServerReporter.scala => BuildServerReporter.scala} (76%) create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/Diagnostic.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/Position.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/PublishDiagnosticsParams.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/Range.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/TextDocumentIdentifier.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DiagnosticFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PositionFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PublishDiagnosticsParamsFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/RangeFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/TextDocumentIdentifierFormats.scala create mode 100644 protocol/src/main/scala/sbt/internal/bsp/DiagnosticSeverity.scala diff --git a/build.sbt b/build.sbt index 05b926cbe..d4a72f525 100644 --- a/build.sbt +++ b/build.sbt @@ -889,7 +889,7 @@ lazy val mainProj = (project in file("main")) exclude[IncompatibleSignatureProblem]("sbt.internal.Inspect.*"), exclude[IncompatibleSignatureProblem]("sbt.internal.ProjectIndex.*"), exclude[IncompatibleSignatureProblem]("sbt.internal.BuildIndex.*"), - exclude[IncompatibleSignatureProblem]("sbt.internal.server.LanguageServerReporter.*"), + exclude[IncompatibleSignatureProblem]("sbt.internal.server.BuildServerReporter.*"), exclude[VirtualStaticMemberProblem]("sbt.internal.server.LanguageServerProtocol.*"), exclude[IncompatibleSignatureProblem]("sbt.internal.librarymanagement.IvyXml.*"), exclude[IncompatibleSignatureProblem]("sbt.ScriptedPlugin.*Settings"), diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 4a0fc44fa..afb1bc3f4 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -44,9 +44,9 @@ import sbt.internal.librarymanagement.{ CustomHttp => _, _ } import sbt.internal.nio.{ CheckBuildSources, Globs } import sbt.internal.server.{ BuildServerProtocol, + BuildServerReporter, Definition, LanguageServerProtocol, - LanguageServerReporter, ServerHandler } import sbt.internal.testing.TestLogger @@ -1876,7 +1876,7 @@ object Defaults extends BuildCommon { val prev = i.previousResult prev.analysis.toOption map { analysis => i.setup.reporter match { - case r: LanguageServerReporter => + case r: BuildServerReporter => r.resetPrevious(analysis) case _ => () } @@ -1939,7 +1939,8 @@ object Defaults extends BuildCommon { ) }, compilerReporter := { - new LanguageServerReporter( + new BuildServerReporter( + buildTargetIdentifier.value, maxErrors.value, streams.value.log, foldMappers(sourcePositionMappers.value), @@ -2177,7 +2178,7 @@ object Classpaths { classpathConfiguration.?.value, update.value ) - ) + ) ++ BuildServerProtocol.configSettings private[this] def classpaths: Seq[Setting[_]] = Seq( externalDependencyClasspath := concat(unmanagedClasspath, managedClasspath).value, @@ -2222,7 +2223,7 @@ object Classpaths { val stamper = (managedSourcePaths / outputFileStamper).value dependencyClasspathFiles.value.flatMap(p => cache.getOrElseUpdate(p, stamper).map(p -> _)) } - ) ++ BuildServerProtocol.configSettings + ) private[this] def exportClasspath(s: Setting[Task[Classpath]]): Setting[Task[Classpath]] = s.mapInitialize(init => Def.task { exportClasspath(streams.value, init.value) }) diff --git a/main/src/main/scala/sbt/internal/server/LanguageServerReporter.scala b/main/src/main/scala/sbt/internal/server/BuildServerReporter.scala similarity index 76% rename from main/src/main/scala/sbt/internal/server/LanguageServerReporter.scala rename to main/src/main/scala/sbt/internal/server/BuildServerReporter.scala index 0394a0d2b..eb7bf23d4 100644 --- a/main/src/main/scala/sbt/internal/server/LanguageServerReporter.scala +++ b/main/src/main/scala/sbt/internal/server/BuildServerReporter.scala @@ -1,29 +1,15 @@ -/* - * sbt - * Copyright 2011 - 2018, Lightbend, Inc. - * Copyright 2008 - 2010, Mark Harrah - * Licensed under Apache License 2.0 (see LICENSE) - */ - -package sbt -package internal -package server +package sbt.internal.server import java.io.File + +import sbt.StandardMain +import sbt.internal.bsp._ import sbt.internal.inc.ManagedLoggedReporter import sbt.internal.util.ManagedLogger -import xsbti.{ FileConverter, Problem, Position => XPosition, Severity } import xsbti.compile.CompileAnalysis -import sbt.internal.langserver.{ - PublishDiagnosticsParams, - Position, - Diagnostic, - Range, - DiagnosticSeverity -} -import sbt.internal.inc.JavaInterfaceUtil._ +import xsbti.{ FileConverter, Problem, Severity, Position => XPosition } + import scala.collection.mutable -import scala.collection.JavaConverters._ /** * Defines a compiler reporter that uses event logging provided by a `ManagedLogger`. @@ -32,12 +18,18 @@ import scala.collection.JavaConverters._ * @param logger The event managed logger. * @param sourcePositionMapper The position mapper. */ -class LanguageServerReporter( +class BuildServerReporter( + buildTarget: BuildTargetIdentifier, maximumErrors: Int, logger: ManagedLogger, sourcePositionMapper: XPosition => XPosition = identity[XPosition], converter: FileConverter ) extends ManagedLoggedReporter(maximumErrors, logger, sourcePositionMapper) { + import sbt.internal.bsp.codec.JsonProtocol._ + import sbt.internal.inc.JavaInterfaceUtil._ + + import scala.collection.JavaConverters._ + lazy val exchange = StandardMain.exchange private[sbt] lazy val problemsByFile = new mutable.HashMap[File, mutable.ListBuffer[Problem]] @@ -80,24 +72,34 @@ class LanguageServerReporter( } private[sbt] def resetPrevious(analysis: CompileAnalysis): Unit = { - import sbt.internal.langserver.codec.JsonProtocol._ val files = analysis.readSourceInfos.getAllSourceInfos.keySet.asScala - files foreach { f => - val p = converter.toPath(f) - val params = PublishDiagnosticsParams(p.toUri.toString, Vector()) - exchange.notifyEvent("textDocument/publishDiagnostics", params) + files foreach { file => + val params = PublishDiagnosticsParams( + TextDocumentIdentifier(converter.toPath(file).toUri), + buildTarget, + None, + diagnostics = Vector(), + reset = true + ) + exchange.notifyEvent("build/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: mutable.ListBuffer[Problem]) => - val ds = toDiagnostics(xs) - val params = PublishDiagnosticsParams(sbt.io.IO.toURI(sourceFile).toString, ds) - exchange.notifyEvent("textDocument/publishDiagnostics", params) + val diagnostics = toDiagnostics(xs) + val params = PublishDiagnosticsParams( + TextDocumentIdentifier(sourceFile.toURI), + buildTarget, + originId = None, + diagnostics, + reset = true + ) + exchange.notifyEvent("build/publishDiagnostics", params) case _ => } } @@ -112,7 +114,7 @@ class LanguageServerReporter( } yield { val line = line0.toLong - 1L val pointer = pointer0.toLong - val r = ( + val range = ( pos.startLine.toOption, pos.startColumn.toOption, pos.endLine.toOption, @@ -124,7 +126,7 @@ class LanguageServerReporter( Range(Position(line, pointer), Position(line, pointer + 1)) } Diagnostic( - r, + range, Option(toDiagnosticSeverity(problem.severity)), None, Option("sbt"), diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/Diagnostic.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/Diagnostic.scala new file mode 100644 index 000000000..ed651c44e --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/Diagnostic.scala @@ -0,0 +1,69 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** + * Represents a diagnostic, such as a compiler error or warning. + * Diagnostic objects are only valid in the scope of a resource. + * @param range The range at which the message applies. + * @param severity The diagnostic's severity. Can be omitted. If omitted it is up to the + client to interpret diagnostics as error, warning, info or hint. + * @param code The diagnostic's code. Can be omitted. + * @param source A human-readable string describing the source of this + diagnostic, e.g. 'typescript' or 'super lint'. + * @param message The diagnostic's message. + */ +final class Diagnostic private ( + val range: sbt.internal.bsp.Range, + val severity: Option[Long], + val code: Option[String], + val source: Option[String], + 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.bsp.Diagnostic".##) + range.##) + severity.##) + code.##) + source.##) + message.##) + } + override def toString: String = { + "Diagnostic(" + range + ", " + severity + ", " + code + ", " + source + ", " + message + ")" + } + private[this] def copy(range: sbt.internal.bsp.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.bsp.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.bsp.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.bsp.Range, severity: Long, code: String, source: String, message: String): Diagnostic = new Diagnostic(range, Option(severity), Option(code), Option(source), message) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/Position.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/Position.scala new file mode 100644 index 000000000..a42cc1693 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/Position.scala @@ -0,0 +1,42 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** + * 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. + * @param line Line position in a document (zero-based). + * @param character Character offset on a line in a document (zero-based). + */ +final class Position private ( + val line: Long, + 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.bsp.Position".##) + line.##) + character.##) + } + override def toString: String = { + "Position(" + line + ", " + character + ")" + } + private[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) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/PublishDiagnosticsParams.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/PublishDiagnosticsParams.scala new file mode 100644 index 000000000..955f5d693 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/PublishDiagnosticsParams.scala @@ -0,0 +1,63 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** + * Publish Diagnostics + * @param textDocument The document where the diagnostics are published. + * @param buildTarget The build target where the diagnostics origin. + It is valid for one text to belong to multiple build targets, + for example sources that are compiled against multiple platforms (JVM, JavaScript). + * @param originId The request id that originated this notification + * @param diagnostics The diagnostics to be published by the client + * @param reset Whether the client should clear the previous diagnostics + mapped to the same `textDocument` and buildTarget + */ +final class PublishDiagnosticsParams private ( + val textDocument: sbt.internal.bsp.TextDocumentIdentifier, + val buildTarget: sbt.internal.bsp.BuildTargetIdentifier, + val originId: Option[String], + val diagnostics: Vector[sbt.internal.bsp.Diagnostic], + val reset: Boolean) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: PublishDiagnosticsParams => (this.textDocument == x.textDocument) && (this.buildTarget == x.buildTarget) && (this.originId == x.originId) && (this.diagnostics == x.diagnostics) && (this.reset == x.reset) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.PublishDiagnosticsParams".##) + textDocument.##) + buildTarget.##) + originId.##) + diagnostics.##) + reset.##) + } + override def toString: String = { + "PublishDiagnosticsParams(" + textDocument + ", " + buildTarget + ", " + originId + ", " + diagnostics + ", " + reset + ")" + } + private[this] def copy(textDocument: sbt.internal.bsp.TextDocumentIdentifier = textDocument, buildTarget: sbt.internal.bsp.BuildTargetIdentifier = buildTarget, originId: Option[String] = originId, diagnostics: Vector[sbt.internal.bsp.Diagnostic] = diagnostics, reset: Boolean = reset): PublishDiagnosticsParams = { + new PublishDiagnosticsParams(textDocument, buildTarget, originId, diagnostics, reset) + } + def withTextDocument(textDocument: sbt.internal.bsp.TextDocumentIdentifier): PublishDiagnosticsParams = { + copy(textDocument = textDocument) + } + def withBuildTarget(buildTarget: sbt.internal.bsp.BuildTargetIdentifier): PublishDiagnosticsParams = { + copy(buildTarget = buildTarget) + } + def withOriginId(originId: Option[String]): PublishDiagnosticsParams = { + copy(originId = originId) + } + def withOriginId(originId: String): PublishDiagnosticsParams = { + copy(originId = Option(originId)) + } + def withDiagnostics(diagnostics: Vector[sbt.internal.bsp.Diagnostic]): PublishDiagnosticsParams = { + copy(diagnostics = diagnostics) + } + def withReset(reset: Boolean): PublishDiagnosticsParams = { + copy(reset = reset) + } +} +object PublishDiagnosticsParams { + + def apply(textDocument: sbt.internal.bsp.TextDocumentIdentifier, buildTarget: sbt.internal.bsp.BuildTargetIdentifier, originId: Option[String], diagnostics: Vector[sbt.internal.bsp.Diagnostic], reset: Boolean): PublishDiagnosticsParams = new PublishDiagnosticsParams(textDocument, buildTarget, originId, diagnostics, reset) + def apply(textDocument: sbt.internal.bsp.TextDocumentIdentifier, buildTarget: sbt.internal.bsp.BuildTargetIdentifier, originId: String, diagnostics: Vector[sbt.internal.bsp.Diagnostic], reset: Boolean): PublishDiagnosticsParams = new PublishDiagnosticsParams(textDocument, buildTarget, Option(originId), diagnostics, reset) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/Range.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/Range.scala new file mode 100644 index 000000000..4b054c867 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/Range.scala @@ -0,0 +1,42 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** + * 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. + * @param start The range's start position. + * @param end The range's end position. + */ +final class Range private ( + val start: sbt.internal.bsp.Position, + val end: sbt.internal.bsp.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.bsp.Range".##) + start.##) + end.##) + } + override def toString: String = { + "Range(" + start + ", " + end + ")" + } + private[this] def copy(start: sbt.internal.bsp.Position = start, end: sbt.internal.bsp.Position = end): Range = { + new Range(start, end) + } + def withStart(start: sbt.internal.bsp.Position): Range = { + copy(start = start) + } + def withEnd(end: sbt.internal.bsp.Position): Range = { + copy(end = end) + } +} +object Range { + + def apply(start: sbt.internal.bsp.Position, end: sbt.internal.bsp.Position): Range = new Range(start, end) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/TextDocumentIdentifier.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/TextDocumentIdentifier.scala new file mode 100644 index 000000000..6435a0f67 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/TextDocumentIdentifier.scala @@ -0,0 +1,33 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** @param uri The file's Uri */ +final class TextDocumentIdentifier private ( + val uri: java.net.URI) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: TextDocumentIdentifier => (this.uri == x.uri) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (17 + "sbt.internal.bsp.TextDocumentIdentifier".##) + uri.##) + } + override def toString: String = { + "TextDocumentIdentifier(" + uri + ")" + } + private[this] def copy(uri: java.net.URI = uri): TextDocumentIdentifier = { + new TextDocumentIdentifier(uri) + } + def withUri(uri: java.net.URI): TextDocumentIdentifier = { + copy(uri = uri) + } +} +object TextDocumentIdentifier { + + def apply(uri: java.net.URI): TextDocumentIdentifier = new TextDocumentIdentifier(uri) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DiagnosticFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DiagnosticFormats.scala new file mode 100644 index 000000000..64a3a224b --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/DiagnosticFormats.scala @@ -0,0 +1,35 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait DiagnosticFormats { self: sbt.internal.bsp.codec.RangeFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val DiagnosticFormat: JsonFormat[sbt.internal.bsp.Diagnostic] = new JsonFormat[sbt.internal.bsp.Diagnostic] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.Diagnostic = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val range = unbuilder.readField[sbt.internal.bsp.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.bsp.Diagnostic(range, severity, code, source, message) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.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() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala index 6083f41b2..a25912842 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/JsonProtocol.scala @@ -9,9 +9,14 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.util.codec.JValueFormats with sbt.internal.bsp.codec.BuildTargetFormats with sbt.internal.bsp.codec.TaskIdFormats + with sbt.internal.bsp.codec.TextDocumentIdentifierFormats + with sbt.internal.bsp.codec.PositionFormats + with sbt.internal.bsp.codec.RangeFormats + with sbt.internal.bsp.codec.DiagnosticFormats with sbt.internal.bsp.codec.BuildClientCapabilitiesFormats with sbt.internal.bsp.codec.InitializeBuildParamsFormats with sbt.internal.bsp.codec.InitializeBuildResultFormats + with sbt.internal.bsp.codec.PublishDiagnosticsParamsFormats with sbt.internal.bsp.codec.WorkspaceBuildTargetsResultFormats with sbt.internal.bsp.codec.SourcesParamsFormats with sbt.internal.bsp.codec.SourceItemFormats diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PositionFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PositionFormats.scala new file mode 100644 index 000000000..1a8dcdd30 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PositionFormats.scala @@ -0,0 +1,29 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait PositionFormats { self: sjsonnew.BasicJsonProtocol => +implicit lazy val PositionFormat: JsonFormat[sbt.internal.bsp.Position] = new JsonFormat[sbt.internal.bsp.Position] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.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.bsp.Position(line, character) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.Position, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("line", obj.line) + builder.addField("character", obj.character) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PublishDiagnosticsParamsFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PublishDiagnosticsParamsFormats.scala new file mode 100644 index 000000000..0b5551c66 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/PublishDiagnosticsParamsFormats.scala @@ -0,0 +1,35 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait PublishDiagnosticsParamsFormats { self: sbt.internal.bsp.codec.TextDocumentIdentifierFormats with sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sbt.internal.bsp.codec.DiagnosticFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val PublishDiagnosticsParamsFormat: JsonFormat[sbt.internal.bsp.PublishDiagnosticsParams] = new JsonFormat[sbt.internal.bsp.PublishDiagnosticsParams] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.PublishDiagnosticsParams = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val textDocument = unbuilder.readField[sbt.internal.bsp.TextDocumentIdentifier]("textDocument") + val buildTarget = unbuilder.readField[sbt.internal.bsp.BuildTargetIdentifier]("buildTarget") + val originId = unbuilder.readField[Option[String]]("originId") + val diagnostics = unbuilder.readField[Vector[sbt.internal.bsp.Diagnostic]]("diagnostics") + val reset = unbuilder.readField[Boolean]("reset") + unbuilder.endObject() + sbt.internal.bsp.PublishDiagnosticsParams(textDocument, buildTarget, originId, diagnostics, reset) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.PublishDiagnosticsParams, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("textDocument", obj.textDocument) + builder.addField("buildTarget", obj.buildTarget) + builder.addField("originId", obj.originId) + builder.addField("diagnostics", obj.diagnostics) + builder.addField("reset", obj.reset) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/RangeFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/RangeFormats.scala new file mode 100644 index 000000000..1f50ef349 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/RangeFormats.scala @@ -0,0 +1,29 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait RangeFormats { self: sbt.internal.bsp.codec.PositionFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val RangeFormat: JsonFormat[sbt.internal.bsp.Range] = new JsonFormat[sbt.internal.bsp.Range] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.Range = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val start = unbuilder.readField[sbt.internal.bsp.Position]("start") + val end = unbuilder.readField[sbt.internal.bsp.Position]("end") + unbuilder.endObject() + sbt.internal.bsp.Range(start, end) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.Range, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("start", obj.start) + builder.addField("end", obj.end) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/TextDocumentIdentifierFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/TextDocumentIdentifierFormats.scala new file mode 100644 index 000000000..b61f50774 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/TextDocumentIdentifierFormats.scala @@ -0,0 +1,27 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp.codec +import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } +trait TextDocumentIdentifierFormats { self: sjsonnew.BasicJsonProtocol => +implicit lazy val TextDocumentIdentifierFormat: JsonFormat[sbt.internal.bsp.TextDocumentIdentifier] = new JsonFormat[sbt.internal.bsp.TextDocumentIdentifier] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.TextDocumentIdentifier = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val uri = unbuilder.readField[java.net.URI]("uri") + unbuilder.endObject() + sbt.internal.bsp.TextDocumentIdentifier(uri) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.TextDocumentIdentifier, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("uri", obj.uri) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband/bsp.contra b/protocol/src/main/contraband/bsp.contra index f8ad0de4f..4ca6eeac9 100644 --- a/protocol/src/main/contraband/bsp.contra +++ b/protocol/src/main/contraband/bsp.contra @@ -53,12 +53,58 @@ type BuildTargetIdentifier { } type TaskId { - ## A unique identifier - id: String! + ## A unique identifier + id: String! - ## The parent task ids, if any. A non-empty parents field means - ## this task is a sub-task of every parent task. - parents: [String] + ## The parent task ids, if any. A non-empty parents field means + ## this task is a sub-task of every parent task. + parents: [String] +} + +type TextDocumentIdentifier { + ## The file's Uri + uri: java.net.URI! +} + +## 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.bsp.Position! + + ## The range's end position. + end: sbt.internal.bsp.Position! +} + +## 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.bsp.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 Build Request @@ -107,6 +153,27 @@ type InitializeBuildResult { data: sjsonnew.shaded.scalajson.ast.unsafe.JValue } +## Publish Diagnostics +type PublishDiagnosticsParams { + ## The document where the diagnostics are published. + textDocument: sbt.internal.bsp.TextDocumentIdentifier! + + ## The build target where the diagnostics origin. + ## It is valid for one text to belong to multiple build targets, + ## for example sources that are compiled against multiple platforms (JVM, JavaScript). + buildTarget: sbt.internal.bsp.BuildTargetIdentifier! + + ## The request id that originated this notification + originId: String + + ## The diagnostics to be published by the client + diagnostics: [sbt.internal.bsp.Diagnostic] + + ## Whether the client should clear the previous diagnostics + ## mapped to the same `textDocument` and buildTarget + reset: Boolean! +} + ## Workspace Build Targets response type WorkspaceBuildTargetsResult { ## The build targets in this workspace that diff --git a/protocol/src/main/scala/sbt/internal/bsp/DiagnosticSeverity.scala b/protocol/src/main/scala/sbt/internal/bsp/DiagnosticSeverity.scala new file mode 100644 index 000000000..6f7797421 --- /dev/null +++ b/protocol/src/main/scala/sbt/internal/bsp/DiagnosticSeverity.scala @@ -0,0 +1,31 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt.internal.bsp + +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 +}