Skip to content

Commit

Permalink
Add BSP support
Browse files Browse the repository at this point in the history
  • Loading branch information
alexarchambault committed Jul 8, 2021
1 parent 46830ae commit 4297b07
Show file tree
Hide file tree
Showing 43 changed files with 2,584 additions and 268 deletions.
25 changes: 24 additions & 1 deletion build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Build(val crossScalaVersion: String) extends CrossSbtModule with ScalaCliP
Deps.guava, // for coursierJvm / scalaJsEnvNodeJs, see above
Deps.nativeTools,
Deps.osLib,
Deps.pprint,
Deps.pureconfig,
Deps.scalaJsLinkerInterface,
Deps.scalametaTrees,
Expand Down Expand Up @@ -152,6 +153,11 @@ trait Cli extends SbtModule with CliLaunchers with ScalaCliPublishModule with Fo
def localRepoJar = `local-repo`.localRepoJar()
def graalVmVersion = deps.graalVmVersion

// lsp4j, pulled by metabrowse, brings a class that conflicts with one
// defined in bloop, and sometimes creates issues when running
// native-image
def stripLsp4jPreconditionsFromBsp4j = true

object test extends Tests
}

Expand Down Expand Up @@ -194,8 +200,10 @@ trait CliIntegrationBase extends SbtModule with ScalaCliPublishModule with HasTe
private def mainArtifactName = T{ artifactName() }
trait Tests extends super.Tests {
def ivyDeps = super.ivyDeps() ++ Agg(
Deps.bsp4j,
Deps.osLib,
Deps.pprint
Deps.pprint,
Deps.scalaAsync
)
def forkEnv = super.forkEnv() ++ Seq(
"SCALA_CLI" -> testLauncher().path.toString,
Expand All @@ -207,6 +215,21 @@ trait CliIntegrationBase extends SbtModule with ScalaCliPublishModule with HasTe
PathRef(os.Path(ref.path.toString.replace(File.separator + name + File.separator, File.separator)))
}
}

def constantsFile = T{
val dest = T.dest / "Constants.scala"
val code =
s"""package scala.cli.integration
|
|/** Build-time constants. Generated by mill. */
|object Constants {
| def bspVersion = "${Deps.bsp4j.dep.version}"
|}
|""".stripMargin
os.write(dest, code)
PathRef(dest)
}
def generatedSources = super.generatedSources() ++ Seq(constantsFile())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,14 @@ object BloopServer {
create(System.currentTimeMillis() + timeout.toMillis)
}

