11package dotty .tools .repl
22
33import scala .language .unsafeNulls
4- import java .io .{PrintStream , File as JFile }
4+ import java .io .{File => JFile , PrintStream }
55import java .nio .charset .StandardCharsets
66import dotty .tools .dotc .ast .Trees .*
77import dotty .tools .dotc .ast .{tpd , untpd }
8- import dotty .tools .dotc .classpath .{ AggregateClassPath , ClassPathFactory , ZipAndJarClassPathFactory }
8+ import dotty .tools .dotc .classpath .ClassPathFactory
99import dotty .tools .dotc .config .CommandLineParser .tokenize
1010import dotty .tools .dotc .config .Properties .{javaVersion , javaVmName , simpleVersionString }
1111import dotty .tools .dotc .core .Contexts .*
1212import dotty .tools .dotc .core .Decorators .*
13- import dotty .tools .dotc .core .Phases .{typerPhase , unfusedPhases }
13+ import dotty .tools .dotc .core .Phases .{unfusedPhases , typerPhase }
1414import dotty .tools .dotc .core .Denotations .Denotation
1515import dotty .tools .dotc .core .Flags .*
1616import dotty .tools .dotc .core .Mode
@@ -94,7 +94,7 @@ class ReplDriver(settings: Array[String],
9494 initCtx.settings.YwithBestEffortTasty .name
9595 )
9696
97- private def setupRootCtx (settings : Array [String ], rootCtx : Context ) = {
97+ private def setupRootCtx (settings : Array [String ], rootCtx : Context , previousOutputDir : Option [ AbstractFile ] = None ) = {
9898 val incompatible = settings.intersect(incompatibleOptions)
9999 val filteredSettings =
100100 if ! incompatible.isEmpty then
@@ -107,7 +107,7 @@ class ReplDriver(settings: Array[String],
107107 case Some ((files, ictx)) => inContext(ictx) {
108108 shouldStart = true
109109 if files.nonEmpty then out.println(i " Ignoring spurious arguments: $files%, % " )
110- ictx.base.initialize()
110+ ictx.base.initialize(previousOutputDir )
111111 ictx
112112 }
113113 case None =>
@@ -523,44 +523,49 @@ class ReplDriver(settings: Array[String],
523523
524524 val entries = flatten(jarFile)
525525
526- def classNameOf (classFile : AbstractFile ): String = {
526+ def tryClassLoad (classFile : AbstractFile ): Option [ String ] = {
527527 val input = classFile.input
528528 try {
529529 val reader = new ClassReader (input)
530- reader.getClassName.replace('/' , '.' )
531- } finally {
530+ val clsName = reader.getClassName.replace('/' , '.' )
531+ rendering.myClassLoader.loadClass(clsName)
532+ Some (clsName)
533+ } catch
534+ case _ : ClassNotFoundException => None
535+ finally {
532536 input.close()
533537 }
534538 }
535539
536- def alreadyDefined (clsName : String ) = state.context.platform.classPath(using state.context).findClassFile(clsName).isDefined
537- val existingClass = entries.filter(_.ext.isClass).map(classNameOf).find(alreadyDefined)
540+ val existingClass = entries.filter(_.ext.isClass).find(tryClassLoad(_).isDefined)
538541 if (existingClass.nonEmpty)
539542 out.println(s " The path ' $f' cannot be loaded, it contains a classfile that already exists on the classpath: ${existingClass.get}" )
540543 state
541544 else
542545 val cp = state.context.platform.classPath(using state.context).asClassPathString
543- // println(s"CURRENT CP STRING: $cp")
544546 val newCP = s " $cp${JFile .pathSeparator}$path"
545- println(s " UPDATED CP: $newCP" )
546547
547548 // add to compiler class path
548- // println(s"INIT state classPath = ${state.context.platform.classPath(using state.context).asClassPathString}")
549- // val cpCP = ClassPathFactory.newClassPath(jarFile)(using state.context)
550- // state.context.platform.addToClassPath(cpCP)
551- // println(s"classPath after add = ${state.context.platform.classPath(using state.context).asClassPathString}")
552-
553- // recreate initial context
554- resetToInitial(List (" -classpath" , newCP))
555- // rootCtx = setupRootCtx(Array(), rootCtx.fresh.setSetting(rootCtx.settings.classpath, newCP))
549+ val prevOutputDir = rootCtx.settings.outputDir.valueIn(rootCtx.settingsState)
550+ val ctxToUse = initCtx.fresh.setSetting(rootCtx.settings.classpath, newCP)
551+ rootCtx = setupRootCtx(
552+ Array (),
553+ ctxToUse,
554+ previousOutputDir = Some (prevOutputDir)
555+ )
556556 val s = state.copy(context = rootCtx)
557557
558- // new class loader
559- val oldCL = rendering.classLoader()(using state.context)
560- val newCL = fromURLsParallelCapable(s.context.platform.classPath(using s.context).asURLs, oldCL)
561- rendering.myClassLoader = new AbstractFileClassLoader (state.context.settings.outputDir.default, newCL)
562- // out.println(s"Added '$path' to classpath.")
558+ // new class loader with previous output dir and specified jar
559+ val prevClassLoader = rendering.classLoader()(using state.context)
560+ val jarClassLoader = fromURLsParallelCapable(
561+ ClassPathFactory .newClassPath(jarFile)(using rootCtx).asURLs, prevClassLoader)
562+ val replOutputClassLoader = new AbstractFileClassLoader (
563+ prevOutputDir, jarClassLoader)
564+ rendering.myClassLoader = new AbstractFileClassLoader (
565+ rootCtx.settings.outputDir.valueIn(rootCtx.settingsState), replOutputClassLoader)
566+ out.println(s " Added ' $path' to classpath. " )
563567 s
568+
564569 case TypeOf (expr) =>
565570 expr match {
566571 case " " => out.println(s " :type <expression> " )
0 commit comments