Skip to content

Commit 98150ce

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 7dec935 commit 98150ce

File tree

1 file changed

+76
-28
lines changed

1 file changed

+76
-28
lines changed

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

Lines changed: 76 additions & 28 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")
@@ -289,33 +291,18 @@ object DottyPlugin extends AutoPlugin {
289291
},
290292
// ... instead, we'll fetch the compiler and its dependencies ourselves.
291293
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(
294+
if (isDotty.value)
295+
dottyScalaInstanceTask(
296+
scalaOrganization.value %% "dotty-compiler" % scalaVersion.value,
297+
dependencyResolution.value,
298+
scalaModuleInfo.value,
299+
updateConfiguration.value,
300+
(unresolvedWarningConfiguration in update).value,
301+
streams.value.log,
311302
state.value,
312303
scalaVersion.value,
313-
scalaLibraryJar,
314-
dottyLibraryJar,
315-
compilerJar,
316-
allJars
304+
scalaBinaryVersion.value
317305
)
318-
}
319306
else
320307
// This dereferences the Initialize graph, but keeps the Task unevaluated,
321308
// so its effect gets fired only when isDotty.value evaluates to false. yay monad.
@@ -344,6 +331,26 @@ object DottyPlugin extends AutoPlugin {
344331
}
345332

346333
private val docSettings = inTask(doc)(Seq(
334+
// Copy-paste of scalaInstance in `projectSettings`, but with "dotty-compiler"
335+
// replaced by "dotty-doc" because we need more stuff on the classpath to
336+
// run the `doc` task. I can't find a way to avoid the code duplication here.
337+
scalaInstance := Def.taskDyn {
338+
if (isDotty.value)
339+
dottyScalaInstanceTask(
340+
scalaOrganization.value %% "dotty-doc" % scalaVersion.value,
341+
dependencyResolution.value,
342+
scalaModuleInfo.value,
343+
updateConfiguration.value,
344+
(unresolvedWarningConfiguration in update).value,
345+
streams.value.log,
346+
state.value,
347+
scalaVersion.value,
348+
scalaBinaryVersion.value
349+
)
350+
else
351+
Def.valueStrict { scalaInstance.taskValue }
352+
}.value,
353+
347354
sources := Def.taskDyn {
348355
val old = sources.value
349356

@@ -355,6 +362,7 @@ object DottyPlugin extends AutoPlugin {
355362
old
356363
}
357364
}.value,
365+
358366
scalacOptions ++= {
359367
if (isDotty.value) {
360368
val projectName =
@@ -369,17 +377,17 @@ object DottyPlugin extends AutoPlugin {
369377
}
370378
else
371379
Seq()
372-
}
380+
},
373381
))
374382

375383
/** Fetch artifacts for moduleID */
376384
def fetchArtifactsOf(
385+
moduleID: ModuleID,
377386
dependencyRes: DependencyResolution,
378387
scalaInfo: Option[ScalaModuleInfo],
379388
updateConfig: UpdateConfiguration,
380389
warningConfig: UnresolvedWarningConfiguration,
381-
log: Logger,
382-
moduleID: ModuleID): UpdateReport = {
390+
log: Logger): UpdateReport = {
383391
val descriptor = dependencyRes.wrapDependencyInModule(moduleID, scalaInfo)
384392

385393
dependencyRes.update(descriptor, updateConfig, warningConfig, log) match {
@@ -408,6 +416,46 @@ object DottyPlugin extends AutoPlugin {
408416
jars.head
409417
}
410418

419+
/** Create a scalaInstance task that uses Dotty based on the artifacts found in `moduleID` */
420+
def dottyScalaInstanceTask(
421+
moduleID: ModuleID,
422+
dependencyRes: DependencyResolution,
423+
scalaInfo: Option[ScalaModuleInfo],
424+
updateConfig: UpdateConfiguration,
425+
warningConfig: UnresolvedWarningConfiguration,
426+
log: Logger,
427+
state: State,
428+
scalaVersion: String,
429+
scalaBinaryVersion: String
430+
): Initialize[Task[ScalaInstance]] = Def.task {
431+
val updateReport =
432+
fetchArtifactsOf(
433+
moduleID,
434+
dependencyRes,
435+
scalaInfo,
436+
updateConfig,
437+
warningConfig,
438+
log,
439+
)
440+
val scalaLibraryJar = getJar(updateReport,
441+
"org.scala-lang", "scala-library", revision = AllPassFilter)
442+
val dottyLibraryJar = getJar(updateReport,
443+
scalaOrganization.value, s"dotty-library_${scalaBinaryVersion}", scalaVersion)
444+
val compilerJar = getJar(updateReport,
445+
scalaOrganization.value, s"dotty-compiler_${scalaBinaryVersion}", scalaVersion)
446+
val allJars =
447+
getJars(updateReport, AllPassFilter, AllPassFilter, AllPassFilter)
448+
449+
makeScalaInstance(
450+
state,
451+
scalaVersion,
452+
scalaLibraryJar,
453+
dottyLibraryJar,
454+
compilerJar,
455+
allJars
456+
)
457+
}
458+
411459
def makeScalaInstance(
412460
state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File]
413461
): ScalaInstance = {

0 commit comments

Comments
 (0)