def buildServer(
def bsp(
config: BloopRifleConfig,
clientName: String,
clientVersion: String,
workspace: Path,
classesDir: Path,
buildClient: bsp4j.BuildClient,
threads: BloopThreads,
logger: BloopRifleLogger,
period: FiniteDuration = 100.milliseconds,
timeout: FiniteDuration = 5.seconds,
initTimeout: FiniteDuration = 10.seconds
): BloopServer = {
timeout: FiniteDuration = 5.seconds
): (BspConnection, Socket) = {

ensureBloopRunning(config, threads.startServerChecks, logger)

Expand All @@ -126,6 +121,27 @@ object BloopServer {

logger.debug(s"Connected to Bloop via BSP at ${conn.address}")

(conn, socket)
}

def buildServer(
config: BloopRifleConfig,
clientName: String,
clientVersion: String,
workspace: Path,
classesDir: Path,
buildClient: bsp4j.BuildClient,
threads: BloopThreads,
logger: BloopRifleLogger,
period: FiniteDuration = 100.milliseconds,
timeout: FiniteDuration = 5.seconds,
initTimeout: FiniteDuration = 10.seconds
): BloopServer = {

val (conn, socket) = bsp(config, workspace, threads, logger, period, timeout)

logger.debug(s"Connected to Bloop via BSP at ${conn.address}")

// FIXME As of now, we don't detect when connection gets closed.
// For TCP connections, this should be do-able with heartbeat messages
// (to be added to BSP?).
Expand Down
36 changes: 36 additions & 0 deletions modules/build/src/main/scala/pprint/better.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package pprint

object better {

def log[T](x: sourcecode.Text[T],
tag: String = "",
width: Int = defaultWidth,
height: Int = defaultHeight,
indent: Int = defaultIndent,
initialOffset: Int = 0)
(implicit line: sourcecode.Line,
fileName: sourcecode.FileName): T = {

def joinSeq[T](seq: Seq[T], sep: T): Seq[T] = {
seq.flatMap(x => Seq(x, sep)).dropRight(1)
}

val tagStrs =
if (tag.isEmpty) Seq()
else Seq(fansi.Color.Cyan(tag), fansi.Str(" "))

val prefix = Seq(
fansi.Color.Magenta(fileName.value),
fansi.Str(":"),
fansi.Color.Green(line.value.toString),
fansi.Str(" "),
fansi.Color.Cyan(x.source),
fansi.Str(": ")
) ++ tagStrs
val str = fansi.Str.join(prefix ++ tokenize(x.value, width, height, indent).toSeq:_*)

System.err.println(str)
x.value
}

}
74 changes: 58 additions & 16 deletions modules/build/src/main/scala/scala/build/Artifacts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package scala.build

import coursier.cache.FileCache
import coursier.cache.loggers.RefreshLogger
import coursier.core.Classifier
import coursier.Fetch
import coursier.parse.RepositoryParser
import _root_.dependency._
import scala.build.internal.Constants
Expand All @@ -17,11 +19,26 @@ final case class Artifacts(
compilerArtifacts: Seq[(String, Path)],
compilerPlugins: Seq[(AnyDependency, String, Path)],
dependencies: Seq[AnyDependency],
artifacts: Seq[(String, Path)],
sourceArtifacts: Seq[(String, Path)],
detailedArtifacts: Seq[(coursier.Dependency, coursier.core.Publication, coursier.util.Artifact, Path)],
extraJars: Seq[Path],
params: ScalaParameters
) {
lazy val artifacts: Seq[(String, Path)] =
detailedArtifacts
.iterator
.collect {
case (dep, pub, a, f) if pub.classifier != Classifier.sources =>
(a.url, f)
}
.toVector
lazy val sourceArtifacts: Seq[(String, Path)] =
detailedArtifacts
.iterator
.collect {
case (dep, pub, a, f) if pub.classifier == Classifier.sources =>
(a.url, f)
}
.toVector
lazy val compilerClassPath: Seq[Path] =
compilerArtifacts.map(_._2)
lazy val classPath: Seq[Path] =
Expand Down Expand Up @@ -87,11 +104,24 @@ object Artifacts {
jmhDependencies

val compilerArtifacts = artifacts(compilerDependencies, allExtraRepositories, params, logger)
val artifacts0 = artifacts(updatedDependencies, allExtraRepositories, params, logger)

val fetchRes = fetch(
updatedDependencies,
allExtraRepositories,
params,
logger,
classifiersOpt = Some(Set("_") ++ (if (fetchSources) Set("sources") else Set.empty))
)
val artifacts0 = {
val a = fetchRes.fullExtraArtifacts.iterator.collect { case (a, Some(f)) => (None, a.url, f.toPath) }.toVector ++
fetchRes.fullDetailedArtifacts.iterator.collect { case (dep, pub, a, Some(f)) if pub.classifier != Classifier.sources => (Some(dep.moduleVersion), a.url, f.toPath) }.toVector
a.distinct
}
val sourceArtifacts =
if (fetchSources) artifacts(updatedDependencies, allExtraRepositories, params, logger, classifiersOpt = Some(Set("sources")))
else Nil
if (fetchSources) {
val a = fetchRes.fullDetailedArtifacts.iterator.collect { case (dep, pub, a, Some(f)) if pub.classifier == Classifier.sources => (a.url, f.toPath) }.toVector
a.distinct
} else Nil

val extraStubsJars =
if (addStubs)
Expand All @@ -115,8 +145,7 @@ object Artifacts {
compilerArtifacts,
compilerPlugins0,
updatedDependencies,
artifacts0,
sourceArtifacts,
fetchRes.fullDetailedArtifacts.collect { case (d, p, a, Some(f)) => (d, p, a, f.toPath) },
extraJars ++ extraStubsJars,
params
)
Expand All @@ -129,6 +158,22 @@ object Artifacts {
logger: Logger,
classifiersOpt: Option[Set[String]] = None
): Seq[(String, Path)] = {
val result = fetch(dependencies, extraRepositories, params, logger, classifiersOpt)
.artifacts
.iterator
.map { case (a, f) => (a.url, f.toPath) }
.toList
logger.debug((Seq(s"Found ${result.length} artifacts:") ++ result.map(" " + _._2) ++ Seq("")).mkString(System.lineSeparator()))
result
}

private[build] def fetch(
dependencies: Seq[AnyDependency],
extraRepositories: Seq[String],
params: ScalaParameters,
logger: Logger,
classifiersOpt: Option[Set[String]]
): Fetch.Result = {
logger.debug(s"Fetching $dependencies" + (if (extraRepositories.isEmpty) "" else s", adding $extraRepositories"))

val extraRepositories0 = RepositoryParser.repositories(extraRepositories).either match {
Expand All @@ -143,16 +188,13 @@ object Artifacts {
.withCache(cache)
.addRepositories(extraRepositories0: _*)
.addDependencies(dependencies.map(_.toCs(params)): _*)
for (classifiers <- classifiersOpt)
fetcher = fetcher.addClassifiers(classifiers.toSeq.map(coursier.Classifier(_)): _*)
for (classifiers <- classifiersOpt) {
if (classifiers("_"))
fetcher = fetcher.withMainArtifacts()
fetcher = fetcher.addClassifiers(classifiers.toSeq.filter(_ != "_").map(coursier.Classifier(_)): _*)
}

val result = fetcher.runResult()
.artifacts
.iterator
.map { case (a, f) => (a.url, f.toPath) }
.toList
logger.debug((Seq(s"Found ${result.length} artifacts:") ++ result.map(" " + _._2) ++ Seq("")).mkString(System.lineSeparator()))
result
fetcher.runResult()
}

}
Loading

0 comments on commit 4297b07

Please sign in to comment.