Skip to content

Commit 28a64a8

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 3362726 commit 28a64a8

File tree

2 files changed

+51
-35
lines changed

2 files changed

+51
-35
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: 48 additions & 34 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,39 +291,20 @@ 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(
311-
state.value,
312-
scalaVersion.value,
313-
scalaLibraryJar,
314-
dottyLibraryJar,
315-
compilerJar,
316-
allJars
317-
)
318-
}
294+
if (isDotty.value)
295+
dottyScalaInstanceTask("dotty-compiler")
319296
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.
322297
Def.valueStrict { scalaInstance.taskValue }
323298
}.value,
324299

300+
// We need more stuff on the classpath to run the `doc` task.
301+
scalaInstance in doc := Def.taskDyn {
302+
if (isDotty.value)
303+
dottyScalaInstanceTask("dotty-doc")
304+
else
305+
Def.valueStrict { (scalaInstance in doc).taskValue }
306+
}.value,
307+
325308
// Because managedScalaInstance is false, sbt won't add the standard library to our dependencies for us
326309
libraryDependencies ++= {
327310
if (isDotty.value && autoScalaLibrary.value)
@@ -355,6 +338,7 @@ object DottyPlugin extends AutoPlugin {
355338
old
356339
}
357340
}.value,
341+
358342
scalacOptions ++= {
359343
if (isDotty.value) {
360344
val projectName =
@@ -369,17 +353,17 @@ object DottyPlugin extends AutoPlugin {
369353
}
370354
else
371355
Seq()
372-
}
356+
},
373357
))
374358

375359
/** Fetch artifacts for moduleID */
376360
def fetchArtifactsOf(
361+
moduleID: ModuleID,
377362
dependencyRes: DependencyResolution,
378363
scalaInfo: Option[ScalaModuleInfo],
379364
updateConfig: UpdateConfiguration,
380365
warningConfig: UnresolvedWarningConfiguration,
381-
log: Logger,
382-
moduleID: ModuleID): UpdateReport = {
366+
log: Logger): UpdateReport = {
383367
val descriptor = dependencyRes.wrapDependencyInModule(moduleID, scalaInfo)
384368

385369
dependencyRes.update(descriptor, updateConfig, warningConfig, log) match {
@@ -401,13 +385,43 @@ object DottyPlugin extends AutoPlugin {
401385
}
402386

403387
/** 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. */
388+
* If zero or more than one jar match, an exception will be thrown.
389+
*/
405390
def getJar(updateReport: UpdateReport, organization: NameFilter, name: NameFilter, revision: NameFilter): File = {
406391
val jars = getJars(updateReport, organization, name, revision)
407392
assert(jars.size == 1, s"There should only be one $name jar but found: $jars")
408393
jars.head
409394
}
410395

396+
/** Create a scalaInstance task that uses Dotty based on `moduleName`. */
397+
def dottyScalaInstanceTask(moduleName: String): Initialize[Task[ScalaInstance]] = Def.task {
398+
val updateReport =
399+
fetchArtifactsOf(
400+
scalaOrganization.value %% moduleName % scalaVersion.value,
401+
dependencyResolution.value,
402+
scalaModuleInfo.value,
403+
updateConfiguration.value,
404+
(unresolvedWarningConfiguration in update).value,
405+
streams.value.log)
406+
val scalaLibraryJar = getJar(updateReport,
407+
"org.scala-lang", "scala-library", revision = AllPassFilter)
408+
val dottyLibraryJar = getJar(updateReport,
409+
scalaOrganization.value, s"dotty-library_${scalaBinaryVersion.value}", scalaVersion.value)
410+
val compilerJar = getJar(updateReport,
411+
scalaOrganization.value, s"dotty-compiler_${scalaBinaryVersion.value}", scalaVersion.value)
412+
val allJars =
413+
getJars(updateReport, AllPassFilter, AllPassFilter, AllPassFilter)
414+
415+
makeScalaInstance(
416+
state.value,
417+
scalaVersion.value,
418+
scalaLibraryJar,
419+
dottyLibraryJar,
420+
compilerJar,
421+
allJars
422+
)
423+
}
424+
411425
def makeScalaInstance(
412426
state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File]
413427
): ScalaInstance = {

0 commit comments

Comments
 (0)