6
6
package scala .tools .nsc
7
7
package backend .jvm
8
8
9
- import java .io .{DataOutputStream , FileOutputStream , IOException , File => JFile }
9
+ import java .io .{DataOutputStream , FileOutputStream , File => JFile }
10
10
import java .nio .ByteBuffer
11
11
import java .nio .file .{StandardOpenOption , Files => JNFiles , Path => JNPath }
12
- import java .nio .file .attribute .{FileAttribute => JNFileAttribute }
13
12
import java .util
14
13
15
14
import scala .tools .nsc .io ._
16
15
import java .util .jar .Attributes .Name
17
16
import scala .language .postfixOps
18
17
19
18
object OutputDirectories {
20
-
21
- def apply (file: AbstractFile ) : OutputDirectories = {
22
- require (file.isDirectory)
19
+ def apply (file : AbstractFile ): OutputDirectories = {
20
+ require(file.isDirectory)
23
21
if (file.file ne null ) new PathDirInfo (file.file.toPath)
24
22
else new AbstractFileDirInfo (file)
25
23
}
26
24
27
- private class PathDirInfo (val base : JNPath ) extends OutputDirectories {
28
- // should be strict, when we fix duplicate file names
29
- val optsStrict = util.EnumSet .of(StandardOpenOption .CREATE_NEW , StandardOpenOption .WRITE , StandardOpenOption .TRUNCATE_EXISTING )
30
- val optsLax = util.EnumSet .of(StandardOpenOption .CREATE , StandardOpenOption .WRITE , StandardOpenOption .TRUNCATE_EXISTING )
31
- val noAttr = Array [JNFileAttribute [_]]()
25
+ private val openOpts = util.EnumSet .of(StandardOpenOption .CREATE , StandardOpenOption .WRITE , StandardOpenOption .TRUNCATE_EXISTING )
32
26
33
- class PathFile (path: JNPath ) extends OutputFile {
27
+ private class PathDirInfo (base : JNPath ) extends OutputDirectories {
28
+ class PathFile (path : JNPath ) extends OutputFile {
34
29
override def writeFile (bytes : Array [Byte ]): Unit = {
35
-
36
- val channel = path.getFileSystem.provider.newByteChannel(path, optsLax, noAttr : _* )
30
+ val channel = path.getFileSystem.provider.newByteChannel(path, openOpts)
37
31
val bb = ByteBuffer .wrap(bytes)
38
-
39
32
try do channel.write(bb) while (bb.remaining() > 0 )
40
33
finally channel.close()
41
-
42
34
}
43
35
}
44
- class PathDir (path: String ) extends OutputDirectory {
36
+
37
+ class PathDir (path : String ) extends OutputDirectory {
45
38
private lazy val dir = JNFiles .createDirectories(base.resolve(path))
46
39
override def file (name : String ): OutputFile = new PathFile (dir.resolve(name))
47
40
}
41
+
48
42
private val dirs = new collection.concurrent.TrieMap [String , PathDir ]()
49
- def directory (path: String ): OutputDirectory = {
43
+
44
+ def directory (path : String ): OutputDirectory = {
50
45
dirs.getOrElseUpdate(path, new PathDir (path))
51
46
}
52
- lazy val root : OutputDirectory = new PathDir ( " . " )
53
- val caseInsensitive = base.resolve( " a " ) == base.resolve( " A " )
47
+
48
+ lazy val root : OutputDirectory = new PathDir ( " . " )
54
49
}
55
- private class AbstractFileDirInfo (val base : AbstractFile ) extends OutputDirectories {
56
- private class SimpleFile (outfile: AbstractFile ) extends OutputFile {
50
+
51
+ private class AbstractFileDirInfo (val base : AbstractFile ) extends OutputDirectories {
52
+ private class SimpleFile (outfile : AbstractFile ) extends OutputFile {
57
53
override def writeFile (bytes : Array [Byte ]): Unit = {
58
54
val outstream = outfile.output
59
55
try outstream.write(bytes, 0 , bytes.length)
60
56
finally outstream.close()
61
57
}
62
58
}
63
- private class SimpleDir (file: AbstractFile ) extends OutputDirectory {
59
+
60
+ private class SimpleDir (file : AbstractFile ) extends OutputDirectory {
64
61
override def file (name : String ): OutputFile = new SimpleFile (file.fileNamed(name))
65
62
}
66
- val root : OutputDirectory = new SimpleDir (base)
67
- def directory (path: String ): OutputDirectory = {
63
+
64
+ def directory (path : String ): OutputDirectory = {
68
65
val file = path.split(" /" ).foldLeft(base) {
69
66
case (parentDir, child) => parentDir.subdirectoryNamed(child)
70
67
}
71
68
new SimpleDir (file)
72
69
}
73
- val caseInsensitive = {
74
- if (base.file == null ) false
75
- else {
76
- val path = base.file.toPath
77
- path.resolve(" a" ) == path.resolve(" A" )
78
- }
79
- }
70
+
71
+ val root : OutputDirectory = new SimpleDir (base)
80
72
}
81
73
}
82
74
83
75
trait OutputDirectories {
84
- def directory (path: String ): OutputDirectory
76
+ def directory (path : String ): OutputDirectory
85
77
def root : OutputDirectory
86
- val caseInsensitive : Boolean
87
78
}
79
+
88
80
trait OutputDirectory {
89
- def file (name: String ): OutputFile
81
+ def file (name : String ): OutputFile
90
82
}
83
+
91
84
trait OutputFile {
92
- def writeFile (bytes: Array [Byte ])
85
+ def writeFile (bytes : Array [Byte ])
93
86
}
94
87
95
-
96
-
97
88
/** For the last mile: turning generated bytecode in memory into
98
89
* something you can use. Has implementations for writing to class
99
90
* files, jars, and disassembled/javap output.
@@ -102,20 +93,17 @@ trait BytecodeWriters {
102
93
val global : Global
103
94
import global ._
104
95
105
- def outputDirectory (sym : Symbol ): AbstractFile =
106
- settings.outputDirs outputDirFor enteringFlatten(sym.sourceFile)
107
-
108
96
/**
109
97
* @param clsName cls.getName
110
98
*/
111
- def getFile (known : OutputDirectories , clsName : String , suffix : String ): OutputFile = {
99
+ def getFile (outDirs : OutputDirectories , clsName : String , suffix : String ): OutputFile = {
112
100
val pathAndName = clsName.replace('.' , '/' )
113
101
val split = pathAndName.lastIndexOf('/' )
114
- if (split == - 1 ) known .root.file(clsName + suffix)
102
+ if (split == - 1 ) outDirs .root.file(clsName + suffix)
115
103
else {
116
104
val dirPath = pathAndName.substring(0 , split)
117
105
val filename = pathAndName.substring(split + 1 ) + suffix
118
- known .directory(dirPath).file(filename)
106
+ outDirs .directory(dirPath).file(filename)
119
107
}
120
108
}
121
109
0 commit comments