@@ -12,6 +12,8 @@ import scala.annotation.internal.sharable
12
12
import dotty .tools .dotc .util .ClasspathFromClassloader
13
13
import dotty .tools .runner .ObjectRunner
14
14
import dotty .tools .dotc .config .Properties .envOrNone
15
+ import java .util .jar ._
16
+ import java .util .jar .Attributes .Name
15
17
16
18
enum ExecuteMode :
17
19
case Guess
@@ -31,6 +33,7 @@ case class Settings(
31
33
targetScript : String = " " ,
32
34
save : Boolean = false ,
33
35
modeShouldBeRun : Boolean = false ,
36
+ compiler : Boolean = false ,
34
37
) {
35
38
def withExecuteMode (em : ExecuteMode ): Settings = this .executeMode match
36
39
case ExecuteMode .Guess =>
@@ -65,6 +68,9 @@ case class Settings(
65
68
66
69
def withModeShouldBeRun : Settings =
67
70
this .copy(modeShouldBeRun = true )
71
+
72
+ def withCompiler : Settings =
73
+ this .copy(compiler = true )
68
74
}
69
75
70
76
object MainGenericRunner {
@@ -97,6 +103,8 @@ object MainGenericRunner {
97
103
)
98
104
case " -save" :: tail =>
99
105
process(tail, settings.withSave)
106
+ case " -with-compiler" :: tail =>
107
+ process(tail, settings.withCompiler)
100
108
case (o @ javaOption(striped)) :: tail =>
101
109
process(tail, settings.withJavaArgs(striped).withScalaArgs(o))
102
110
case (o @ scalaOption(_* )) :: tail =>
@@ -128,8 +136,34 @@ object MainGenericRunner {
128
136
repl.Main .main(properArgs.toArray)
129
137
case ExecuteMode .Run =>
130
138
val scalaClasspath = ClasspathFromClassloader (Thread .currentThread().getContextClassLoader).split(classpathSeparator)
131
- val newClasspath = (settings.classPath ++ scalaClasspath :+ " ." ).map(File (_).toURI.toURL)
132
- errorFn(" " , ObjectRunner .runAndCatch(newClasspath, settings.residualArgs.head, settings.residualArgs.drop(1 )))
139
+
140
+ def removeCompiler (cp : Array [String ]) =
141
+ if (! settings.compiler) then // Let's remove compiler from the classpath
142
+ val compilerLibs = Seq (" scala3-compiler" , " scala3-interfaces" , " tasty-core" , " scala-asm" , " scala3-staging" , " scala3-tasty-inspector" )
143
+ cp.filterNot(c => compilerLibs.exists(c.contains))
144
+ else
145
+ cp
146
+ val newClasspath = (settings.classPath ++ removeCompiler(scalaClasspath) :+ " ." ).map(File (_).toURI.toURL)
147
+
148
+ val res = ObjectRunner .runAndCatch(newClasspath, settings.residualArgs.head, settings.residualArgs.drop(1 )).flatMap {
149
+ case ex : ClassNotFoundException if ex.getMessage == settings.residualArgs.head =>
150
+ val file = settings.residualArgs.head
151
+ def withJarInput [T ](f : JarInputStream => T ): T =
152
+ val in = new JarInputStream (java.io.FileInputStream (file))
153
+ try f(in)
154
+ finally in.close()
155
+ val manifest = withJarInput(s => Option (s.getManifest))
156
+ manifest match
157
+ case None => Some (IllegalArgumentException (s " Cannot find manifest in jar: $file" ))
158
+ case Some (f) =>
159
+ f.getMainAttributes.get(Name .MAIN_CLASS ) match
160
+ case mainClass : String =>
161
+ ObjectRunner .runAndCatch(newClasspath :+ File (file).toURI.toURL, mainClass, settings.residualArgs)
162
+ case _ =>
163
+ Some (IllegalArgumentException (s " No main class defined in manifest in jar: $file" ))
164
+ case ex => Some (ex)
165
+ }
166
+ errorFn(" " , res)
133
167
case ExecuteMode .Script =>
134
168
val properArgs =
135
169
List (" -classpath" , settings.classPath.mkString(classpathSeparator)).filter(Function .const(settings.classPath.nonEmpty))
0 commit comments