Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ trait CommonScalaSettings:
val encoding: Setting[String] = StringSetting(RootSetting, "encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding, aliases = List("--encoding"))
val scalajs: Setting[Boolean] = BooleanSetting(RootSetting, "scalajs", "Compile in Scala.js mode (requires scalajs-library.jar on the classpath).", aliases = List("--scalajs"))
val replInitScript: Setting[String] = StringSetting(RootSetting, "repl-init-script", "code", "The code will be run on REPL startup.", "", aliases = List("--repl-init-script"))
val replInitPackage: Setting[String] = StringSetting(RootSetting, "repl-init-package", "package", "The package in which REPL-entered code is wrapped. Defaults to the empty package.", "", aliases = List("--repl-init-package"))
val replQuitAfterInit: Setting[Boolean] = BooleanSetting(RootSetting, "repl-quit-after-init", "Quit REPL after evaluating the init script.", aliases = List("--repl-quit-after-init"))

/* YSettings shared with scaladoc */
Expand Down
24 changes: 20 additions & 4 deletions repl/src/dotty/tools/repl/ReplCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@ class ReplCompiler extends Compiler:
def importContext(imp: tpd.Import)(using Context) =
ctx.importContext(imp, imp.symbol)

val pkgName = initCtx.settings.replInitPackage.value(using initCtx).trim
val pkgPrefix = if pkgName.isEmpty then nme.EMPTY_PACKAGE.toString else pkgName

def importPreviousRun(id: Int)(using Context) = {
// we first import the wrapper object id
val path = nme.EMPTY_PACKAGE ++ "." ++ ReplCompiler.objectNames(id)
val path = s"$pkgPrefix.${ReplCompiler.objectNames(id)}"
val ctx0 = ctx.fresh
.setNewScope
.withRootImports(RootRef(() => requiredModuleRef(path)) :: Nil)
Expand All @@ -64,6 +67,9 @@ class ReplCompiler extends Compiler:
importContext(imp)(using ctx))
}

// The owner stays the empty package; the PackageDef wrapping each
// input is what places definitions into the configured package
// during typechecking.
val rootCtx = super.rootContext.fresh
.withRootImports
.fresh.setOwner(defn.EmptyPackageClass): Context
Expand All @@ -77,7 +83,7 @@ class ReplCompiler extends Compiler:

private def packaged(stats: List[untpd.Tree])(using Context): untpd.PackageDef =
import untpd.*
PackageDef(Ident(nme.EMPTY_PACKAGE), stats)
PackageDef(ReplCompiler.packageId, stats)

final def compile(parsed: Parsed)(using state: State): Either[(List[Diagnostic], State), (CompilationUnit, State)] =
assert(!parsed.trees.isEmpty)
Expand Down Expand Up @@ -166,7 +172,7 @@ class ReplCompiler extends Compiler:
val wrapper = TypeDef("$wrapper".toTypeName, tmpl)
.withMods(Modifiers(Final))
.withSpan(Span(0, expr.length))
PackageDef(Ident(nme.EMPTY_PACKAGE), List(wrapper))
PackageDef(ReplCompiler.packageId, List(wrapper))
}

ParseResult(sourceFile) match {
Expand Down Expand Up @@ -230,9 +236,19 @@ class ReplCompiler extends Compiler:
}
}
}

object ReplCompiler:
val ReplState: Property.StickyKey[State] = Property.StickyKey()
val objectNames = mutable.Map.empty[Int, TermName]

def packageId(using Context): untpd.RefTree =
import untpd.*
val name = ctx.settings.replInitPackage.value.trim
if name.isEmpty then Ident(nme.EMPTY_PACKAGE)
else
val parts = name.split('.').toList
parts.tail.foldLeft[RefTree](Ident(parts.head.toTermName))((acc, p) =>
Select(acc, p.toTermName))
end ReplCompiler

class ReplCompilationUnit(source: SourceFile) extends CompilationUnit(source, CompilationUnitInfo(source.file)):
Expand Down Expand Up @@ -346,5 +362,5 @@ class ReplPhase extends Phase:
val tmpl = Template(emptyConstructor, Nil, Nil, EmptyValDef, defs.stats)
val module = ModuleDef(objectTermName, tmpl).withSpan(span)

PackageDef(Ident(nme.EMPTY_PACKAGE), List(module))
PackageDef(ReplCompiler.packageId, List(module))
end ReplPhase
11 changes: 11 additions & 0 deletions repl/test-resources/repl/replInitPackage
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//> using options --repl-init-package:my.app
scala> class Foo
// defined class Foo
scala> classOf[Foo].getName
val res0: String = "my.app.rs$line$1$Foo"
scala> object Bar { val x = 1 }
// defined object Bar
scala> Bar.x + 1
val res1: Int = 2
scala> Bar.getClass.getName
val res2: String = "my.app.rs$line$3$Bar$"
Loading