Skip to content

Commit 6e37dec

Browse files
authored
Merge pull request #13982 from dwijnand/repl/settings-command
Implement :settings in the REPL
2 parents 5fffd2d + 4b7175f commit 6e37dec

File tree

7 files changed

+67
-7
lines changed

7 files changed

+67
-7
lines changed

compiler/src/dotty/tools/dotc/core/MacroClassLoader.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object MacroClassLoader {
2323
private def makeMacroClassLoader(using Context): ClassLoader = trace("new macro class loader") {
2424
val entries = ClassPath.expandPath(ctx.settings.classpath.value, expandStar=true)
2525
val urls = entries.map(cp => java.nio.file.Paths.get(cp).toUri.toURL).toArray
26-
val out = ctx.settings.outputDir.value.jpath.toUri.toURL // to find classes in case of suspended compilation
27-
new java.net.URLClassLoader(urls :+ out, getClass.getClassLoader)
26+
val out = Option(ctx.settings.outputDir.value.toURL) // to find classes in case of suspended compilation
27+
new java.net.URLClassLoader(urls ++ out.toList, getClass.getClassLoader)
2828
}
2929
}

compiler/src/dotty/tools/repl/AbstractFileClassLoader.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import io.AbstractFile
1818
import java.net.{URL, URLConnection, URLStreamHandler}
1919
import java.util.Collections
2020

21-
class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) extends ClassLoader(parent):
21+
class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader) extends ClassLoader(parent):
2222
private def findAbstractFile(name: String) = root.lookupPath(name.split('/').toIndexedSeq, directory = false)
2323

2424
override protected def findResource(name: String) =

compiler/src/dotty/tools/repl/ParseResult.scala

+8-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ case object Imports extends Command {
8080
val command: String = ":imports"
8181
}
8282

83+
case class Settings(arg: String) extends Command
84+
object Settings {
85+
val command: String = ":settings"
86+
}
87+
8388
/** Reset the session to the initial state from when the repl program was
8489
* started
8590
*/
@@ -106,6 +111,7 @@ case object Help extends Command {
106111
|:doc <expression> print the documentation for the given expression
107112
|:imports show import history
108113
|:reset reset the repl to its initial state, forgetting all session entries
114+
|:settings <options> update compiler options, if possible
109115
""".stripMargin
110116
}
111117

@@ -128,7 +134,8 @@ object ParseResult {
128134
Imports.command -> (_ => Imports),
129135
Load.command -> (arg => Load(arg)),
130136
TypeOf.command -> (arg => TypeOf(arg)),
131-
DocOf.command -> (arg => DocOf(arg))
137+
DocOf.command -> (arg => DocOf(arg)),
138+
Settings.command -> (arg => Settings(arg)),
132139
)
133140

134141
def apply(source: SourceFile)(implicit state: State): ParseResult = {

compiler/src/dotty/tools/repl/Rendering.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {
3131

3232
private val MaxStringElements: Int = 1000 // no need to mkString billions of elements
3333

34-
private var myClassLoader: ClassLoader = _
34+
private var myClassLoader: AbstractFileClassLoader = _
3535

3636
private var myReplStringOf: Object => String = _
3737

3838

3939
/** Class loader used to load compiled code */
4040
private[repl] def classLoader()(using Context) =
41-
if (myClassLoader != null) myClassLoader
41+
if (myClassLoader != null && myClassLoader.root == ctx.settings.outputDir.value) myClassLoader
4242
else {
43-
val parent = parentClassLoader.getOrElse {
43+
val parent = Option(myClassLoader).orElse(parentClassLoader).getOrElse {
4444
val compilerClasspath = ctx.platform.classPath(using ctx).asURLs
4545
// We can't use the system classloader as a parent because it would
4646
// pollute the user classpath with everything passed to the JVM

compiler/src/dotty/tools/repl/ReplDriver.scala

+19
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import java.nio.charset.StandardCharsets
55

66
import dotty.tools.dotc.ast.Trees._
77
import dotty.tools.dotc.ast.{tpd, untpd}
8+
import dotty.tools.dotc.config.CommandLineParser.tokenize
89
import dotty.tools.dotc.config.Properties.{javaVersion, javaVmName, simpleVersionString}
910
import dotty.tools.dotc.core.Contexts._
11+
import dotty.tools.dotc.core.Decorators._
1012
import dotty.tools.dotc.core.Phases.{unfusedPhases, typerPhase}
1113
import dotty.tools.dotc.core.Denotations.Denotation
1214
import dotty.tools.dotc.core.Flags._
@@ -414,6 +416,23 @@ class ReplDriver(settings: Array[String],
414416
}
415417
state
416418

419+
case Settings(arg) => arg match
420+
case "" =>
421+
given ctx: Context = state.context
422+
for (s <- ctx.settings.userSetSettings(ctx.settingsState).sortBy(_.name))
423+
out.println(s"${s.name} = ${if s.value == "" then "\"\"" else s.value}")
424+
state
425+
case _ =>
426+
setup(tokenize(arg).toArray, rootCtx) match
427+
case Some((files, ictx)) =>
428+
inContext(ictx) {
429+
if files.nonEmpty then out.println(i"Ignoring spurious arguments: $files%, %")
430+
ictx.base.initialize()(using ictx)
431+
rootCtx = ictx
432+
}
433+
case _ =>
434+
state.copy(context = rootCtx)
435+
417436
case Quit =>
418437
// end of the world!
419438
state
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
scala> def f(thread: Thread) = thread.stop()
2+
there were 1 deprecation warning(s); re-run with -deprecation for details
3+
def f(thread: Thread): Unit
4+
5+
scala>:settings -deprecation foo.scala
6+
Ignoring spurious arguments: foo.scala
7+
8+
scala> def f(thread: Thread) = thread.stop()
9+
1 warning found
10+
-- Deprecation Warning: --------------------------------------------------------
11+
1 | def f(thread: Thread) = thread.stop()
12+
| ^^^^^^^^^^^
13+
|method stop in class Thread is deprecated since : see corresponding Javadoc for more information.
14+
def f(thread: Thread): Unit
15+
16+
scala>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
scala> java.nio.file.Files.exists(java.nio.file.Files.createDirectories(java.nio.file.Paths.get("target", "test-repl-settings-outDir")))
2+
val res0: Boolean = true
3+
4+
scala> val x = 1
5+
val x: Int = 1
6+
7+
scala>:settings -d target/test-repl-settings-outDir
8+
9+
scala> val y = 2
10+
val y: Int = 2
11+
12+
scala> x
13+
val res1: Int = 1
14+
15+
scala> y
16+
val res2: Int = 2
17+
18+
scala> java.nio.file.Files.walk(java.nio.file.Paths.get("target", "test-repl-settings-outDir")).sorted(java.util.Comparator.reverseOrder).forEach(java.nio.file.Files.delete)

0 commit comments

Comments
 (0)