@@ -20,31 +20,34 @@ class ClassfileWriter(frontendAccess: PostProcessorFrontendAccess) {
20
20
private val dumpOutputDir : AbstractFile = getDirectoryOrNull(compilerSettings.dumpClassesDirectory)
21
21
22
22
// if non-null, classfiles are written to a jar instead of the output directory
23
- private val jarWriter : JarWriter =
24
- val f = compilerSettings.outputDirectory
25
- if f.hasExtension(" jar" ) then
26
- // If no main class was specified, see if there's only one
27
- // entry point among the classes going into the jar.
28
- val mainClass = compilerSettings.mainClass match {
29
- case c @ Some (m) =>
30
- backendReporting.log(s " Main-Class was specified: ${m}" )
31
- c
32
- case None => frontendAccess.getEntryPoints match {
33
- case Nil =>
34
- backendReporting.log(" No Main-Class designated or discovered." )
35
- None
23
+ private val jarWriter : JarWriter | Null = compilerSettings.outputDirectory match {
24
+ case jar : JarArchive =>
25
+ val mainClass = compilerSettings.mainClass.orElse {
26
+ // If no main class was specified, see if there's only one
27
+ // entry point among the classes going into the jar.
28
+ frontendAccess.getEntryPoints match {
36
29
case name :: Nil =>
37
30
backendReporting.log(s " Unique entry point: setting Main-Class to $name" )
38
31
Some (name)
39
32
case names =>
40
- backendReporting.log(s " No Main-Class due to multiple entry points: \n ${names.mkString(" \n " )}" )
33
+ if names.isEmpty then backendReporting.warning(" No Main-Class designated or discovered." )
34
+ else backendReporting.warning(s " No Main-Class due to multiple entry points: \n ${names.mkString(" \n " )}" )
41
35
None
42
36
}
43
37
}
44
-
45
- val jarMainAttrs = mainClass.map(c => Name .MAIN_CLASS -> c).toList
46
- new Jar (f.file).jarWriter(jarMainAttrs : _* )
47
- else null
38
+ jar.underlyingSource.map{ source =>
39
+ if jar.isEmpty then
40
+ val jarMainAttrs = mainClass.map(Name .MAIN_CLASS -> _).toList
41
+ new Jar (source.file).jarWriter(jarMainAttrs : _* )
42
+ else
43
+ // Writing to non-empty JAR might be an undefined behaviour, e.g. in case if other files where
44
+ // created using `AbstractFile.bufferedOutputStream`instead of JarWritter
45
+ backendReporting.warning(s " Tried to write to non-empty JAR: $source" )
46
+ null
47
+ }.orNull
48
+
49
+ case _ => null
50
+ }
48
51
49
52
private def getDirectoryOrNull (dir : Option [String ]): AbstractFile =
50
53
dir.map(d => new PlainDirectory (Directory (d))).orNull
@@ -88,20 +91,9 @@ class ClassfileWriter(frontendAccess: PostProcessorFrontendAccess) {
88
91
}
89
92
}
90
93
91
- def write (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile | Null = try {
94
+ def writeClass (className : InternalName , bytes : Array [Byte ], sourceFile : AbstractFile ): AbstractFile | Null = try {
92
95
// val writeStart = Statistics.startTimer(BackendStats.bcodeWriteTimer)
93
- val outFile = if (jarWriter == null ) {
94
- val outFolder = compilerSettings.outputDirectory
95
- val outFile = getFile(outFolder, className, " .class" )
96
- writeBytes(outFile, bytes)
97
- outFile
98
- } else {
99
- val path = className + " .class"
100
- val out = jarWriter.newOutputStream(path)
101
- try out.write(bytes, 0 , bytes.length)
102
- finally out.flush()
103
- null
104
- }
96
+ val outFile = writeToJarOrFile(className, bytes, " .class" )
105
97
// Statistics.stopTimer(BackendStats.bcodeWriteTimer, writeStart)
106
98
107
99
if (dumpOutputDir != null ) {
@@ -111,22 +103,34 @@ class ClassfileWriter(frontendAccess: PostProcessorFrontendAccess) {
111
103
outFile
112
104
} catch {
113
105
case e : FileConflictException =>
114
- backendReporting.error(s " error writing $className: ${e.getMessage}" , NoSourcePosition )
106
+ backendReporting.error(s " error writing $className: ${e.getMessage}" )
115
107
null
116
108
case e : java.nio.file.FileSystemException =>
117
109
if compilerSettings.debug then e.printStackTrace()
118
- backendReporting.error(s " error writing $className: ${e.getClass.getName} ${e.getMessage}" , NoSourcePosition )
110
+ backendReporting.error(s " error writing $className: ${e.getClass.getName} ${e.getMessage}" )
119
111
null
120
112
}
121
113
122
- def writeTasty (className : InternalName , bytes : Array [Byte ]): Unit =
123
- val outFolder = compilerSettings.outputDirectory
124
- val outFile = getFile(outFolder, className, " .tasty" )
125
- try writeBytes(outFile, bytes)
126
- catch case ex : ClosedByInterruptException =>
127
- try outFile.delete() // don't leave an empty or half-written tastyfile around after an interrupt
128
- catch case _ : Throwable => ()
129
- finally throw ex
114
+ def writeTasty (className : InternalName , bytes : Array [Byte ]): Unit =
115
+ writeToJarOrFile(className, bytes, " .tasty" )
116
+
117
+ private def writeToJarOrFile (className : InternalName , bytes : Array [Byte ], suffix : String ): AbstractFile | Null = {
118
+ if jarWriter == null then
119
+ val outFolder = compilerSettings.outputDirectory
120
+ val outFile = getFile(outFolder, className, suffix)
121
+ try writeBytes(outFile, bytes)
122
+ catch case ex : ClosedByInterruptException =>
123
+ try outFile.delete() // don't leave an empty or half-written files around after an interrupt
124
+ catch case _ : Throwable => ()
125
+ finally throw ex
126
+ outFile
127
+ else
128
+ val path = className + suffix
129
+ val out = jarWriter.newOutputStream(path)
130
+ try out.write(bytes, 0 , bytes.length)
131
+ finally out.flush()
132
+ null
133
+ }
130
134
131
135
def close (): Unit = {
132
136
if (jarWriter != null ) jarWriter.close()
0 commit comments