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 .*
@@ -26,7 +26,6 @@ import scala.language.unsafeNulls
2626 * Until then, any changes to this file should be copied to `dotty.tools.io.FileWriters` as well.
2727 */
2828class ClassfileWriters (frontendAccess : PostProcessorFrontendAccess ) {
29- type NullableFile = AbstractFile | Null
3029 import frontendAccess .{compilerSettings , backendReporting }
3130
3231 sealed trait TastyWriter {
@@ -46,7 +45,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
4645 /**
4746 * Write a classfile
4847 */
49- def writeClass (name : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): NullableFile
48+ def writeClass (name : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile
5049
5150
5251 /**
@@ -91,7 +90,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
9190 }
9291
9392 private final class SingleClassWriter (underlying : FileWriter ) extends ClassfileWriter {
94- override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): NullableFile = {
93+ override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile = {
9594 underlying.writeFile(classRelativePath(className), bytes)
9695 }
9796 override def writeTasty (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): Unit = {
@@ -103,7 +102,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
103102 }
104103
105104 private final class DebugClassWriter (basic : ClassfileWriter , dump : FileWriter ) extends ClassfileWriter {
106- override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): NullableFile = {
105+ override def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile = {
107106 val outFile = basic.writeClass(className, bytes, sourceFile)
108107 dump.writeFile(classRelativePath(className), bytes)
109108 outFile
@@ -121,7 +120,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
121120 }
122121
123122 sealed trait FileWriter {
124- def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile
123+ def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile
125124 def close (): Unit
126125 }
127126
@@ -165,7 +164,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
165164
166165 lazy val crc = new CRC32
167166
168- override def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile = this .synchronized {
167+ override def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile = this .synchronized {
169168 val entry = new ZipEntry (relativePath)
170169 if (storeOnly) {
171170 // When using compression method `STORED`, the ZIP spec requires the CRC and compressed/
@@ -182,7 +181,13 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
182181 jarWriter.putNextEntry(entry)
183182 try jarWriter.write(bytes, 0 , bytes.length)
184183 finally jarWriter.flush()
185- null
184+ // important detail here, even on Windows, Zinc expects the separator within the jar
185+ // to be the system default, (even if in the actual jar file the entry always uses '/').
186+ // see https://github.com/sbt/zinc/blob/dcddc1f9cfe542d738582c43f4840e17c053ce81/internal/compiler-bridge/src/main/scala/xsbt/JarUtils.scala#L47
187+ val pathInJar =
188+ if File .separatorChar == '/' then relativePath
189+ else relativePath.replace('/' , File .separatorChar)
190+ PlainFile .toPlainFile(Paths .get(s " ${file.absolutePath}! $pathInJar" ))
186191 }
187192
188193 override def close (): Unit = this .synchronized (jarWriter.close())
@@ -230,7 +235,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
230235 private val fastOpenOptions = util.EnumSet .of(StandardOpenOption .CREATE_NEW , StandardOpenOption .WRITE )
231236 private val fallbackOpenOptions = util.EnumSet .of(StandardOpenOption .CREATE , StandardOpenOption .WRITE , StandardOpenOption .TRUNCATE_EXISTING )
232237
233- override def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile = {
238+ override def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile = {
234239 val path = base.resolve(relativePath)
235240 try {
236241 ensureDirForPath(base, path)
@@ -279,7 +284,7 @@ class ClassfileWriters(frontendAccess: PostProcessorFrontendAccess) {
279284 finally out.close()
280285 }
281286
282- override def writeFile (relativePath : String , bytes : Array [Byte ]): NullableFile = {
287+ override def writeFile (relativePath : String , bytes : Array [Byte ]): AbstractFile = {
283288 val outFile = getFile(base, relativePath)
284289 writeBytes(outFile, bytes)
285290 outFile
0 commit comments