@@ -7,6 +7,7 @@ import java.nio.charset.StandardCharsets
7
7
8
8
import dotty .tools .dotc .ast .Trees .*
9
9
import dotty .tools .dotc .ast .{tpd , untpd }
10
+ import dotty .tools .dotc .classpath .ClassPathFactory
10
11
import dotty .tools .dotc .config .CommandLineParser .tokenize
11
12
import dotty .tools .dotc .config .Properties .{javaVersion , javaVmName , simpleVersionString }
12
13
import dotty .tools .dotc .core .Contexts .*
@@ -21,6 +22,7 @@ import dotty.tools.dotc.core.NameOps.*
21
22
import dotty .tools .dotc .core .Names .Name
22
23
import dotty .tools .dotc .core .StdNames .*
23
24
import dotty .tools .dotc .core .Symbols .{Symbol , defn }
25
+ import dotty .tools .dotc .core .SymbolLoaders
24
26
import dotty .tools .dotc .interfaces
25
27
import dotty .tools .dotc .interactive .Completion
26
28
import dotty .tools .dotc .printing .SyntaxHighlighting
@@ -39,6 +41,7 @@ import scala.annotation.tailrec
39
41
import scala .collection .mutable
40
42
import scala .compiletime .uninitialized
41
43
import scala .jdk .CollectionConverters .*
44
+ import scala .tools .asm .ClassReader
42
45
import scala .util .control .NonFatal
43
46
import scala .util .Using
44
47
@@ -512,10 +515,65 @@ class ReplDriver(settings: Array[String],
512
515
state
513
516
}
514
517
518
+ case Require (path) =>
519
+ out.println(" :require is no longer supported, but has been replaced with :jar. Please use :jar" )
520
+ state
521
+
522
+ case JarCmd (path) =>
523
+ val jarFile = AbstractFile .getDirectory(path)
524
+ if (jarFile == null )
525
+ out.println(s """ Cannot add " $path" to classpath. """ )
526
+ state
527
+ else
528
+ def flatten (f : AbstractFile ): Iterator [AbstractFile ] =
529
+ if (f.isClassContainer) f.iterator.flatMap(flatten)
530
+ else Iterator (f)
531
+
532
+ def tryClassLoad (classFile : AbstractFile ): Option [String ] = {
533
+ val input = classFile.input
534
+ try {
535
+ val reader = new ClassReader (input)
536
+ val clsName = reader.getClassName.replace('/' , '.' )
537
+ rendering.myClassLoader.loadClass(clsName)
538
+ Some (clsName)
539
+ } catch
540
+ case _ : ClassNotFoundException => None
541
+ finally {
542
+ input.close()
543
+ }
544
+ }
545
+
546
+ try {
547
+ val entries = flatten(jarFile)
548
+
549
+ val existingClass = entries.filter(_.ext.isClass).find(tryClassLoad(_).isDefined)
550
+ if (existingClass.nonEmpty)
551
+ out.println(s " The path ' $path' cannot be loaded, it contains a classfile that already exists on the classpath: ${existingClass.get}" )
552
+ else inContext(state.context):
553
+ val jarClassPath = ClassPathFactory .newClassPath(jarFile)
554
+ val prevOutputDir = ctx.settings.outputDir.value
555
+
556
+ // add to compiler class path
557
+ ctx.platform.addToClassPath(jarClassPath)
558
+ SymbolLoaders .mergeNewEntries(defn.RootClass , ClassPath .RootPackage , jarClassPath, ctx.platform.classPath)
559
+
560
+ // new class loader with previous output dir and specified jar
561
+ val prevClassLoader = rendering.classLoader()
562
+ val jarClassLoader = fromURLsParallelCapable(
563
+ jarClassPath.asURLs, prevClassLoader)
564
+ rendering.myClassLoader = new AbstractFileClassLoader (
565
+ prevOutputDir, jarClassLoader)
566
+
567
+ out.println(s " Added ' $path' to classpath. " )
568
+ } catch {
569
+ case e : Throwable =>
570
+ out.println(s " Failed to load ' $path' to classpath: ${e.getMessage}" )
571
+ }
572
+ state
573
+
515
574
case KindOf (expr) =>
516
575
out.println(s """ The :kind command is not currently supported. """ )
517
576
state
518
-
519
577
case TypeOf (expr) =>
520
578
expr match {
521
579
case " " => out.println(s " :type <expression> " )
0 commit comments