From 1ccff0ca6d1fadc5b46da3378b56e3bf00bc5eec Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 23 Feb 2020 21:12:20 -0500 Subject: [PATCH] Add Scala Build Target --- .../internal/server/BuildServerProtocol.scala | 24 ++++++- .../sbt/internal/bsp/BuildTarget.scala | 25 ++++--- .../internal/bsp/InitializeBuildResult.scala | 23 +++++-- .../sbt/internal/bsp/SbtBuildTarget.scala | 65 +++++++++++++++++++ .../sbt/internal/bsp/ScalaBuildTarget.scala | 59 +++++++++++++++++ .../bsp/codec/BuildTargetFormats.scala | 6 +- .../codec/InitializeBuildResultFormats.scala | 6 +- .../sbt/internal/bsp/codec/JsonProtocol.scala | 3 + .../bsp/codec/SbtBuildTargetFormats.scala | 35 ++++++++++ .../bsp/codec/ScalaBuildTargetFormats.scala | 35 ++++++++++ protocol/src/main/contraband/bsp.contra | 57 ++++++++++++++-- .../sbt/internal/bsp/ScalaPlatform.scala | 16 +++++ 12 files changed, 328 insertions(+), 26 deletions(-) create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/SbtBuildTarget.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/ScalaBuildTarget.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/SbtBuildTargetFormats.scala create mode 100644 protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ScalaBuildTargetFormats.scala create mode 100644 protocol/src/main/scala/sbt/internal/bsp/ScalaPlatform.scala diff --git a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala index c6030fff3..03d7e99fa 100644 --- a/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala +++ b/main/src/main/scala/sbt/internal/server/BuildServerProtocol.scala @@ -16,6 +16,7 @@ import Configurations.{ Compile, Test } import sbt.SlashSyntax0._ import sbt.BuildSyntax._ import scala.collection.mutable +import sjsonnew.support.scalajson.unsafe.Converter object BuildServerProtocol { private[sbt] val idMap: mutable.Map[BuildTargetIdentifier, (ProjectRef, Configuration)] = @@ -96,7 +97,7 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel => val languageIds = Vector("scala") val sbtV = setting(Keys.sbtVersion) val response = - InitializeBuildResult("sbt", sbtV, bspVersion, BuildClientCapabilities(languageIds)) + InitializeBuildResult("sbt", sbtV, bspVersion, BuildClientCapabilities(languageIds), None) respondResult(response, execId) } @@ -110,6 +111,7 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel => } def buildTargets: WorkspaceBuildTargetsResult = { + import sbt.internal.bsp.codec.JsonProtocol._ val allProjectPairs = structure.allProjectPairs val ts = allProjectPairs flatMap { case (p, ref) => @@ -117,6 +119,13 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel => val internalCompileDeps = p.dependencies.flatMap(idForConfig(_, Compile)).toVector val compileId = toId(ref, Compile) idMap(compileId) = (ref, Compile) + val compileData = ScalaBuildTarget( + scalaOrganization = getSetting(ref / Compile / Keys.scalaOrganization).get, + scalaVersion = getSetting(ref / Compile / Keys.scalaVersion).get, + scalaBinaryVersion = getSetting(ref / Compile / Keys.scalaBinaryVersion).get, + platform = ScalaPlatform.JVM, + jars = Vector("scala-library") + ) val t0 = BuildTarget( compileId, displayName = Some(p.id), @@ -124,7 +133,8 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel => tags = Vector.empty, languageIds = Vector("scala"), dependencies = internalCompileDeps, - dataKind = None + dataKind = Some("scala"), + data = Some(Converter.toJsonUnsafe(compileData)), ) val testId = toId(ref, Test) idMap(testId) = (ref, Test) @@ -133,6 +143,13 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel => (p.dependencies ++ Seq(ResolvedClasspathDependency(ref, Some("test->compile")))) .flatMap(idForConfig(_, Test)) .toVector + val testData = ScalaBuildTarget( + scalaOrganization = getSetting(ref / Test / Keys.scalaOrganization).get, + scalaVersion = getSetting(ref / Test / Keys.scalaVersion).get, + scalaBinaryVersion = getSetting(ref / Test / Keys.scalaBinaryVersion).get, + platform = ScalaPlatform.JVM, + jars = Vector("scala-library") + ) val t1 = BuildTarget( testId, displayName = Some(p.id + " test"), @@ -140,7 +157,8 @@ trait BuildServerImpl { self: LanguageServerProtocol with NetworkChannel => tags = Vector.empty, languageIds = Vector("scala"), dependencies = internalTestDeps, - dataKind = None + dataKind = Some("scala"), + data = Some(Converter.toJsonUnsafe(testData)), ) Seq(t0, t1) } diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildTarget.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildTarget.scala index c728f85d0..6732350c6 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildTarget.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/BuildTarget.scala @@ -24,6 +24,8 @@ package sbt.internal.bsp * @param languageIds The set of languages that this target contains. The ID string for each language is defined in the LSP. * @param dataKind Kind of data to expect in the `data` field. If this field is not set, the kind of data is not specified. + * @param data Language-specific metadata about this target. + See ScalaBuildTarget as an example. */ final class BuildTarget private ( val id: sbt.internal.bsp.BuildTargetIdentifier, @@ -32,22 +34,23 @@ final class BuildTarget private ( val tags: Vector[String], val languageIds: Vector[String], val dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier], - val dataKind: Option[String]) extends Serializable { + val dataKind: Option[String], + val data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends Serializable { override def equals(o: Any): Boolean = o match { - case x: BuildTarget => (this.id == x.id) && (this.displayName == x.displayName) && (this.baseDirectory == x.baseDirectory) && (this.tags == x.tags) && (this.languageIds == x.languageIds) && (this.dependencies == x.dependencies) && (this.dataKind == x.dataKind) + case x: BuildTarget => (this.id == x.id) && (this.displayName == x.displayName) && (this.baseDirectory == x.baseDirectory) && (this.tags == x.tags) && (this.languageIds == x.languageIds) && (this.dependencies == x.dependencies) && (this.dataKind == x.dataKind) && (this.data == x.data) case _ => false } override def hashCode: Int = { - 37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildTarget".##) + id.##) + displayName.##) + baseDirectory.##) + tags.##) + languageIds.##) + dependencies.##) + dataKind.##) + 37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.BuildTarget".##) + id.##) + displayName.##) + baseDirectory.##) + tags.##) + languageIds.##) + dependencies.##) + dataKind.##) + data.##) } override def toString: String = { - "BuildTarget(" + id + ", " + displayName + ", " + baseDirectory + ", " + tags + ", " + languageIds + ", " + dependencies + ", " + dataKind + ")" + "BuildTarget(" + id + ", " + displayName + ", " + baseDirectory + ", " + tags + ", " + languageIds + ", " + dependencies + ", " + dataKind + ", " + data + ")" } - private[this] def copy(id: sbt.internal.bsp.BuildTargetIdentifier = id, displayName: Option[String] = displayName, baseDirectory: Option[java.net.URI] = baseDirectory, tags: Vector[String] = tags, languageIds: Vector[String] = languageIds, dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier] = dependencies, dataKind: Option[String] = dataKind): BuildTarget = { - new BuildTarget(id, displayName, baseDirectory, tags, languageIds, dependencies, dataKind) + private[this] def copy(id: sbt.internal.bsp.BuildTargetIdentifier = id, displayName: Option[String] = displayName, baseDirectory: Option[java.net.URI] = baseDirectory, tags: Vector[String] = tags, languageIds: Vector[String] = languageIds, dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier] = dependencies, dataKind: Option[String] = dataKind, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = data): BuildTarget = { + new BuildTarget(id, displayName, baseDirectory, tags, languageIds, dependencies, dataKind, data) } def withId(id: sbt.internal.bsp.BuildTargetIdentifier): BuildTarget = { copy(id = id) @@ -79,9 +82,15 @@ final class BuildTarget private ( def withDataKind(dataKind: String): BuildTarget = { copy(dataKind = Option(dataKind)) } + def withData(data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): BuildTarget = { + copy(data = data) + } + def withData(data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): BuildTarget = { + copy(data = Option(data)) + } } object BuildTarget { - def apply(id: sbt.internal.bsp.BuildTargetIdentifier, displayName: Option[String], baseDirectory: Option[java.net.URI], tags: Vector[String], languageIds: Vector[String], dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier], dataKind: Option[String]): BuildTarget = new BuildTarget(id, displayName, baseDirectory, tags, languageIds, dependencies, dataKind) - def apply(id: sbt.internal.bsp.BuildTargetIdentifier, displayName: String, baseDirectory: java.net.URI, tags: Vector[String], languageIds: Vector[String], dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier], dataKind: String): BuildTarget = new BuildTarget(id, Option(displayName), Option(baseDirectory), tags, languageIds, dependencies, Option(dataKind)) + def apply(id: sbt.internal.bsp.BuildTargetIdentifier, displayName: Option[String], baseDirectory: Option[java.net.URI], tags: Vector[String], languageIds: Vector[String], dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier], dataKind: Option[String], data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): BuildTarget = new BuildTarget(id, displayName, baseDirectory, tags, languageIds, dependencies, dataKind, data) + def apply(id: sbt.internal.bsp.BuildTargetIdentifier, displayName: String, baseDirectory: java.net.URI, tags: Vector[String], languageIds: Vector[String], dependencies: Vector[sbt.internal.bsp.BuildTargetIdentifier], dataKind: String, data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): BuildTarget = new BuildTarget(id, Option(displayName), Option(baseDirectory), tags, languageIds, dependencies, Option(dataKind), Option(data)) } diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/InitializeBuildResult.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/InitializeBuildResult.scala index 63e6e1a0d..7eb8c7e98 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/InitializeBuildResult.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/InitializeBuildResult.scala @@ -9,27 +9,29 @@ package sbt.internal.bsp * @param version The version of the server * @param bspVersion The BSP version that the server speaks * @param capabilities The capabilities of the build server + * @param data Additional metadata about the server */ final class InitializeBuildResult private ( val displayName: String, val version: String, val bspVersion: String, - val capabilities: sbt.internal.bsp.BuildClientCapabilities) extends Serializable { + val capabilities: sbt.internal.bsp.BuildClientCapabilities, + val data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]) extends Serializable { override def equals(o: Any): Boolean = o match { - case x: InitializeBuildResult => (this.displayName == x.displayName) && (this.version == x.version) && (this.bspVersion == x.bspVersion) && (this.capabilities == x.capabilities) + case x: InitializeBuildResult => (this.displayName == x.displayName) && (this.version == x.version) && (this.bspVersion == x.bspVersion) && (this.capabilities == x.capabilities) && (this.data == x.data) case _ => false } override def hashCode: Int = { - 37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.InitializeBuildResult".##) + displayName.##) + version.##) + bspVersion.##) + capabilities.##) + 37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.InitializeBuildResult".##) + displayName.##) + version.##) + bspVersion.##) + capabilities.##) + data.##) } override def toString: String = { - "InitializeBuildResult(" + displayName + ", " + version + ", " + bspVersion + ", " + capabilities + ")" + "InitializeBuildResult(" + displayName + ", " + version + ", " + bspVersion + ", " + capabilities + ", " + data + ")" } - private[this] def copy(displayName: String = displayName, version: String = version, bspVersion: String = bspVersion, capabilities: sbt.internal.bsp.BuildClientCapabilities = capabilities): InitializeBuildResult = { - new InitializeBuildResult(displayName, version, bspVersion, capabilities) + private[this] def copy(displayName: String = displayName, version: String = version, bspVersion: String = bspVersion, capabilities: sbt.internal.bsp.BuildClientCapabilities = capabilities, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue] = data): InitializeBuildResult = { + new InitializeBuildResult(displayName, version, bspVersion, capabilities, data) } def withDisplayName(displayName: String): InitializeBuildResult = { copy(displayName = displayName) @@ -43,8 +45,15 @@ final class InitializeBuildResult private ( def withCapabilities(capabilities: sbt.internal.bsp.BuildClientCapabilities): InitializeBuildResult = { copy(capabilities = capabilities) } + def withData(data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): InitializeBuildResult = { + copy(data = data) + } + def withData(data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): InitializeBuildResult = { + copy(data = Option(data)) + } } object InitializeBuildResult { - def apply(displayName: String, version: String, bspVersion: String, capabilities: sbt.internal.bsp.BuildClientCapabilities): InitializeBuildResult = new InitializeBuildResult(displayName, version, bspVersion, capabilities) + def apply(displayName: String, version: String, bspVersion: String, capabilities: sbt.internal.bsp.BuildClientCapabilities, data: Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]): InitializeBuildResult = new InitializeBuildResult(displayName, version, bspVersion, capabilities, data) + def apply(displayName: String, version: String, bspVersion: String, capabilities: sbt.internal.bsp.BuildClientCapabilities, data: sjsonnew.shaded.scalajson.ast.unsafe.JValue): InitializeBuildResult = new InitializeBuildResult(displayName, version, bspVersion, capabilities, Option(data)) } diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/SbtBuildTarget.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/SbtBuildTarget.scala new file mode 100644 index 000000000..d454280e7 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/SbtBuildTarget.scala @@ -0,0 +1,65 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** + * Contains sbt-specific metadata for providing editor support for sbt build files. + * This metadata is embedded in the data: Option[Json] field of the BuildTarget definition + * when the dataKind field contains "sbt". + * @param sbtVersion The sbt version. Useful to support version-dependent syntax. + * @param autoImports A sequence of Scala imports that are automatically imported in the sbt build files. + * @param scalaBuildTarget The Scala build target describing the scala + version and scala jars used by this sbt version. + * @param parent An optional parent if the target has an sbt meta project. + * @param children The inverse of parent, list of targets that have this build target + defined as their parent. It can contain normal project targets or + sbt build targets if this target represents an sbt meta-meta build. + */ +final class SbtBuildTarget private ( + val sbtVersion: String, + val autoImports: Vector[String], + val scalaBuildTarget: sbt.internal.bsp.ScalaBuildTarget, + val parent: Option[sbt.internal.bsp.BuildTargetIdentifier], + val children: Vector[sbt.internal.bsp.BuildTargetIdentifier]) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: SbtBuildTarget => (this.sbtVersion == x.sbtVersion) && (this.autoImports == x.autoImports) && (this.scalaBuildTarget == x.scalaBuildTarget) && (this.parent == x.parent) && (this.children == x.children) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.SbtBuildTarget".##) + sbtVersion.##) + autoImports.##) + scalaBuildTarget.##) + parent.##) + children.##) + } + override def toString: String = { + "SbtBuildTarget(" + sbtVersion + ", " + autoImports + ", " + scalaBuildTarget + ", " + parent + ", " + children + ")" + } + private[this] def copy(sbtVersion: String = sbtVersion, autoImports: Vector[String] = autoImports, scalaBuildTarget: sbt.internal.bsp.ScalaBuildTarget = scalaBuildTarget, parent: Option[sbt.internal.bsp.BuildTargetIdentifier] = parent, children: Vector[sbt.internal.bsp.BuildTargetIdentifier] = children): SbtBuildTarget = { + new SbtBuildTarget(sbtVersion, autoImports, scalaBuildTarget, parent, children) + } + def withSbtVersion(sbtVersion: String): SbtBuildTarget = { + copy(sbtVersion = sbtVersion) + } + def withAutoImports(autoImports: Vector[String]): SbtBuildTarget = { + copy(autoImports = autoImports) + } + def withScalaBuildTarget(scalaBuildTarget: sbt.internal.bsp.ScalaBuildTarget): SbtBuildTarget = { + copy(scalaBuildTarget = scalaBuildTarget) + } + def withParent(parent: Option[sbt.internal.bsp.BuildTargetIdentifier]): SbtBuildTarget = { + copy(parent = parent) + } + def withParent(parent: sbt.internal.bsp.BuildTargetIdentifier): SbtBuildTarget = { + copy(parent = Option(parent)) + } + def withChildren(children: Vector[sbt.internal.bsp.BuildTargetIdentifier]): SbtBuildTarget = { + copy(children = children) + } +} +object SbtBuildTarget { + + def apply(sbtVersion: String, autoImports: Vector[String], scalaBuildTarget: sbt.internal.bsp.ScalaBuildTarget, parent: Option[sbt.internal.bsp.BuildTargetIdentifier], children: Vector[sbt.internal.bsp.BuildTargetIdentifier]): SbtBuildTarget = new SbtBuildTarget(sbtVersion, autoImports, scalaBuildTarget, parent, children) + def apply(sbtVersion: String, autoImports: Vector[String], scalaBuildTarget: sbt.internal.bsp.ScalaBuildTarget, parent: sbt.internal.bsp.BuildTargetIdentifier, children: Vector[sbt.internal.bsp.BuildTargetIdentifier]): SbtBuildTarget = new SbtBuildTarget(sbtVersion, autoImports, scalaBuildTarget, Option(parent), children) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/ScalaBuildTarget.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/ScalaBuildTarget.scala new file mode 100644 index 000000000..14c486466 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/ScalaBuildTarget.scala @@ -0,0 +1,59 @@ +/** + * This code is generated using [[https://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt.internal.bsp +/** + * Contains scala-specific metadata for compiling a target containing Scala sources. + * This metadata is embedded in the data: Option[Json] field of the BuildTarget definition, + * when the dataKind field contains "scala". + * @param scalaOrganization The Scala organization that is used for a target. + * @param scalaVersion The scala version to compile this target + * @param scalaBinaryVersion The binary version of scalaVersion. + For example, 2.12 if scalaVersion is 2.12.4. + * @param platform The target platform for this target + * @param jars A sequence of Scala jars such as scala-library, scala-compiler and scala-reflect. + */ +final class ScalaBuildTarget private ( + val scalaOrganization: String, + val scalaVersion: String, + val scalaBinaryVersion: String, + val platform: Int, + val jars: Vector[String]) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: ScalaBuildTarget => (this.scalaOrganization == x.scalaOrganization) && (this.scalaVersion == x.scalaVersion) && (this.scalaBinaryVersion == x.scalaBinaryVersion) && (this.platform == x.platform) && (this.jars == x.jars) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (37 * (37 * (37 * (17 + "sbt.internal.bsp.ScalaBuildTarget".##) + scalaOrganization.##) + scalaVersion.##) + scalaBinaryVersion.##) + platform.##) + jars.##) + } + override def toString: String = { + "ScalaBuildTarget(" + scalaOrganization + ", " + scalaVersion + ", " + scalaBinaryVersion + ", " + platform + ", " + jars + ")" + } + private[this] def copy(scalaOrganization: String = scalaOrganization, scalaVersion: String = scalaVersion, scalaBinaryVersion: String = scalaBinaryVersion, platform: Int = platform, jars: Vector[String] = jars): ScalaBuildTarget = { + new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars) + } + def withScalaOrganization(scalaOrganization: String): ScalaBuildTarget = { + copy(scalaOrganization = scalaOrganization) + } + def withScalaVersion(scalaVersion: String): ScalaBuildTarget = { + copy(scalaVersion = scalaVersion) + } + def withScalaBinaryVersion(scalaBinaryVersion: String): ScalaBuildTarget = { + copy(scalaBinaryVersion = scalaBinaryVersion) + } + def withPlatform(platform: Int): ScalaBuildTarget = { + copy(platform = platform) + } + def withJars(jars: Vector[String]): ScalaBuildTarget = { + copy(jars = jars) + } +} +object ScalaBuildTarget { + + def apply(scalaOrganization: String, scalaVersion: String, scalaBinaryVersion: String, platform: Int, jars: Vector[String]): ScalaBuildTarget = new ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars) +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildTargetFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildTargetFormats.scala index 72306879a..58a6342a3 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildTargetFormats.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/BuildTargetFormats.scala @@ -5,7 +5,7 @@ // DO NOT EDIT MANUALLY package sbt.internal.bsp.codec import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } -trait BuildTargetFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sjsonnew.BasicJsonProtocol => +trait BuildTargetFormats { self: sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol => implicit lazy val BuildTargetFormat: JsonFormat[sbt.internal.bsp.BuildTarget] = new JsonFormat[sbt.internal.bsp.BuildTarget] { override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.BuildTarget = { __jsOpt match { @@ -18,8 +18,9 @@ implicit lazy val BuildTargetFormat: JsonFormat[sbt.internal.bsp.BuildTarget] = val languageIds = unbuilder.readField[Vector[String]]("languageIds") val dependencies = unbuilder.readField[Vector[sbt.internal.bsp.BuildTargetIdentifier]]("dependencies") val dataKind = unbuilder.readField[Option[String]]("dataKind") + val data = unbuilder.readField[Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]]("data") unbuilder.endObject() - sbt.internal.bsp.BuildTarget(id, displayName, baseDirectory, tags, languageIds, dependencies, dataKind) + sbt.internal.bsp.BuildTarget(id, displayName, baseDirectory, tags, languageIds, dependencies, dataKind, data) case None => deserializationError("Expected JsObject but found None") } @@ -33,6 +34,7 @@ implicit lazy val BuildTargetFormat: JsonFormat[sbt.internal.bsp.BuildTarget] = builder.addField("languageIds", obj.languageIds) builder.addField("dependencies", obj.dependencies) builder.addField("dataKind", obj.dataKind) + builder.addField("data", obj.data) builder.endObject() } } diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/InitializeBuildResultFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/InitializeBuildResultFormats.scala index d02958ba6..9ecb59118 100644 --- a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/InitializeBuildResultFormats.scala +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/InitializeBuildResultFormats.scala @@ -5,7 +5,7 @@ // DO NOT EDIT MANUALLY package sbt.internal.bsp.codec import _root_.sjsonnew.{ Unbuilder, Builder, JsonFormat, deserializationError } -trait InitializeBuildResultFormats { self: sbt.internal.bsp.codec.BuildClientCapabilitiesFormats with sjsonnew.BasicJsonProtocol => +trait InitializeBuildResultFormats { self: sbt.internal.bsp.codec.BuildClientCapabilitiesFormats with sbt.internal.util.codec.JValueFormats with sjsonnew.BasicJsonProtocol => implicit lazy val InitializeBuildResultFormat: JsonFormat[sbt.internal.bsp.InitializeBuildResult] = new JsonFormat[sbt.internal.bsp.InitializeBuildResult] { override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.InitializeBuildResult = { __jsOpt match { @@ -15,8 +15,9 @@ implicit lazy val InitializeBuildResultFormat: JsonFormat[sbt.internal.bsp.Initi val version = unbuilder.readField[String]("version") val bspVersion = unbuilder.readField[String]("bspVersion") val capabilities = unbuilder.readField[sbt.internal.bsp.BuildClientCapabilities]("capabilities") + val data = unbuilder.readField[Option[sjsonnew.shaded.scalajson.ast.unsafe.JValue]]("data") unbuilder.endObject() - sbt.internal.bsp.InitializeBuildResult(displayName, version, bspVersion, capabilities) + sbt.internal.bsp.InitializeBuildResult(displayName, version, bspVersion, capabilities, data) case None => deserializationError("Expected JsObject but found None") } @@ -27,6 +28,7 @@ implicit lazy val InitializeBuildResultFormat: JsonFormat[sbt.internal.bsp.Initi builder.addField("version", obj.version) builder.addField("bspVersion", obj.bspVersion) builder.addField("capabilities", obj.capabilities) + builder.addField("data", obj.data) 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 96247518f..ac039c0b8 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 @@ -6,6 +6,7 @@ package sbt.internal.bsp.codec trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.bsp.codec.BuildTargetIdentifierFormats + with sbt.internal.util.codec.JValueFormats with sbt.internal.bsp.codec.BuildTargetFormats with sbt.internal.bsp.codec.BuildClientCapabilitiesFormats with sbt.internal.bsp.codec.InitializeBuildParamsFormats @@ -15,4 +16,6 @@ trait JsonProtocol extends sjsonnew.BasicJsonProtocol with sbt.internal.bsp.codec.SourceItemFormats with sbt.internal.bsp.codec.SourcesItemFormats with sbt.internal.bsp.codec.SourcesResultFormats + with sbt.internal.bsp.codec.ScalaBuildTargetFormats + with sbt.internal.bsp.codec.SbtBuildTargetFormats object JsonProtocol extends JsonProtocol \ No newline at end of file diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/SbtBuildTargetFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/SbtBuildTargetFormats.scala new file mode 100644 index 000000000..788d26a98 --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/SbtBuildTargetFormats.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 SbtBuildTargetFormats { self: sbt.internal.bsp.codec.ScalaBuildTargetFormats with sbt.internal.bsp.codec.BuildTargetIdentifierFormats with sjsonnew.BasicJsonProtocol => +implicit lazy val SbtBuildTargetFormat: JsonFormat[sbt.internal.bsp.SbtBuildTarget] = new JsonFormat[sbt.internal.bsp.SbtBuildTarget] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.SbtBuildTarget = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val sbtVersion = unbuilder.readField[String]("sbtVersion") + val autoImports = unbuilder.readField[Vector[String]]("autoImports") + val scalaBuildTarget = unbuilder.readField[sbt.internal.bsp.ScalaBuildTarget]("scalaBuildTarget") + val parent = unbuilder.readField[Option[sbt.internal.bsp.BuildTargetIdentifier]]("parent") + val children = unbuilder.readField[Vector[sbt.internal.bsp.BuildTargetIdentifier]]("children") + unbuilder.endObject() + sbt.internal.bsp.SbtBuildTarget(sbtVersion, autoImports, scalaBuildTarget, parent, children) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.SbtBuildTarget, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("sbtVersion", obj.sbtVersion) + builder.addField("autoImports", obj.autoImports) + builder.addField("scalaBuildTarget", obj.scalaBuildTarget) + builder.addField("parent", obj.parent) + builder.addField("children", obj.children) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ScalaBuildTargetFormats.scala b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ScalaBuildTargetFormats.scala new file mode 100644 index 000000000..900994c4e --- /dev/null +++ b/protocol/src/main/contraband-scala/sbt/internal/bsp/codec/ScalaBuildTargetFormats.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 ScalaBuildTargetFormats { self: sjsonnew.BasicJsonProtocol => +implicit lazy val ScalaBuildTargetFormat: JsonFormat[sbt.internal.bsp.ScalaBuildTarget] = new JsonFormat[sbt.internal.bsp.ScalaBuildTarget] { + override def read[J](__jsOpt: Option[J], unbuilder: Unbuilder[J]): sbt.internal.bsp.ScalaBuildTarget = { + __jsOpt match { + case Some(__js) => + unbuilder.beginObject(__js) + val scalaOrganization = unbuilder.readField[String]("scalaOrganization") + val scalaVersion = unbuilder.readField[String]("scalaVersion") + val scalaBinaryVersion = unbuilder.readField[String]("scalaBinaryVersion") + val platform = unbuilder.readField[Int]("platform") + val jars = unbuilder.readField[Vector[String]]("jars") + unbuilder.endObject() + sbt.internal.bsp.ScalaBuildTarget(scalaOrganization, scalaVersion, scalaBinaryVersion, platform, jars) + case None => + deserializationError("Expected JsObject but found None") + } + } + override def write[J](obj: sbt.internal.bsp.ScalaBuildTarget, builder: Builder[J]): Unit = { + builder.beginObject() + builder.addField("scalaOrganization", obj.scalaOrganization) + builder.addField("scalaVersion", obj.scalaVersion) + builder.addField("scalaBinaryVersion", obj.scalaBinaryVersion) + builder.addField("platform", obj.platform) + builder.addField("jars", obj.jars) + builder.endObject() + } +} +} diff --git a/protocol/src/main/contraband/bsp.contra b/protocol/src/main/contraband/bsp.contra index ed9642087..944254683 100644 --- a/protocol/src/main/contraband/bsp.contra +++ b/protocol/src/main/contraband/bsp.contra @@ -41,8 +41,9 @@ type BuildTarget { ## Kind of data to expect in the `data` field. If this field is not set, the kind of data is not specified. dataKind: String - # Language-specific metadata about this target. - # data: any + ## Language-specific metadata about this target. + ## See ScalaBuildTarget as an example. + data: sjsonnew.shaded.scalajson.ast.unsafe.JValue } ## Build Target Identifier @@ -93,8 +94,8 @@ type InitializeBuildResult { ## The capabilities of the build server capabilities: sbt.internal.bsp.BuildClientCapabilities! - # Additional metadata about the server - # data: any + ## Additional metadata about the server + data: sjsonnew.shaded.scalajson.ast.unsafe.JValue } ## Workspace Build Targets response @@ -134,3 +135,51 @@ type SourceItem { ## intended to be manually edited by the user. generated: Boolean! } + +# Scala Extension + +## Contains scala-specific metadata for compiling a target containing Scala sources. +## This metadata is embedded in the data: Option[Json] field of the BuildTarget definition, +## when the dataKind field contains "scala". +type ScalaBuildTarget { + ## The Scala organization that is used for a target. + scalaOrganization: String! + + ## The scala version to compile this target + scalaVersion: String! + + ## The binary version of scalaVersion. + ## For example, 2.12 if scalaVersion is 2.12.4. + scalaBinaryVersion: String! + + ## The target platform for this target + platform: Int! + + ## A sequence of Scala jars such as scala-library, scala-compiler and scala-reflect. + jars: [String]! +} + +# sbt Extension + +## Contains sbt-specific metadata for providing editor support for sbt build files. +## This metadata is embedded in the data: Option[Json] field of the BuildTarget definition +## when the dataKind field contains "sbt". +type SbtBuildTarget { + ## The sbt version. Useful to support version-dependent syntax. + sbtVersion: String! + + ## A sequence of Scala imports that are automatically imported in the sbt build files. + autoImports: [String]! + + ## The Scala build target describing the scala + ## version and scala jars used by this sbt version. + scalaBuildTarget: sbt.internal.bsp.ScalaBuildTarget! + + ## An optional parent if the target has an sbt meta project. + parent: sbt.internal.bsp.BuildTargetIdentifier + + ## The inverse of parent, list of targets that have this build target + ## defined as their parent. It can contain normal project targets or + ## sbt build targets if this target represents an sbt meta-meta build. + children: [sbt.internal.bsp.BuildTargetIdentifier]! +} diff --git a/protocol/src/main/scala/sbt/internal/bsp/ScalaPlatform.scala b/protocol/src/main/scala/sbt/internal/bsp/ScalaPlatform.scala new file mode 100644 index 000000000..ea1efffb5 --- /dev/null +++ b/protocol/src/main/scala/sbt/internal/bsp/ScalaPlatform.scala @@ -0,0 +1,16 @@ +/* + * sbt + * Copyright 2011 - 2018, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under Apache License 2.0 (see LICENSE) + */ + +package sbt +package internal +package bsp + +object ScalaPlatform { + val JVM = 1 + val JS = 2 + val Native = 3 +}