1
1
package dotty .tools .repl
2
2
3
3
import scala .language .unsafeNulls
4
- import java .io .{PrintStream , File as JFile }
4
+ import java .io .{File => JFile , PrintStream }
5
5
import java .nio .charset .StandardCharsets
6
6
import dotty .tools .dotc .ast .Trees .*
7
7
import dotty .tools .dotc .ast .{tpd , untpd }
8
- import dotty .tools .dotc .classpath .{ AggregateClassPath , ClassPathFactory , ZipAndJarClassPathFactory }
8
+ import dotty .tools .dotc .classpath .ClassPathFactory
9
9
import dotty .tools .dotc .config .CommandLineParser .tokenize
10
10
import dotty .tools .dotc .config .Properties .{javaVersion , javaVmName , simpleVersionString }
11
11
import dotty .tools .dotc .core .Contexts .*
12
12
import dotty .tools .dotc .core .Decorators .*
13
- import dotty .tools .dotc .core .Phases .{typerPhase , unfusedPhases }
13
+ import dotty .tools .dotc .core .Phases .{unfusedPhases , typerPhase }
14
14
import dotty .tools .dotc .core .Denotations .Denotation
15
15
import dotty .tools .dotc .core .Flags .*
16
16
import dotty .tools .dotc .core .Mode
@@ -94,7 +94,7 @@ class ReplDriver(settings: Array[String],
94
94
initCtx.settings.YwithBestEffortTasty .name
95
95
)
96
96
97
- private def setupRootCtx (settings : Array [String ], rootCtx : Context ) = {
97
+ private def setupRootCtx (settings : Array [String ], rootCtx : Context , previousOutputDir : Option [ AbstractFile ] = None ) = {
98
98
val incompatible = settings.intersect(incompatibleOptions)
99
99
val filteredSettings =
100
100
if ! incompatible.isEmpty then
@@ -107,7 +107,7 @@ class ReplDriver(settings: Array[String],
107
107
case Some ((files, ictx)) => inContext(ictx) {
108
108
shouldStart = true
109
109
if files.nonEmpty then out.println(i " Ignoring spurious arguments: $files%, % " )
110
- ictx.base.initialize()
110
+ ictx.base.initialize(previousOutputDir )
111
111
ictx
112
112
}
113
113
case None =>
@@ -523,44 +523,49 @@ class ReplDriver(settings: Array[String],
523
523
524
524
val entries = flatten(jarFile)
525
525
526
- def classNameOf (classFile : AbstractFile ): String = {
526
+ def tryClassLoad (classFile : AbstractFile ): Option [ String ] = {
527
527
val input = classFile.input
528
528
try {
529
529
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 {
532
536
input.close()
533
537
}
534
538
}
535
539
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)
538
541
if (existingClass.nonEmpty)
539
542
out.println(s " The path ' $f' cannot be loaded, it contains a classfile that already exists on the classpath: ${existingClass.get}" )
540
543
state
541
544
else
542
545
val cp = state.context.platform.classPath(using state.context).asClassPathString
543
- // println(s"CURRENT CP STRING: $cp")
544
546
val newCP = s " $cp${JFile .pathSeparator}$path"
545
- println(s " UPDATED CP: $newCP" )
546
547
547
548
// 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
+ )
556
556
val s = state.copy(context = rootCtx)
557
557
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. " )
563
567
s
568
+
564
569
case TypeOf (expr) =>
565
570
expr match {
566
571
case " " => out.println(s " :type <expression> " )
0 commit comments