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