Skip to content

Commit

Permalink
Merge pull request #13982 from dwijnand/repl/settings-command
Browse files Browse the repository at this point in the history
Implement :settings in the REPL
  • Loading branch information
griggt committed Dec 13, 2021
2 parents 5fffd2d + 4b7175f commit 6e37dec
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 7 deletions.
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/MacroClassLoader.scala
Expand Up @@ -23,7 +23,7 @@ object MacroClassLoader {
private def makeMacroClassLoader(using Context): ClassLoader = trace("new macro class loader") {
val entries = ClassPath.expandPath(ctx.settings.classpath.value, expandStar=true)
val urls = entries.map(cp => java.nio.file.Paths.get(cp).toUri.toURL).toArray
val out = ctx.settings.outputDir.value.jpath.toUri.toURL // to find classes in case of suspended compilation
new java.net.URLClassLoader(urls :+ out, getClass.getClassLoader)
val out = Option(ctx.settings.outputDir.value.toURL) // to find classes in case of suspended compilation
new java.net.URLClassLoader(urls ++ out.toList, getClass.getClassLoader)
}
}
Expand Up @@ -18,7 +18,7 @@ import io.AbstractFile
import java.net.{URL, URLConnection, URLStreamHandler}
import java.util.Collections

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

override protected def findResource(name: String) =
Expand Down
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/repl/ParseResult.scala
Expand Up @@ -80,6 +80,11 @@ case object Imports extends Command {
val command: String = ":imports"
}

case class Settings(arg: String) extends Command
object Settings {
val command: String = ":settings"
}

/** Reset the session to the initial state from when the repl program was
* started
*/
Expand All @@ -106,6 +111,7 @@ case object Help extends Command {
|:doc <expression> print the documentation for the given expression
|:imports show import history
|:reset reset the repl to its initial state, forgetting all session entries
|:settings <options> update compiler options, if possible
""".stripMargin
}

Expand All @@ -128,7 +134,8 @@ object ParseResult {
Imports.command -> (_ => Imports),
Load.command -> (arg => Load(arg)),
TypeOf.command -> (arg => TypeOf(arg)),
DocOf.command -> (arg => DocOf(arg))
DocOf.command -> (arg => DocOf(arg)),
Settings.command -> (arg => Settings(arg)),
)

def apply(source: SourceFile)(implicit state: State): ParseResult = {
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/repl/Rendering.scala
Expand Up @@ -31,16 +31,16 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {

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

private var myClassLoader: ClassLoader = _
private var myClassLoader: AbstractFileClassLoader = _

private var myReplStringOf: Object => String = _


/** Class loader used to load compiled code */
private[repl] def classLoader()(using Context) =
if (myClassLoader != null) myClassLoader
if (myClassLoader != null && myClassLoader.root == ctx.settings.outputDir.value) myClassLoader
else {
val parent = parentClassLoader.getOrElse {
val parent = Option(myClassLoader).orElse(parentClassLoader).getOrElse {
val compilerClasspath = ctx.platform.classPath(using ctx).asURLs
// We can't use the system classloader as a parent because it would
// pollute the user classpath with everything passed to the JVM
Expand Down
19 changes: 19 additions & 0 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Expand Up @@ -5,8 +5,10 @@ import java.nio.charset.StandardCharsets

import dotty.tools.dotc.ast.Trees._
import dotty.tools.dotc.ast.{tpd, untpd}
import dotty.tools.dotc.config.CommandLineParser.tokenize
import dotty.tools.dotc.config.Properties.{javaVersion, javaVmName, simpleVersionString}
import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.core.Decorators._
import dotty.tools.dotc.core.Phases.{unfusedPhases, typerPhase}
import dotty.tools.dotc.core.Denotations.Denotation
import dotty.tools.dotc.core.Flags._
Expand Down Expand Up @@ -414,6 +416,23 @@ class ReplDriver(settings: Array[String],
}
state

case Settings(arg) => arg match
case "" =>
given ctx: Context = state.context
for (s <- ctx.settings.userSetSettings(ctx.settingsState).sortBy(_.name))
out.println(s"${s.name} = ${if s.value == "" then "\"\"" else s.value}")
state
case _ =>
setup(tokenize(arg).toArray, rootCtx) match
case Some((files, ictx)) =>
inContext(ictx) {
if files.nonEmpty then out.println(i"Ignoring spurious arguments: $files%, %")
ictx.base.initialize()(using ictx)
rootCtx = ictx
}
case _ =>
state.copy(context = rootCtx)

case Quit =>
// end of the world!
state
Expand Down
16 changes: 16 additions & 0 deletions compiler/test-resources/repl/settings-command
@@ -0,0 +1,16 @@
scala> def f(thread: Thread) = thread.stop()
there were 1 deprecation warning(s); re-run with -deprecation for details
def f(thread: Thread): Unit

scala>:settings -deprecation foo.scala
Ignoring spurious arguments: foo.scala

scala> def f(thread: Thread) = thread.stop()
1 warning found
-- Deprecation Warning: --------------------------------------------------------
1 | def f(thread: Thread) = thread.stop()
| ^^^^^^^^^^^
|method stop in class Thread is deprecated since : see corresponding Javadoc for more information.
def f(thread: Thread): Unit

scala>
18 changes: 18 additions & 0 deletions compiler/test-resources/repl/settings-outputDir
@@ -0,0 +1,18 @@
scala> java.nio.file.Files.exists(java.nio.file.Files.createDirectories(java.nio.file.Paths.get("target", "test-repl-settings-outDir")))
val res0: Boolean = true

scala> val x = 1
val x: Int = 1

scala>:settings -d target/test-repl-settings-outDir

scala> val y = 2
val y: Int = 2

scala> x
val res1: Int = 1

scala> y
val res2: Int = 2

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 comments on commit 6e37dec

Please sign in to comment.