11package dotty .tools .backend .jvm
22
3- import java .io .{DataOutputStream , IOException , BufferedOutputStream , FileOutputStream }
3+ import java .io .{DataOutputStream , File , IOException , BufferedOutputStream , FileOutputStream }
44import java .nio .ByteBuffer
55import java .nio .channels .{ClosedByInterruptException , FileChannel }
66import java .nio .charset .StandardCharsets .UTF_8
@@ -12,7 +12,7 @@ import java.util.zip.{CRC32, Deflater, ZipEntry, ZipOutputStream}
1212
1313import dotty .tools .dotc .core .Contexts .*
1414import dotty .tools .dotc .core .Decorators .em
15- import dotty .tools .io .{AbstractFile , PlainFile }
15+ import dotty .tools .io .{AbstractFile , PlainFile , VirtualFile }
1616import dotty .tools .io .PlainFile .toPlainFile
1717import BTypes .InternalName
1818import scala .util .chaining ._
@@ -22,7 +22,6 @@ import scala.language.unsafeNulls
2222
2323
2424class ClassfileWriters (frontendAccess : PostProcessorFrontendAccess ) {
25- type NullableFile = AbstractFile | Null
2625 import frontendAccess .{compilerSettings , backendReporting }
2726
2827 sealed trait TastyWriter {
@@ -42,7 +41,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
4241 /**
4342 * Write a classfile
4443 */
45- def writeClass (name : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): NullableFile
44+ def writeClass (name : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile
4645
4746
4847 /**
@@ -87,7 +86,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
8786 }
8887
8988 private final class SingleClassWriter (underlying : FileWriter ) extends ClassfileWriter {
90- override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): NullableFile = {
89+ override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile = {
9190 underlying.writeFile(classRelativePath(className), bytes)
9291 }
9392 override def writeTasty (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): Unit = {
@@ -99,7 +98,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
9998 }
10099
101100 private final class DebugClassWriter (basic : ClassfileWriter , dump : FileWriter ) extends ClassfileWriter {
102- override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): NullableFile = {
101+ override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile = {
103102 val outFile = basic.writeClass(className, bytes, sourceFile)
104103 dump.writeFile(classRelativePath(className), bytes)
105104 outFile
@@ -117,7 +116,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
117116 }
118117
119118 sealed trait FileWriter {
120- def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile
119+ def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile
121120 def close (): Unit
122121 }
123122
@@ -161,7 +160,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
161160
162161 lazy val crc = new CRC32
163162
164- override def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile = this .synchronized {
163+ override def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile = this .synchronized {
165164 val entry = new ZipEntry (relativePath)
166165 if (storeOnly) {
167166 // When using compression method `STORED`, the ZIP spec requires the CRC and compressed/
@@ -178,7 +177,13 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
178177 jarWriter.putNextEntry(entry)
179178 try jarWriter.write(bytes, 0 , bytes.length)
180179 finally jarWriter.flush()
181- null
180+ // important detail here, even on Windows, Zinc expects the separator within the jar
181+ // to be the system default, (even if in the actual jar file the entry always uses '/').
182+ // see https://github.com/sbt/zinc/blob/dcddc1f9cfe542d738582c43f4840e17c053ce81/internal/compiler-bridge/src/main/scala/xsbt/JarUtils.scala#L47
183+ val pathInJar =
184+ if File .separatorChar == '/' then relativePath
185+ else relativePath.replace('/' , File .separatorChar)
186+ PlainFile .toPlainFile(Paths .get(s " ${file.absolutePath}! $pathInJar" ))
182187 }
183188
184189 override def close (): Unit = this .synchronized (jarWriter.close())
@@ -226,7 +231,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
226231 private val fastOpenOptions = util.EnumSet .of(StandardOpenOption .CREATE_NEW , StandardOpenOption .WRITE )
227232 private val fallbackOpenOptions = util.EnumSet .of(StandardOpenOption .CREATE , StandardOpenOption .WRITE , StandardOpenOption .TRUNCATE_EXISTING )
228233
229- override def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile = {
234+ override def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile = {
230235 val path = base.resolve(relativePath)
231236 try {
232237 ensureDirForPath(base, path)
@@ -275,7 +280,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
275280 finally out.close()
276281 }
277282
278- override def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile = {
283+ override def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile = {
279284 val outFile = getFile(base, relativePath)
280285 writeBytes(outFile, bytes)
281286 outFile
0 commit comments