Skip to content

Commit 32933a5

Browse files
authored
Merge pull request #4744 from dotty-staging/directory-setting
Simplify output directory handling
2 parents f267b27 + 3c419db commit 32933a5

15 files changed

+63
-106
lines changed

compiler/src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,9 @@ class GenBCode extends Phase {
4141

4242
private[this] var myOutput: AbstractFile = _
4343

44-
protected def outputDir(implicit ctx: Context): AbstractFile = {
45-
if (myOutput eq null) {
46-
val path = Directory(ctx.settings.outputDir.value)
47-
myOutput =
48-
if (path.extension == "jar") JarArchive.create(path)
49-
else new PlainDirectory(path)
50-
}
44+
private def outputDir(implicit ctx: Context): AbstractFile = {
45+
if (myOutput eq null)
46+
myOutput = ctx.settings.outputDir.value
5147
myOutput
5248
}
5349

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools.dotc
22
package config
33

44
import java.io.File
5-
import dotty.tools.io.{ Directory, Path }
5+
import dotty.tools.io.{ Directory, PlainDirectory }
66

77
import PathResolver.Defaults
88
import rewrite.Rewrites
@@ -20,7 +20,8 @@ class ScalaSettings extends Settings.SettingGroup {
2020
val scansource = BooleanSetting("-scansource", "Scan source files to locate classes for which class-name != file-name")
2121

2222
val classpath = PathSetting("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp"
23-
val outputDir = PathSetting("-d", "directory|jar", "destination for generated classfiles.", ".")
23+
val outputDir = OutputSetting("-d", "directory|jar", "destination for generated classfiles.",
24+
new PlainDirectory(Directory(".")))
2425
val priorityclasspath = PathSetting("-priorityclasspath", "class path that takes precedence over all other paths (or testing only)", "")
2526

2627
/** Other settings */

compiler/src/dotty/tools/dotc/config/Settings.scala

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import scala.util.{ Try, Success, Failure }
66
import reflect.ClassTag
77
import core.Contexts._
88
import scala.annotation.tailrec
9-
import dotty.tools.io.{ Directory, File, Path }
9+
import dotty.tools.io.{ AbstractFile, Directory, JarArchive, PlainDirectory, File, Path }
1010

1111
// import annotation.unchecked
1212
// Dotty deviation: Imports take precedence over definitions in enclosing package
@@ -22,6 +22,7 @@ object Settings {
2222
val ListTag = ClassTag(classOf[List[_]])
2323
val VersionTag = ClassTag(classOf[ScalaVersion])
2424
val OptionTag = ClassTag(classOf[Option[_]])
25+
val OutputTag = ClassTag(classOf[AbstractFile])
2526

2627
class SettingsState(initialValues: Seq[Any]) {
2728
private[this] var values = ArrayBuffer(initialValues: _*)
@@ -140,14 +141,14 @@ object Settings {
140141
else if (!choices.contains(argRest))
141142
fail(s"$arg is not a valid choice for $name", args)
142143
else update(argRest, args)
143-
case (StringTag, arg :: args) if name == "-d" =>
144-
Path(arg) match {
145-
case _: Directory =>
146-
update(arg, args)
147-
case p if p.extension == "jar" =>
148-
update(arg, args)
149-
case _ =>
150-
fail(s"'$arg' does not exist or is not a directory", args)
144+
case (OutputTag, arg :: args) =>
145+
val path = Directory(arg)
146+
val isJar = path.extension == "jar"
147+
if (!isJar && !path.isDirectory)
148+
fail(s"'$arg' does not exist or is not a directory or .jar file", args)
149+
else {
150+
val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path)
151+
update(output, args)
151152
}
152153
case (StringTag, arg2 :: args2) =>
153154
update(arg2, args2)
@@ -275,11 +276,14 @@ object Settings {
275276
def MultiStringSetting(name: String, helpArg: String, descr: String): Setting[List[String]] =
276277
publish(Setting(name, descr, Nil, helpArg))
277278

279+
def OutputSetting(name: String, helpArg: String, descr: String, default: AbstractFile): Setting[AbstractFile] =
280+
publish(Setting(name, descr, default, helpArg))
281+
278282
def PathSetting(name: String, descr: String, default: String): Setting[String] =
279283
publish(Setting(name, descr, default))
280284

281285
def PathSetting(name: String, helpArg: String, descr: String, default: String): Setting[String] =
282-
publish(Setting(name, descr, default, helpArg))
286+
publish(Setting(name, descr, default, helpArg))
283287

284288
def PhasesSetting(name: String, descr: String, default: String = ""): Setting[List[String]] =
285289
publish(Setting(name, descr, if (default.isEmpty) Nil else List(default)))

compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ class DecompilationPrinter extends Phase {
1919
override def phaseName: String = "decompilationPrinter"
2020

2121
override def run(implicit ctx: Context): Unit = {
22-
val outputDir = ctx.settings.outputDir.value
23-
if (outputDir == ".") printToOutput(System.out)
22+
if (ctx.settings.outputDir.isDefault) printToOutput(System.out)
2423
else {
24+
val outputDir = ctx.settings.outputDir.value
2525
var os: OutputStream = null
2626
var ps: PrintStream = null
2727
try {
28-
os = File(outputDir + "/decompiled.scala").outputStream(append = true)
28+
os = File(outputDir.fileNamed("decompiled.scala").path).outputStream(append = true)
2929
ps = new PrintStream(os)
3030
printToOutput(ps)
3131
} finally {

compiler/src/dotty/tools/dotc/decompiler/Main.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import dotty.tools.dotc.core.Contexts._
1212
object Main extends dotc.Driver {
1313
override protected def newCompiler(implicit ctx: Context): dotc.Compiler = {
1414
assert(ctx.settings.fromTasty.value)
15-
val outputDir = ctx.settings.outputDir.value
16-
if (outputDir != ".")
17-
Files.deleteIfExists(Paths.get(outputDir + "/decompiled.scala"))
15+
if (!ctx.settings.outputDir.isDefault)
16+
Files.deleteIfExists(ctx.settings.outputDir.value.fileNamed("decompiled.scala").jpath)
1817
new TASTYDecompiler
1918
}
2019

compiler/src/dotty/tools/dotc/quoted/QuoteCompiler.scala

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,15 @@ import scala.quoted.{Expr, Type}
2525
/** Compiler that takes the contents of a quoted expression `expr` and produces
2626
* a class file with `class ' { def apply: Object = expr }`.
2727
*/
28-
class QuoteCompiler(directory: AbstractFile) extends Compiler {
28+
class QuoteCompiler extends Compiler {
2929
import tpd._
3030

31-
/** A GenBCode phase that outputs to a virtual directory */
32-
private class ExprGenBCode extends GenBCode {
33-
override def phaseName = "genBCode"
34-
override def outputDir(implicit ctx: Context) = directory
35-
}
36-
3731
override protected def frontendPhases: List[List[Phase]] =
3832
List(List(new QuotedFrontend(putInClass = true)))
3933

4034
override protected def picklerPhases: List[List[Phase]] =
4135
List(List(new ReifyQuotes))
4236

43-
override protected def backendPhases: List[List[Phase]] =
44-
List(List(new ExprGenBCode))
45-
4637
override def newRun(implicit ctx: Context): ExprRun = {
4738
reset()
4839
new ExprRun(this, ctx.addMode(Mode.ReadPositions))

compiler/src/dotty/tools/dotc/quoted/QuoteDecompiler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import dotty.tools.dotc.core.Contexts.Context
55
import dotty.tools.dotc.core.Phases.Phase
66

77
/** Compiler that takes the contents of a quoted expression (or type) and outputs it's tree. */
8-
class QuoteDecompiler(output: tpd.Tree => Context => Unit) extends QuoteCompiler(null) {
8+
class QuoteDecompiler(output: tpd.Tree => Context => Unit) extends QuoteCompiler {
99
override def phases: List[List[Phase]] = List(
1010
List(new QuotedFrontend(putInClass = false)), // Create class from Expr
1111
List(new QuoteTreeOutput(output))

compiler/src/dotty/tools/dotc/quoted/QuoteDriver.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@ class QuoteDriver extends Driver {
1717
private[this] val contextBase: ContextBase = new ContextBase
1818

1919
def run[T](expr: Expr[T], settings: ToolboxSettings): T = {
20-
val (_, ctx: Context) = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh)
21-
2220
val outDir: AbstractFile = settings.outDir match {
2321
case Some(out) =>
2422
val dir = Directory(out)
2523
dir.createDirectory()
2624
new PlainDirectory(Directory(out))
2725
case None =>
28-
new VirtualDirectory("(memory)", None)
26+
new VirtualDirectory("<quote compilation output>")
2927
}
3028

31-
val driver = new QuoteCompiler(outDir)
29+
val (_, ctx0: Context) = setup(settings.compilerArgs.toArray :+ "dummy.scala", initCtx.fresh)
30+
val ctx = ctx0.fresh.setSetting(ctx0.settings.outputDir, outDir)
31+
32+
val driver = new QuoteCompiler
3233
driver.newRun(ctx).compileExpr(expr)
3334

3435
val classLoader = new AbstractFileClassLoader(outDir, this.getClass.getClassLoader)

compiler/src/dotty/tools/io/VirtualDirectory.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import scala.collection.mutable
1313
*
1414
* ''Note: This library is considered experimental and should not be used unless you know what you are doing.''
1515
*/
16-
class VirtualDirectory(val name: String, maybeContainer: Option[VirtualDirectory])
16+
class VirtualDirectory(val name: String, maybeContainer: Option[VirtualDirectory] = None)
1717
extends AbstractFile {
1818
def path: String =
1919
maybeContainer match {

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ import dotc.core.StdNames.str
2222
* `ReplDriver#resetToInitial` is called, the accompanying instance of
2323
* `Rendering` is no longer valid.
2424
*/
25-
private[repl] class Rendering(compiler: ReplCompiler,
26-
parentClassLoader: Option[ClassLoader] = None) {
25+
private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {
2726

2827
private[this] var myClassLoader: ClassLoader = _
2928

@@ -37,7 +36,7 @@ private[repl] class Rendering(compiler: ReplCompiler,
3736
new java.net.URLClassLoader(compilerClasspath.toArray, classOf[ReplDriver].getClassLoader)
3837
}
3938

40-
myClassLoader = new AbstractFileClassLoader(compiler.directory, parent)
39+
myClassLoader = new AbstractFileClassLoader(ctx.settings.outputDir.value, parent)
4140
// Set the current Java "context" class loader to this rendering class loader
4241
Thread.currentThread.setContextClassLoader(myClassLoader)
4342
myClassLoader

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

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,10 @@ import scala.collection.mutable
2828
* in conjunction with a specialized class loader in order to load virtual
2929
* classfiles.
3030
*/
31-
class ReplCompiler(val directory: AbstractFile) extends Compiler {
32-
33-
34-
/** A GenBCode phase that outputs to a virtual directory */
35-
private class REPLGenBCode extends GenBCode {
36-
override def phaseName = "genBCode"
37-
override def outputDir(implicit ctx: Context) = directory
38-
}
39-
31+
class ReplCompiler extends Compiler {
4032
override protected def frontendPhases: List[List[Phase]] =
4133
Phases.replace(classOf[FrontEnd], _ => new REPLFrontEnd :: Nil, super.frontendPhases)
4234

43-
override protected def backendPhases: List[List[Phase]] =
44-
List(new REPLGenBCode) :: Nil
45-
4635
def newRun(initCtx: Context, objectIndex: Int) = new Run(this, initCtx) {
4736
override protected[this] def rootContext(implicit ctx: Context) =
4837
addMagicImports(super.rootContext)

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

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,11 @@ class ReplDriver(settings: Array[String],
8080
*/
8181
protected[this] def resetToInitial(): Unit = {
8282
rootCtx = initialCtx
83-
val outDir: AbstractFile = {
84-
if (rootCtx.settings.outputDir.isDefault(rootCtx))
85-
new VirtualDirectory("(memory)", None)
86-
else {
87-
val path = Directory(rootCtx.settings.outputDir.value(rootCtx))
88-
assert(path.isDirectory)
89-
new PlainDirectory(path)
90-
}
91-
}
92-
compiler = new ReplCompiler(outDir)
93-
rendering = new Rendering(compiler, classLoader)
83+
if (rootCtx.settings.outputDir.isDefault(rootCtx))
84+
rootCtx = rootCtx.fresh
85+
.setSetting(rootCtx.settings.outputDir, new VirtualDirectory("<REPL compilation output>"))
86+
compiler = new ReplCompiler
87+
rendering = new Rendering(classLoader)
9488
}
9589

9690
private[this] var rootCtx: Context = _

compiler/test/dotty/tools/backend/jvm/DottyBytecodeTest.scala

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
package dotty.tools
1+
package dotty
2+
package tools
23
package backend.jvm
34

45
import dotc.core.Contexts.{Context, ContextBase}
6+
import dotc.core.Comments.{ContextDoc, ContextDocstrings}
57
import dotc.core.Phases.Phase
68
import dotc.Compiler
79

@@ -11,19 +13,13 @@ import asm._
1113
import asm.tree._
1214
import scala.collection.JavaConverters._
1315

14-
import io.JavaClassPath
16+
import io.{AbstractFile, JavaClassPath, VirtualDirectory}
1517
import scala.collection.JavaConverters._
1618
import scala.tools.asm.{ClassWriter, ClassReader}
1719
import scala.tools.asm.tree._
1820
import java.io.{File => JFile, InputStream}
1921

20-
class TestGenBCode(val outDir: String) extends GenBCode {
21-
override def phaseName: String = "testGenBCode"
22-
val virtualDir = new Directory(outDir, None)
23-
override def outputDir(implicit ctx: Context) = virtualDir
24-
}
25-
26-
trait DottyBytecodeTest extends DottyTest {
22+
trait DottyBytecodeTest {
2723
import AsmNode._
2824
import ASMConverters._
2925

@@ -45,32 +41,23 @@ trait DottyBytecodeTest extends DottyTest {
4541
val javaString = "java/lang/String"
4642
}
4743

48-
private def bCodeCheckingComp(testPhase: TestGenBCode)(check: Directory => Unit) = {
49-
class AssertionChecker extends Phase {
50-
def phaseName = "assertionChecker"
51-
def run(implicit ctx: Context): Unit = check(testPhase.virtualDir)
52-
}
53-
new Compiler {
54-
override protected def backendPhases: List[List[Phase]] =
55-
List(testPhase) ::
56-
List(new AssertionChecker) ::
57-
Nil
58-
}
44+
def initCtx = {
45+
val ctx0 = (new ContextBase).initialCtx.fresh
46+
val outputDir = new VirtualDirectory("<DottyBytecodeTest output>")
47+
ctx0.setSetting(ctx0.settings.classpath, Jars.dottyLib)
48+
ctx0.setProperty(ContextDoc, new ContextDocstrings)
49+
ctx0.setSetting(ctx0.settings.outputDir, outputDir)
5950
}
6051

61-
private def outPath(obj: Any) =
62-
"/genBCodeTest" + math.abs(obj.hashCode) + System.currentTimeMillis
63-
6452
/** Checks source code from raw string */
65-
def checkBCode(source: String)(assertion: Directory => Unit) = {
66-
val comp = bCodeCheckingComp(new TestGenBCode(outPath(source)))(assertion)
67-
comp.newRun.compile(source)
68-
}
53+
def checkBCode(source: String)(checkOutput: AbstractFile => Unit): Unit = {
54+
implicit val ctx: Context = initCtx
55+
56+
val compiler = new Compiler
57+
val run = compiler.newRun
58+
compiler.newRun.compile(source)
6959

70-
/** Checks actual _files_ referenced in `sources` list */
71-
def checkBCode(sources: List[String])(assertion: Directory => Unit) = {
72-
val comp = bCodeCheckingComp(new TestGenBCode(outPath(sources)))(assertion)
73-
comp.newRun.compile(sources)
60+
checkOutput(ctx.settings.outputDir.value)
7461
}
7562

7663
protected def loadClassNode(input: InputStream, skipDebugInfo: Boolean = true): ClassNode = {

compiler/test/dotty/tools/dotc/SettingsTests.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class SettingsTests {
1414
val options = Array("-d", "not_here")
1515
val reporter = Main.process(options)
1616
assertEquals(1, reporter.errorCount)
17-
assertEquals("'not_here' does not exist or is not a directory", reporter.allErrors.head.message)
17+
assertEquals("'not_here' does not exist or is not a directory or .jar file", reporter.allErrors.head.message)
1818
}
1919

2020
@Test def jarOutput: Unit = {

compiler/test/dotty/tools/dotc/SimplifyTests.scala

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,9 @@ class SimplifyPosTests extends SimplifyTests(optimise = true)
1111
class SimplifyNegTests extends SimplifyTests(optimise = false)
1212

1313
abstract class SimplifyTests(val optimise: Boolean) extends DottyBytecodeTest {
14-
override protected def initializeCtx(c: FreshContext): Unit = {
15-
super.initializeCtx(c)
16-
if (optimise) {
17-
val flags = Array("-optimise") // :+ "-Xprint:simplify"
18-
val summary = CompilerCommand.distill(flags)(c)
19-
c.setSettings(summary.sstate)
20-
}
14+
override def initCtx = {
15+
val ctx0 = super.initCtx
16+
ctx0.setSetting(ctx0.settings.optimise, optimise)
2117
}
2218

2319
def check(source: String, expected: String, shared: String = ""): Unit = {

0 commit comments

Comments
 (0)