@@ -7,6 +7,7 @@ import dotty.tools.dotc.core.Phases.Phase
77import dotty .tools .dotc .core .Names .TypeName
88
99import scala .collection .mutable
10+ import scala .collection .JavaConverters ._
1011import scala .tools .asm .{ClassVisitor , CustomAttr , FieldVisitor , MethodVisitor }
1112import scala .tools .nsc .backend .jvm ._
1213import dotty .tools .dotc
@@ -26,14 +27,15 @@ import Denotations._
2627import Phases ._
2728import java .lang .AssertionError
2829import java .io .{DataOutputStream , File => JFile }
29- import dotty .tools .io .{Jar , File , Directory }
30+ import java .nio .file .{Files , FileSystem , FileSystems , Path => JPath }
31+
32+ import dotty .tools .io .{Directory , File , Jar }
3033
3134import scala .tools .asm
3235import scala .tools .asm .tree ._
3336import dotty .tools .dotc .util .{DotClass , Positions }
3437import tpd ._
3538import StdNames ._
36-
3739import dotty .tools .io ._
3840
3941class GenBCode extends Phase {
@@ -50,37 +52,53 @@ class GenBCode extends Phase {
5052 def outputDir (implicit ctx : Context ): AbstractFile = {
5153 val path = ctx.settings.outputDir.value
5254 if (path.isDirectory) new PlainDirectory (Directory (path))
53- else new PlainFile (path)
55+ else jarOutput (path)
5456 }
5557
56- private [this ] var classOutput : AbstractFile = _
57-
5858 def run (implicit ctx : Context ): Unit = {
5959 new GenBCodePipeline (entryPoints.toList,
60- new DottyBackendInterface (classOutput , superCallsMap.toMap)(ctx))(ctx).run(ctx.compilationUnit.tpdTree)
60+ new DottyBackendInterface (outputDir , superCallsMap.toMap)(ctx))(ctx).run(ctx.compilationUnit.tpdTree)
6161 entryPoints.clear()
6262 }
6363
6464 override def runOn (units : List [CompilationUnit ])(implicit ctx : Context ) = {
65- val output = outputDir
66- if (output.isDirectory) {
67- classOutput = output
68- val res = super .runOn(units)
69- classOutput = null
70- res
71- } else {
72- assert(output.hasExtension(" jar" ))
73- classOutput = new PlainDirectory (Path (Path (output.file).parent + " /tmp-jar-" + System .currentTimeMillis().toHexString).createDirectory())
74- val res = super .runOn(units)
75- Jar .create(new File (ctx.settings.outputDir.value.jfile), new Directory (classOutput.file), mainClass = " " )
76- classOutput.delete()
77- classOutput = null
78- res
65+ try super .runOn(units)
66+ finally if (jarFs ne null ) {
67+ try { jarFs.close() } catch { case _ : Throwable => }
68+ jarFs = null
69+ }
70+ }
71+
72+ private [this ] var jarFs : java.nio.file.FileSystem = _
73+ private def jarOutput (path : Path ) = {
74+ assert(path.extension == " jar" )
75+
76+ path.delete()
77+
78+ val env = Map (" create" -> " true" ).asJava
79+ val jar = java.net.URI .create(" jar:file:" + path.toAbsolute.path)
80+ jarFs = java.nio.file.FileSystems .newFileSystem(jar, env)
81+
82+ new JarFilePath (jarFs, jarFs.getRootDirectories.iterator().next())
83+ }
84+
85+ private class JarFilePath (jarFs : FileSystem , path : JPath ) extends PlainDirectory (new Directory (path)) {
86+ override def name = " <jar-file>"
87+ override def file = throw new UnsupportedOperationException
88+ override def fileNamed (name : String ): AbstractFile = new PlainNioFile (pathTo(name))
89+ override def subdirectoryNamed (name : String ): AbstractFile = {
90+ val subPath = pathTo(name)
91+ if (! Files .exists(subPath)) Files .createDirectory(subPath)
92+ new JarFilePath (jarFs, subPath)
93+ }
94+ private def pathTo (name : String ) = {
95+ val absolutePath = if (path.toString == " /" ) name else path.resolve(name).toString
96+ jarFs.getPath(absolutePath)
7997 }
8098 }
8199}
82100
83- class GenBCodePipeline (val entryPoints : List [Symbol ], val int : DottyBackendInterface )(implicit val ctx : Context ) extends BCodeSyncAndTry {
101+ class GenBCodePipeline (val entryPoints : List [Symbol ], val int : DottyBackendInterface )(implicit val ctx : Context ) extends BCodeSyncAndTry {
84102
85103 var tree : Tree = _
86104
0 commit comments