Skip to content

Commit 117359c

Browse files
committed
sbt-dotty: don't pollute classpath with dotty-doc dependencies
This lead to runtime errors when running `scalatestTestDotty/test` in scalatest, because scalatest depends on a different version of flexmark. I'm not sure why these jars leaked into the runtime classpath (might be an sbt bug) but it seems better to limit the compiler classpath to the minimum needed anyway, so we now only add the dotty-doc dependencies when running the `doc` task.
1 parent fd8d859 commit 117359c

File tree

2 files changed

+54
-39
lines changed

2 files changed

+54
-39
lines changed

project/Build.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,9 @@ object Build {
294294
dottyCompiler,
295295
allJars
296296
)
297-
}
297+
},
298+
// sbt-dotty defines `scalaInstance in doc` so we need to override it manually
299+
scalaInstance in doc := scalaInstance.value,
298300
)
299301

300302
lazy val commonBenchmarkSettings = Seq(

sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dotty.tools.sbtplugin
22

33
import sbt._
4+
import sbt.Def.Initialize
45
import sbt.Keys._
56
import sbt.librarymanagement.{
67
ivy, DependencyResolution, ScalaModuleInfo, SemanticSelector, UpdateConfiguration, UnresolvedWarningConfiguration,
@@ -172,12 +173,13 @@ object DottyPlugin extends AutoPlugin {
172173
scalaCompilerBridgeBinaryJar := Def.settingDyn {
173174
if (isDotty.value) Def.task {
174175
val dottyBridgeArtifacts = fetchArtifactsOf(
176+
scalaOrganization.value % "dotty-sbt-bridge" % scalaVersion.value,
175177
dependencyResolution.value,
176178
scalaModuleInfo.value,
177179
updateConfiguration.value,
178180
(unresolvedWarningConfiguration in update).value,
179181
streams.value.log,
180-
scalaOrganization.value % "dotty-sbt-bridge" % scalaVersion.value).allFiles
182+
).allFiles
181183
val jars = dottyBridgeArtifacts.filter(art => art.getName.startsWith("dotty-sbt-bridge") && art.getName.endsWith(".jar")).toArray
182184
if (jars.size == 0)
183185
throw new MessageOnlyException("No jar found for dotty-sbt-bridge")
@@ -288,39 +290,9 @@ object DottyPlugin extends AutoPlugin {
288290
old
289291
},
290292
// ... instead, we'll fetch the compiler and its dependencies ourselves.
291-
scalaInstance := Def.taskDyn {
292-
if (isDotty.value) Def.task {
293-
val updateReport =
294-
fetchArtifactsOf(
295-
dependencyResolution.value,
296-
scalaModuleInfo.value,
297-
updateConfiguration.value,
298-
(unresolvedWarningConfiguration in update).value,
299-
streams.value.log,
300-
scalaOrganization.value %% "dotty-doc" % scalaVersion.value)
301-
val scalaLibraryJar = getJar(updateReport,
302-
"org.scala-lang", "scala-library", revision = AllPassFilter)
303-
val dottyLibraryJar = getJar(updateReport,
304-
scalaOrganization.value, s"dotty-library_${scalaBinaryVersion.value}", scalaVersion.value)
305-
val compilerJar = getJar(updateReport,
306-
scalaOrganization.value, s"dotty-compiler_${scalaBinaryVersion.value}", scalaVersion.value)
307-
val allJars =
308-
getJars(updateReport, AllPassFilter, AllPassFilter, AllPassFilter)
309-
310-
makeScalaInstance(
311-
state.value,
312-
scalaVersion.value,
313-
scalaLibraryJar,
314-
dottyLibraryJar,
315-
compilerJar,
316-
allJars
317-
)
318-
}
319-
else
320-
// This dereferences the Initialize graph, but keeps the Task unevaluated,
321-
// so its effect gets fired only when isDotty.value evaluates to false. yay monad.
322-
Def.valueStrict { scalaInstance.taskValue }
323-
}.value,
293+
scalaInstance := scalaInstanceTask("dotty-compiler").value,
294+
// We need more stuff on the classpath to run the `doc` task.
295+
scalaInstance in doc := scalaInstanceTask("dotty-doc").value,
324296

325297
// Because managedScalaInstance is false, sbt won't add the standard library to our dependencies for us
326298
libraryDependencies ++= {
@@ -355,6 +327,7 @@ object DottyPlugin extends AutoPlugin {
355327
old
356328
}
357329
}.value,
330+
358331
scalacOptions ++= {
359332
if (isDotty.value) {
360333
val projectName =
@@ -369,17 +342,17 @@ object DottyPlugin extends AutoPlugin {
369342
}
370343
else
371344
Seq()
372-
}
345+
},
373346
))
374347

375348
/** Fetch artifacts for moduleID */
376349
def fetchArtifactsOf(
350+
moduleID: ModuleID,
377351
dependencyRes: DependencyResolution,
378352
scalaInfo: Option[ScalaModuleInfo],
379353
updateConfig: UpdateConfiguration,
380354
warningConfig: UnresolvedWarningConfiguration,
381-
log: Logger,
382-
moduleID: ModuleID): UpdateReport = {
355+
log: Logger): UpdateReport = {
383356
val descriptor = dependencyRes.wrapDependencyInModule(moduleID, scalaInfo)
384357

385358
dependencyRes.update(descriptor, updateConfig, warningConfig, log) match {
@@ -401,13 +374,53 @@ object DottyPlugin extends AutoPlugin {
401374
}
402375

403376
/** Get the single jar in updateReport that match the given filter.
404-
* If zero or more than one jar match, an exception will be thrown. */
377+
* If zero or more than one jar match, an exception will be thrown.
378+
*/
405379
def getJar(updateReport: UpdateReport, organization: NameFilter, name: NameFilter, revision: NameFilter): File = {
406380
val jars = getJars(updateReport, organization, name, revision)
407381
assert(jars.size == 1, s"There should only be one $name jar but found: $jars")
408382
jars.head
409383
}
410384

385+
/** If `isDotty` is true, create a scalaInstance task that uses Dotty based on
386+
* `moduleName`, otherwise return the default scalaInstance.
387+
*/
388+
def scalaInstanceTask(moduleName: String): Initialize[Task[ScalaInstance]] = Def.taskDyn {
389+
if (isDotty.value)
390+
dottyScalaInstanceTask(scalaOrganization.value %% moduleName % scalaVersion.value)
391+
else
392+
Def.valueStrict { scalaInstance.taskValue }
393+
}
394+
395+
/** Create a scalaInstance task that uses Dotty based on `moduleID`. */
396+
def dottyScalaInstanceTask(moduleID: ModuleID): Initialize[Task[ScalaInstance]] = Def.task {
397+
val updateReport =
398+
fetchArtifactsOf(
399+
moduleID,
400+
dependencyResolution.value,
401+
scalaModuleInfo.value,
402+
updateConfiguration.value,
403+
(unresolvedWarningConfiguration in update).value,
404+
streams.value.log)
405+
val scalaLibraryJar = getJar(updateReport,
406+
"org.scala-lang", "scala-library", revision = AllPassFilter)
407+
val dottyLibraryJar = getJar(updateReport,
408+
scalaOrganization.value, s"dotty-library_${scalaBinaryVersion.value}", scalaVersion.value)
409+
val compilerJar = getJar(updateReport,
410+
scalaOrganization.value, s"dotty-compiler_${scalaBinaryVersion.value}", scalaVersion.value)
411+
val allJars =
412+
getJars(updateReport, AllPassFilter, AllPassFilter, AllPassFilter)
413+
414+
makeScalaInstance(
415+
state.value,
416+
scalaVersion.value,
417+
scalaLibraryJar,
418+
dottyLibraryJar,
419+
compilerJar,
420+
allJars
421+
)
422+
}
423+
411424
def makeScalaInstance(
412425
state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File]
413426
): ScalaInstance = {

0 commit comments

Comments
 (0)