@@ -7,6 +7,7 @@ import dotty.tools.dotc.core.Phases.Phase
7
7
import dotty .tools .dotc .core .Names .TypeName
8
8
9
9
import scala .collection .mutable
10
+ import scala .collection .JavaConverters ._
10
11
import scala .tools .asm .{ClassVisitor , CustomAttr , FieldVisitor , MethodVisitor }
11
12
import scala .tools .nsc .backend .jvm ._
12
13
import dotty .tools .dotc
@@ -26,14 +27,15 @@ import Denotations._
26
27
import Phases ._
27
28
import java .lang .AssertionError
28
29
import 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 }
30
33
31
34
import scala .tools .asm
32
35
import scala .tools .asm .tree ._
33
36
import dotty .tools .dotc .util .{DotClass , Positions }
34
37
import tpd ._
35
38
import StdNames ._
36
-
37
39
import dotty .tools .io ._
38
40
39
41
class GenBCode extends Phase {
@@ -50,37 +52,53 @@ class GenBCode extends Phase {
50
52
def outputDir (implicit ctx : Context ): AbstractFile = {
51
53
val path = ctx.settings.outputDir.value
52
54
if (path.isDirectory) new PlainDirectory (Directory (path))
53
- else new PlainFile (path)
55
+ else jarOutput (path)
54
56
}
55
57
56
- private [this ] var classOutput : AbstractFile = _
57
-
58
58
def run (implicit ctx : Context ): Unit = {
59
59
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)
61
61
entryPoints.clear()
62
62
}
63
63
64
64
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)
79
97
}
80
98
}
81
99
}
82
100
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 {
84
102
85
103
var tree : Tree = _
86
104
0 commit comments