@@ -8,11 +8,16 @@ import sbt.librarymanagement.{
88 VersionNumber
99}
1010import sbt .internal .inc .ScalaInstance
11+ import sbt .internal .inc .classpath .ClassLoaderCache
1112import xsbti .compile ._
13+ import xsbti .AppConfiguration
1214import java .net .URLClassLoader
1315import java .util .Optional
16+ import java .util .{Enumeration , Collections }
17+ import java .net .URL
1418import scala .util .Properties .isJavaAtLeast
1519
20+
1621object DottyPlugin extends AutoPlugin {
1722 object autoImport {
1823 val isDotty = settingKey[Boolean ](" Is this project compiled with Dotty?" )
@@ -534,15 +539,34 @@ object DottyPlugin extends AutoPlugin {
534539 scalaLibraryJar,
535540 dottyLibraryJar,
536541 compilerJar,
537- allJars
542+ allJars,
543+ appConfiguration.value
538544 )
539545 }
540546
541547 // Adapted from private mkScalaInstance in sbt
542548 def makeScalaInstance (
543- state : State , dottyVersion : String , scalaLibrary : File , dottyLibrary : File , compiler : File , all : Seq [File ]
549+ state : State , dottyVersion : String , scalaLibrary : File , dottyLibrary : File , compiler : File , all : Seq [File ], appConfiguration : AppConfiguration
544550 ): ScalaInstance = {
545- val libraryLoader = state.classLoaderCache(List (dottyLibrary, scalaLibrary))
551+ /**
552+ * The compiler bridge must load the xsbti classes from the sbt
553+ * classloader, and similarly the Scala repl must load the sbt provided
554+ * jline terminal. To do so we add the `appConfiguration` loader in
555+ * the parent hierarchy of the scala 3 instance loader.
556+ *
557+ * The [[TopClassLoader ]] ensures that the xsbti and jline classes
558+ * only are loaded from the sbt loader. That is necessary because
559+ * the sbt class loader contains the Scala 2.12 library and compiler
560+ * bridge.
561+ */
562+ val topLoader = new TopClassLoader (appConfiguration.provider.loader)
563+
564+ val libraryJars = Array (dottyLibrary, scalaLibrary)
565+ val libraryLoader = state.classLoaderCache.cachedCustomClassloader(
566+ libraryJars.toList,
567+ () => new URLClassLoader (libraryJars.map(_.toURI.toURL), topLoader)
568+ )
569+
546570 class DottyLoader
547571 extends URLClassLoader (all.map(_.toURI.toURL).toArray, libraryLoader)
548572 val fullLoader = state.classLoaderCache.cachedCustomClassloader(
@@ -553,10 +577,25 @@ object DottyPlugin extends AutoPlugin {
553577 dottyVersion,
554578 fullLoader,
555579 libraryLoader,
556- Array (dottyLibrary, scalaLibrary) ,
580+ libraryJars ,
557581 compiler,
558582 all.toArray,
559583 None )
584+ }
585+ }
586+
587+ private class TopClassLoader (sbtLoader : ClassLoader ) extends ClassLoader (null ) {
588+ private val sharedPrefixes = List (
589+ " xsbti." ,
590+ " org.jline."
591+ )
560592
593+ override protected def loadClass (name : String , resolve : Boolean ): Class [_] = {
594+ if (sharedPrefixes.exists(name.startsWith(_))) {
595+ val c = sbtLoader.loadClass(name)
596+ if (resolve) resolveClass(c)
597+ c
598+ }
599+ else super .loadClass(name, resolve)
561600 }
562601}
0 commit comments