@@ -12,6 +12,8 @@ import scala.annotation.internal.sharable
1212import dotty .tools .dotc .util .ClasspathFromClassloader
1313import dotty .tools .runner .ObjectRunner
1414import dotty .tools .dotc .config .Properties .envOrNone
15+ import java .util .jar ._
16+ import java .util .jar .Attributes .Name
1517
1618enum ExecuteMode :
1719 case Guess
@@ -31,6 +33,7 @@ case class Settings(
3133 targetScript : String = " " ,
3234 save : Boolean = false ,
3335 modeShouldBeRun : Boolean = false ,
36+ compiler : Boolean = false ,
3437) {
3538 def withExecuteMode (em : ExecuteMode ): Settings = this .executeMode match
3639 case ExecuteMode .Guess =>
@@ -65,6 +68,9 @@ case class Settings(
6568
6669 def withModeShouldBeRun : Settings =
6770 this .copy(modeShouldBeRun = true )
71+
72+ def withCompiler : Settings =
73+ this .copy(compiler = true )
6874}
6975
7076object MainGenericRunner {
@@ -97,6 +103,8 @@ object MainGenericRunner {
97103 )
98104 case " -save" :: tail =>
99105 process(tail, settings.withSave)
106+ case " -with-compiler" :: tail =>
107+ process(tail, settings.withCompiler)
100108 case (o @ javaOption(striped)) :: tail =>
101109 process(tail, settings.withJavaArgs(striped).withScalaArgs(o))
102110 case (o @ scalaOption(_* )) :: tail =>
@@ -128,8 +136,34 @@ object MainGenericRunner {
128136 repl.Main .main(properArgs.toArray)
129137 case ExecuteMode .Run =>
130138 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)
133167 case ExecuteMode .Script =>
134168 val properArgs =
135169 List (" -classpath" , settings.classPath.mkString(classpathSeparator)).filter(Function .const(settings.classPath.nonEmpty))
0 commit comments