@@ -7,6 +7,7 @@ import java.nio.charset.StandardCharsets
77
88import dotty .tools .dotc .ast .Trees .*
99import dotty .tools .dotc .ast .{tpd , untpd }
10+ import dotty .tools .dotc .classpath .ClassPathFactory
1011import dotty .tools .dotc .config .CommandLineParser .tokenize
1112import dotty .tools .dotc .config .Properties .{javaVersion , javaVmName , simpleVersionString }
1213import dotty .tools .dotc .core .Contexts .*
@@ -21,6 +22,7 @@ import dotty.tools.dotc.core.NameOps.*
2122import dotty .tools .dotc .core .Names .Name
2223import dotty .tools .dotc .core .StdNames .*
2324import dotty .tools .dotc .core .Symbols .{Symbol , defn }
25+ import dotty .tools .dotc .core .SymbolLoaders
2426import dotty .tools .dotc .interfaces
2527import dotty .tools .dotc .interactive .Completion
2628import dotty .tools .dotc .printing .SyntaxHighlighting
@@ -38,6 +40,7 @@ import org.jline.reader.*
3840import scala .annotation .tailrec
3941import scala .collection .mutable
4042import scala .jdk .CollectionConverters .*
43+ import scala .tools .asm .ClassReader
4144import scala .util .control .NonFatal
4245import scala .util .Using
4346
@@ -513,10 +516,65 @@ class ReplDriver(settings: Array[String],
513516 state
514517 }
515518
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+
516575 case KindOf (expr) =>
517576 out.println(s """ The :kind command is not currently supported. """ )
518577 state
519-
520578 case TypeOf (expr) =>
521579 expr match {
522580 case " " => out.println(s " :type <expression> " )
0 commit comments