Skip to content

Commit 2aeeac5

Browse files
committed
[sbt-dotty] use sbt loader as parent of scala instance loader
1 parent d099250 commit 2aeeac5

File tree

4 files changed

+46
-135
lines changed

4 files changed

+46
-135
lines changed

project/Build.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ object Build {
337337
scalaLibrary,
338338
dottyLibrary,
339339
dottyCompiler,
340-
allJars
340+
allJars,
341+
appConfiguration.value
341342
)
342343
},
343344
// sbt-dotty defines `scalaInstance in doc` so we need to override it manually

sbt-bridge/src/xsbt/CompilerClassLoader.java

Lines changed: 0 additions & 122 deletions
This file was deleted.

sbt-bridge/src/xsbt/CompilerInterface.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,9 @@
2020

2121
public final class CompilerInterface {
2222
public CachedCompiler newCompiler(String[] options, Output output, Logger initialLog, Reporter initialDelegate) {
23-
// The classloader that sbt uses to load the compiler bridge is broken
24-
// (see CompilerClassLoader#fixBridgeLoader for details). To workaround
25-
// this we construct our own ClassLoader and then run the following code
26-
// with it:
27-
// new CachedCompilerImpl(options, output)
28-
2923
try {
3024
ClassLoader bridgeLoader = this.getClass().getClassLoader();
31-
ClassLoader fixedLoader = CompilerClassLoader.fixBridgeLoader(bridgeLoader);
32-
Class<?> cciClass = fixedLoader.loadClass("xsbt.CachedCompilerImpl");
25+
Class<?> cciClass = bridgeLoader.loadClass("xsbt.CachedCompilerImpl");
3326
return (CachedCompiler) cciClass.getConstructors()[0].newInstance(options, output);
3427
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
3528
throw new RuntimeException(e);

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

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ import sbt.librarymanagement.{
88
VersionNumber
99
}
1010
import sbt.internal.inc.ScalaInstance
11+
import sbt.internal.inc.classpath.ClassLoaderCache
1112
import xsbti.compile._
13+
import xsbti.AppConfiguration
1214
import java.net.URLClassLoader
1315
import java.util.Optional
16+
import java.util.{Enumeration, Collections}
17+
import java.net.URL
1418
import scala.util.Properties.isJavaAtLeast
1519

20+
1621
object DottyPlugin extends AutoPlugin {
1722
object autoImport {
1823
val isDotty = settingKey[Boolean]("Is this project compiled with Dotty?")
@@ -521,15 +526,34 @@ object DottyPlugin extends AutoPlugin {
521526
scalaLibraryJar,
522527
dottyLibraryJar,
523528
compilerJar,
524-
allJars
529+
allJars,
530+
appConfiguration.value
525531
)
526532
}
527533

528534
// Adapted from private mkScalaInstance in sbt
529535
def makeScalaInstance(
530-
state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File]
536+
state: State, dottyVersion: String, scalaLibrary: File, dottyLibrary: File, compiler: File, all: Seq[File], appConfiguration: AppConfiguration
531537
): ScalaInstance = {
532-
val libraryLoader = state.classLoaderCache(List(dottyLibrary, scalaLibrary))
538+
/**
539+
* The compiler bridge must load the xsbti classes from the sbt
540+
* classloader, and similarly the Scala repl must load the sbt provided
541+
* jline terminal. To do so we add the `appConfiguration` loader in
542+
* the parent hierarchy of the scala 3 instance loader.
543+
*
544+
* The [[TopClassLoader]] ensures that the xsbti and jline classes
545+
* only are loaded from the sbt loader. That is necessary because
546+
* the sbt class loader contains the Scala 2.12 library and compiler
547+
* bridge.
548+
*/
549+
val topLoader = new TopClassLoader(appConfiguration.provider.loader)
550+
551+
val libraryJars = Array(dottyLibrary, scalaLibrary)
552+
val libraryLoader = state.classLoaderCache.cachedCustomClassloader(
553+
libraryJars.toList,
554+
() => new URLClassLoader(libraryJars.map(_.toURI.toURL), topLoader)
555+
)
556+
533557
class DottyLoader
534558
extends URLClassLoader(all.map(_.toURI.toURL).toArray, libraryLoader)
535559
val fullLoader = state.classLoaderCache.cachedCustomClassloader(
@@ -540,10 +564,25 @@ object DottyPlugin extends AutoPlugin {
540564
dottyVersion,
541565
fullLoader,
542566
libraryLoader,
543-
Array(dottyLibrary, scalaLibrary),
567+
libraryJars,
544568
compiler,
545569
all.toArray,
546570
None)
571+
}
572+
}
573+
574+
private class TopClassLoader(sbtLoader: ClassLoader) extends ClassLoader(null) {
575+
private val sharedPrefixes = List(
576+
"xsbti.",
577+
"org.jline."
578+
)
547579

580+
override protected def loadClass(name: String, resolve: Boolean): Class[_] = {
581+
if (sharedPrefixes.exists(name.startsWith(_))) {
582+
val c = sbtLoader.loadClass(name)
583+
if (resolve) resolveClass(c)
584+
c
585+
}
586+
else super.loadClass(name, resolve)
548587
}
549588
}

0 commit comments

Comments
 (0)