-
Notifications
You must be signed in to change notification settings - Fork 315
/
ExtendedScalaMainClass.scala
100 lines (90 loc) 路 3.2 KB
/
ExtendedScalaMainClass.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package scala.meta.internal.metals.debug
import java.io.File
import scala.util.Properties
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.io.AbsolutePath
import ch.epfl.scala.bsp4j.ScalaMainClass
import ch.epfl.scala.{bsp4j => b}
/**
* Wrapper around the bsp4j.ScalaMainClass to provide additional information which may be used by client.
*
* For backward compatibility reasons, it provides the same fields as the bsp4j.ScalaMainClass,
* so it's safe for older clients to work without any change:
* @param class the fully qualified name of the class
* @param arguments the arguments to pass to the main method
* @param jvmOptions the jvm options to pass to the jvm
* @param environmentVariables the environment variables to pass to the process
*
* However, it also provides an additional field:
* @param shellCommand which is the command to run in the shell to start the main class, it also
* allows client to distinguish between old, bsp4j.ScalaMainClass and new ExtendedScalaMainClass
* ---
* To sum up:
* - allow old clients to work without any change
* - allow new clients to use shellCommand to run the main class directly in e.g. terminal
*/
case class ExtendedScalaMainClass private (
`class`: String,
arguments: java.util.List[String],
jvmOptions: java.util.List[String],
environmentVariables: java.util.List[String],
shellCommand: String,
)
object ExtendedScalaMainClass {
private def createCommand(
javaHome: AbsolutePath,
classpath: List[String],
jvmOptions: List[String],
arguments: List[String],
mainClass: String,
): String = {
val jvmOptsString =
if (jvmOptions.nonEmpty) jvmOptions.mkString("\"", "\" \"", "\"") else ""
val classpathString = classpath.mkString(File.pathSeparator)
val argumentsString = arguments.mkString(" ")
// We need to add "" to account for whitespace and also escaped \ before "
val escapedJavaHome = javaHome.toNIO.getRoot().toString +
javaHome.toNIO
.iterator()
.asScala
.map(p => "\"" + p + "\"")
.mkString(File.separator)
val safeJavaHome =
if (Properties.isWin) escapedJavaHome.replace("""\"""", """\\"""")
else escapedJavaHome
s"$safeJavaHome $jvmOptsString -classpath \"$classpathString\" $mainClass $argumentsString"
}
def apply(
main: ScalaMainClass,
env: b.JvmEnvironmentItem,
javaHome: AbsolutePath,
): ExtendedScalaMainClass = {
val jvmOpts = (main.getJvmOptions().asScala ++ env
.getJvmOptions()
.asScala).distinct.toList
val jvmEnvVariables =
env
.getEnvironmentVariables()
.asScala
.map { case (key, value) =>
s"$key=$value"
}
.toList
val mainEnvVariables = Option(main.getEnvironmentVariables())
.map(_.asScala.toList)
.getOrElse(Nil)
ExtendedScalaMainClass(
main.getClassName(),
main.getArguments(),
jvmOpts.asJava,
(jvmEnvVariables ++ mainEnvVariables).asJava,
createCommand(
javaHome,
env.getClasspath().asScala.map(_.toAbsolutePath.toString).toList,
jvmOpts,
main.getArguments().asScala.toList,
main.getClassName(),
),
)
}
}