diff --git a/internal/util-core/src/main/scala/sbt/internal/util/Util.scala b/internal/util-core/src/main/scala/sbt/internal/util/Util.scala index 1ba2156f7..76647737b 100644 --- a/internal/util-core/src/main/scala/sbt/internal/util/Util.scala +++ b/internal/util-core/src/main/scala/sbt/internal/util/Util.scala @@ -8,11 +8,12 @@ package sbt.internal.util +import java.nio.file.{ Path, Paths } import java.util.Locale import scala.collection.concurrent.TrieMap -object Util { +object Util: def makeList[T](size: Int, value: T): List[T] = List.fill(size)(value) def separate[T, A, B](ps: Seq[T])(f: T => Either[A, B]): (Seq[A], Seq[B]) = { @@ -78,4 +79,11 @@ object Util { val cache = TrieMap.empty[A1, A2] x => cache.getOrElseUpdate(x, f(x)) } -} + + lazy val javaHome: Path = + sys.env.get("JAVA_HOME") match + case Some(home) => Paths.get(home) + case None => + if sys.props("java.home").endsWith("jre") then Paths.get(sys.props("java.home")).getParent() + else Paths.get(sys.props("java.home")) +end Util diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 89d02e61a..f5f57c957 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -9,7 +9,7 @@ package sbt import java.io.{ File, PrintWriter } -import java.nio.file.{ Files, Paths, Path => NioPath } +import java.nio.file.{ Files, Path => NioPath } import java.util.Optional import java.util.concurrent.TimeUnit import lmcoursier.CoursierDependencyResolution @@ -245,13 +245,12 @@ object Defaults extends BuildCommon { val base = app.baseDirectory.getCanonicalFile.toPath val boot = app.provider.scalaProvider.launcher.bootDirectory.toPath val ih = app.provider.scalaProvider.launcher.ivyHome.toPath - val javaHome = Paths.get(sys.props("java.home")) ListMap( "OUT" -> out, "BASE" -> base, "SBT_BOOT" -> boot, "IVY_HOME" -> ih, - "JAVA_HOME" -> javaHome + "JAVA_HOME" -> Util.javaHome, ) private[sbt] lazy val globalIvyCore: Seq[Setting[?]] = diff --git a/main/src/main/scala/sbt/internal/Load.scala b/main/src/main/scala/sbt/internal/Load.scala index 25d91b642..cb6232c03 100755 --- a/main/src/main/scala/sbt/internal/Load.scala +++ b/main/src/main/scala/sbt/internal/Load.scala @@ -33,7 +33,7 @@ import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFile } import xsbti.compile.{ ClasspathOptionsUtil, Compilers } import java.io.File import java.net.URI -import java.nio.file.{ Path, Paths } +import java.nio.file.Path import scala.annotation.tailrec import scala.collection.mutable import sbt.internal.util.Util @@ -71,7 +71,7 @@ private[sbt] object Load { val scalaProvider = app.provider.scalaProvider val launcher = scalaProvider.launcher val stagingDirectory = getStagingDirectory(state, globalBase).getCanonicalFile - val javaHome = Paths.get(sys.props("java.home")) + val javaHome = Util.javaHome val out = baseDirectory.toPath.resolve("target").resolve("out") val rootPaths = Map( "OUT" -> out, diff --git a/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala b/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala index 65f9fe120..306e17d92 100644 --- a/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala +++ b/protocol/src/main/scala/sbt/internal/bsp/BuildServerConnection.scala @@ -9,6 +9,7 @@ package sbt.internal.bsp import sbt.internal.bsp.codec.JsonProtocol.BspConnectionDetailsFormat +import sbt.internal.util.Util import sbt.io.IO import sjsonnew.support.scalajson.unsafe.{ CompactPrinter, Converter } @@ -25,7 +26,7 @@ object BuildServerConnection { private[sbt] def writeConnectionFile(sbtVersion: String, baseDir: File): Unit = { val bspConnectionFile = new File(baseDir, ".bsp/sbt.json") - val javaHome = System.getProperty("java.home") + val javaHome = Util.javaHome val classPath = System.getProperty("java.class.path") val sbtScript = Option(System.getProperty("sbt.script")) diff --git a/server-test/src/test/scala/testpkg/BuildServerTest.scala b/server-test/src/test/scala/testpkg/BuildServerTest.scala index bdb06fa22..3b6913256 100644 --- a/server-test/src/test/scala/testpkg/BuildServerTest.scala +++ b/server-test/src/test/scala/testpkg/BuildServerTest.scala @@ -234,7 +234,6 @@ class BuildServerTest extends AbstractServerTest { val buildTarget = buildTargetUri("javaProj", "Compile") compile(buildTarget) - assertMessage( "build/publishDiagnostics", "Hello.java", @@ -257,16 +256,17 @@ class BuildServerTest extends AbstractServerTest { val testFile = new File(svr.baseDirectory, s"java-proj/src/main/java/example/Hello.java") val otherBuildFile = new File(svr.baseDirectory, "force-java-out-of-process-compiler.sbt") - // Setting `javaHome` will force SBT to shell out to an external Java compiler instead + // Setting `javaHome` will force sbt to shell out to an external Java compiler instead // of using the local compilation service offered by the JVM running this SBT instance. IO.write( otherBuildFile, """ + |def jdk: File = sbt.internal.Util.javaHome.toFile() |lazy val javaProj = project | .in(file("java-proj")) | .settings( | javacOptions += "-Xlint:all", - | javaHome := Some(file(System.getProperty("java.home"))) + | javaHome := Some(jdk) | ) |""".stripMargin ) @@ -278,16 +278,17 @@ class BuildServerTest extends AbstractServerTest { "build/publishDiagnostics", "Hello.java", """"severity":2""", - """found raw type: List""" - )(message = "should send publishDiagnostics with severity 2 for Hello.java") + """found raw type""" + )(message = "should send publishDiagnostics with severity 2 for Hello.java", debug = false) assertMessage( "build/publishDiagnostics", "Hello.java", """"severity":1""", - """incompatible types: int cannot be converted to String""" + """incompatible types: int cannot be converted""" )( - message = "should send publishDiagnostics with severity 1 for Hello.java" + message = "should send publishDiagnostics with severity 1 for Hello.java", + debug = true ) // Note the messages changed slightly in both cases. That's interesting… @@ -690,9 +691,14 @@ class BuildServerTest extends AbstractServerTest { def assertion = svr.waitForString(duration) { msg => if (debug) println(msg) + if debug then + parts.foreach: p => + if msg.contains(p) then println(s"> $msg contains $p") + else () parts.forall(msg.contains) } - if (message.nonEmpty) assert(assertion, message) else assert(assertion) + if message.nonEmpty then assert(assertion, message) + else assert(assertion) } private def reloadWorkspace(): Int =