Skip to content

Commit

Permalink
bugfix: Use platform Java from BSP instead of metals one
Browse files Browse the repository at this point in the history
~~I am hesistant to add a test case, since that would require downloading separate JDK for the sake of one test~~

Decided to add test as the logic became a bit more complex.

Fixes #5780
  • Loading branch information
tgodzik committed Oct 24, 2023
1 parent 3bc135f commit 8d665b6
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 22 deletions.
21 changes: 16 additions & 5 deletions metals/src/main/scala/scala/meta/internal/metals/JavaBinary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,25 @@ object JavaBinary {
}
}

def allPossibleJavaBinaries(
javaHome: Option[String]
): List[AbsolutePath] = {
JdkSources
.defaultJavaHome(javaHome)
private def fromAbsolutePath(javaPath: Iterable[AbsolutePath]) = {
javaPath
.flatMap(home => List(home.resolve("bin"), home.resolve("bin/jre")))
.flatMap(bin => List("java", "java.exe").map(bin.resolve))
.withFilter(_.exists)
.flatMap(binary => List(binary.dealias, binary))
}

def javaBinaryFromPath(
javaHome: Option[String]
): Option[AbsolutePath] =
fromAbsolutePath(javaHome.map(_.toAbsolutePath)).headOption

def allPossibleJavaBinaries(
javaHome: Option[String]
): Iterable[AbsolutePath] = {
fromAbsolutePath(
JdkSources
.defaultJavaHome(javaHome)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import scala.meta.internal.metals.BuildTargets
import scala.meta.internal.metals.ClientCommands.StartDebugSession
import scala.meta.internal.metals.ClientCommands.StartRunSession
import scala.meta.internal.metals.ClientConfiguration
import scala.meta.internal.metals.JavaBinary
import scala.meta.internal.metals.JsonParser._
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.metals.TestUserInterfaceKind
Expand Down Expand Up @@ -293,13 +294,19 @@ final class RunTestCodeLens(
main: b.ScalaMainClass,
buildServerCanDebug: Boolean,
): List[l.Command] = {
val javaBinary = buildTargets
.scalaTarget(target)
.flatMap(scalaTarget =>
JavaBinary.javaBinaryFromPath(scalaTarget.jvmHome)
)
.orElse(userConfig().usedJavaBinary)
val (data, shellCommandAdded) = buildTargetClasses.jvmRunEnvironment
.get(target)
.zip(userConfig().usedJavaBinary) match {
.zip(javaBinary) match {
case None =>
(main.toJson, false)
case Some((env, javaHome)) =>
(ExtendedScalaMainClass(main, env, javaHome, workspace).toJson, true)
case Some((env, javaBinary)) =>
(ExtendedScalaMainClass(main, env, javaBinary, workspace).toJson, true)
}
val params = {
val dataKind = b.DebugSessionParamsDataKind.SCALA_MAIN_CLASS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import scala.meta.internal.metals.DebugDiscoveryParams
import scala.meta.internal.metals.DebugSession
import scala.meta.internal.metals.DebugUnresolvedMainClassParams
import scala.meta.internal.metals.DebugUnresolvedTestClassParams
import scala.meta.internal.metals.JavaBinary
import scala.meta.internal.metals.JsonParser._
import scala.meta.internal.metals.Messages
import scala.meta.internal.metals.Messages.UnresolvedDebugSessionParams
Expand Down Expand Up @@ -427,9 +428,15 @@ class DebugProvider(
if params.getDataKind == b.DebugSessionParamsDataKind.SCALA_MAIN_CLASS =>
json.as[b.ScalaMainClass] match {
case Success(main) if params.getTargets().size > 0 =>
val javaBinary = buildTargets
.scalaTarget(params.getTargets().get(0))
.flatMap(scalaTarget =>
JavaBinary.javaBinaryFromPath(scalaTarget.jvmHome)
)
.orElse(userConfig().usedJavaBinary)
val updatedData = buildTargetClasses.jvmRunEnvironment
.get(params.getTargets().get(0))
.zip(userConfig().usedJavaBinary) match {
.zip(javaBinary) match {
case None =>
main.toJson
case Some((env, javaHome)) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ case class ExtendedScalaMainClass private (
object ExtendedScalaMainClass {

private def createCommand(
javaHome: AbsolutePath,
javaBinary: AbsolutePath,
classpath: List[String],
jvmOptions: List[String],
arguments: List[String],
Expand All @@ -61,16 +61,16 @@ object ExtendedScalaMainClass {
)
val argumentsString = arguments.mkString(" ")
// We need to add "" to account for whitespace and also escaped \ before "
val escapedJavaHome = javaHome.toNIO.getRoot().toString +
javaHome.toNIO
val escapedJavaHome = javaBinary.toNIO.getRoot().toString +
javaBinary.toNIO
.iterator()
.asScala
.map(p => s""""$p"""")
.mkString(File.separator)
val safeJavaHome =
val safeJavaBinary =
if (Properties.isWin) escapedJavaHome.replace("""\"""", """\\"""")
else escapedJavaHome
s"$safeJavaHome $jvmOptsString -classpath \"$classpathString\" $mainClass $argumentsString"
s"$safeJavaBinary $jvmOptsString -classpath \"$classpathString\" $mainClass $argumentsString"
}

/**
Expand Down Expand Up @@ -126,7 +126,7 @@ object ExtendedScalaMainClass {
def apply(
main: ScalaMainClass,
env: b.JvmEnvironmentItem,
javaHome: AbsolutePath,
javaBinary: AbsolutePath,
workspace: AbsolutePath,
): ExtendedScalaMainClass = {
val jvmOpts = (main.getJvmOptions().asScala ++ env
Expand All @@ -152,7 +152,7 @@ object ExtendedScalaMainClass {
jvmOpts.asJava,
(jvmEnvVariables ++ mainEnvVariables).asJava,
createCommand(
javaHome,
javaBinary,
env.getClasspath().asScala.map(_.toAbsolutePath.toString).toList,
jvmOpts,
main.getArguments().asScala.toList,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class MillServerCodeLensSuite
lenses <- server.codeLenses("MillMinimal/src/Main.scala")
_ = assert(lenses.size > 0, "No lenses were generated!")
command = lenses.head.getCommand()
_ = assertEquals(runFromCommand(command), Some("Hello java!"))
_ = assertEquals(runFromCommand(command, None), Some("Hello java!"))
} yield ()
}
}
24 changes: 20 additions & 4 deletions tests/unit/src/main/scala/tests/BaseCodeLensLspSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ abstract class BaseCodeLensLspSuite(
initializer: BuildServerInitializer = QuickBuildInitializer,
) extends BaseLspSuite(name, initializer) {

protected def runFromCommand(cmd: Command): Option[String] = {
protected def runFromCommand(
cmd: Command,
javaHome: Option[String],
): Option[String] = {
cmd.getArguments().asScala.toList match {
case (params: DebugSessionParams) :: _ =>
params.getData() match {
Expand All @@ -43,6 +46,12 @@ abstract class BaseCodeLensLspSuite(
.replace("ProgramFiles", "Program Files")
.replace("runshellcommand", "run shell command")
)
javaHome.foreach { home =>
assert(
cmd(0).startsWith(home),
s"${cmd(0)} didn't start with java home:\n $home ",
)
}
ShellRunner
.runSync(cmd.toList, workspace, redirectErrorOutput = false)
.map(_.trim())
Expand All @@ -60,14 +69,21 @@ abstract class BaseCodeLensLspSuite(
}
}

protected def testRunShellCommand(name: String): Unit =
protected def testRunShellCommand(
name: String,
javaHome: Option[String] = None,
): Unit =
test(name) {
def javaHomeString(javaHome: String) = {
val escaped = javaHome.replace("\\", "\\\\")
s"\"platformJavaHome\": \"$escaped\""
}
cleanWorkspace()
for {
_ <- initialize(
s"""|/metals.json
|{
| "a": {}
| "a": { ${javaHome.map(javaHomeString).getOrElse("")} }
|}
|/a/src/main/scala/a/Main.scala
|package foo
Expand All @@ -83,7 +99,7 @@ abstract class BaseCodeLensLspSuite(
lenses <- server.codeLenses("a/src/main/scala/a/Main.scala")
_ = assert(lenses.size > 0, "No lenses were generated!")
command = lenses.head.getCommand()
_ = assertEquals(runFromCommand(command), Some("Hello java!"))
_ = assertEquals(runFromCommand(command, javaHome), Some("Hello java!"))
} yield ()
}

Expand Down
6 changes: 5 additions & 1 deletion tests/unit/src/main/scala/tests/QuickBuild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ case class QuickBuild(
additionalSources: Array[String],
sbtVersion: String,
sbtAutoImports: Array[String],
platformJavaHome: String,
) {
def withId(id: String): QuickBuild =
QuickBuild(
Expand All @@ -84,6 +85,7 @@ case class QuickBuild(
orEmpty(additionalSources),
sbtVersion,
orEmpty(sbtAutoImports),
platformJavaHome,
)
private def orEmpty(array: Array[String]): Array[String] =
if (array == null) new Array(0) else array
Expand Down Expand Up @@ -203,7 +205,9 @@ case class QuickBuild(
artifacts,
)
}
val javaHome = Option(Properties.jdkHome).map(Paths.get(_))
val javaHome = Option(platformJavaHome)
.map(Paths.get(_))
.orElse(Option(Properties.jdkHome).map(Paths.get(_)))
val tags = if (isTest) Tag.Test :: Nil else Nil

val scalaCompiler =
Expand Down
6 changes: 6 additions & 0 deletions tests/unit/src/test/scala/tests/CodeLensLspSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tests

import scala.meta.internal.metals.UserConfiguration

import coursierapi.JvmManager

class CodeLensLspSuite extends BaseCodeLensLspSuite("codeLenses") {
override protected val changeSpacesToDash = false
override def userConfig: UserConfiguration =
Expand Down Expand Up @@ -305,6 +307,10 @@ class CodeLensLspSuite extends BaseCodeLensLspSuite("codeLenses") {
|""".stripMargin
)

testRunShellCommand(
"run-shell-command-old-java",
Some(JvmManager.create().get("8").toString()),
)
testRunShellCommand("run-shell-command")
testRunShellCommand("run shell command")

Expand Down

0 comments on commit 8d665b6

Please sign in to comment.