diff --git a/metals/src/main/scala/scala/meta/internal/metals/BuildTargets.scala b/metals/src/main/scala/scala/meta/internal/metals/BuildTargets.scala index 8f3ba230663..a3a674c1f75 100644 --- a/metals/src/main/scala/scala/meta/internal/metals/BuildTargets.scala +++ b/metals/src/main/scala/scala/meta/internal/metals/BuildTargets.scala @@ -7,6 +7,7 @@ import ch.epfl.scala.bsp4j.BuildTarget import ch.epfl.scala.bsp4j.BuildTargetIdentifier import ch.epfl.scala.bsp4j.ScalacOptionsItem import ch.epfl.scala.bsp4j.ScalacOptionsResult +import ch.epfl.scala.bsp4j.ScalaBuildTarget import ch.epfl.scala.bsp4j.WorkspaceBuildTargetsResult import java.util.concurrent.ConcurrentLinkedQueue import scala.annotation.tailrec @@ -175,6 +176,10 @@ final class BuildTargets() { buildTarget: BuildTargetIdentifier ): Option[BuildTarget] = buildTargetInfo.get(buildTarget) + def scalaInfo( + buildTarget: BuildTargetIdentifier + ): Option[ScalaBuildTarget] = + info(buildTarget).flatMap(_.asScalaBuildTarget) def scalacOptions( buildTarget: BuildTargetIdentifier @@ -188,11 +193,25 @@ final class BuildTargets() { source: AbsolutePath ): Option[BuildTargetIdentifier] = { val buildTargets = sourceBuildTargets(source) - buildTargets // prioritize JVM targets over JS/Native - .find(x => scalacOptions(x).exists(_.isJVM)) - .orElse(buildTargets.headOption) - .orElse(tables.flatMap(_.dependencySources.getBuildTarget(source))) - .orElse(inferBuildTarget(source)) + if (buildTargets.isEmpty) { + tables + .flatMap(_.dependencySources.getBuildTarget(source)) + .orElse(inferBuildTarget(source)) + } else { + Some(buildTargets.maxBy { t => + var score = 1 + + val isSupportedScalaVersion = scalaInfo(t).exists( + t => ScalaVersions.isSupportedScalaVersion(t.getScalaVersion()) + ) + if (isSupportedScalaVersion) score <<= 2 + + val isJVM = scalacOptions(t).exists(_.isJVM) + if (isJVM) score <<= 1 + + score + }) + } } /** diff --git a/tests/unit/src/main/scala/tests/QuickBuild.scala b/tests/unit/src/main/scala/tests/QuickBuild.scala index 0f81227c4d0..4e4cc570097 100644 --- a/tests/unit/src/main/scala/tests/QuickBuild.scala +++ b/tests/unit/src/main/scala/tests/QuickBuild.scala @@ -15,6 +15,7 @@ import java.nio.file.Paths import java.security.MessageDigest import scala.meta.internal.io.FileIO import scala.meta.internal.metals.MetalsEnrichments._ +import scala.meta.internal.metals.ScalaVersions import scala.meta.internal.metals.Time import scala.meta.internal.metals.Timer import scala.meta.internal.metals.{BuildInfo => V} @@ -89,12 +90,14 @@ case class QuickBuild( .resolve(s"scala-$binaryVersion") .resolve(s"${testPrefix}classes") } - val sources = (List( + val extraSources = + additionalSources.map(relpath => workspace.resolve(relpath).toNIO).toList + val sources = extraSources ::: List( "src/main/java", "src/main/scala", s"src/main/scala-$binaryVersion", s"src/main/scala-$binaryVersion" - ) ++ additionalSources).map(relpath => baseDirectory.resolve(relpath)) + ).map(relpath => baseDirectory.resolve(relpath)) val allDependencies = Array( s"org.scala-lang:scala-library:$scalaVersion", s"org.scala-lang:scala-reflect:$scalaVersion" @@ -107,7 +110,10 @@ case class QuickBuild( ) val (dependencySources, classpath) = allJars.partition(_.getFileName.toString.endsWith("-sources.jar")) - val allPlugins = s"org.scalameta:::semanticdb-scalac:${V.semanticdbVersion}" :: compilerPlugins.toList + val allPlugins = + if (ScalaVersions.isSupportedScalaVersion(scalaVersion)) + s"org.scalameta:::semanticdb-scalac:${V.semanticdbVersion}" :: compilerPlugins.toList + else compilerPlugins.toList val pluginDependencies = allPlugins.map( plugin => QuickBuild diff --git a/tests/unit/src/test/scala/tests/BuildTargetsSlowSuite.scala b/tests/unit/src/test/scala/tests/BuildTargetsSlowSuite.scala new file mode 100644 index 00000000000..cae3b4e9e0c --- /dev/null +++ b/tests/unit/src/test/scala/tests/BuildTargetsSlowSuite.scala @@ -0,0 +1,36 @@ +package tests + +object BuildTargetsSlowSuite + extends BaseSlowSuite("build-targets") + with TestHovers { + + testAsync("scala-priority") { + for { + _ <- server.initialize( + s"""/metals.json + |{ + | "a": { + | "scalaVersion": "2.10.6", + | "libraryDependencies": ["com.lihaoyi::sourcecode:0.1.7"], + | "additionalSources": [ "shared/Main.scala" ] + | }, + | "b": { + | "scalaVersion": "${BuildInfo.scalaVersion}", + | "libraryDependencies": ["com.lihaoyi::sourcecode:0.1.7"], + | "additionalSources": [ "shared/Main.scala" ] + | } + |} + """.stripMargin + ) + // Assert that a supported Scala version target is picked over 2.10. + _ <- server.assertHover( + "shared/Main.scala", + """ + |object Main { + | sourcecode.Line(1).val@@ue + |}""".stripMargin, + """val value: Int""".hover + ) + } yield () + } +} diff --git a/tests/unit/src/test/scala/tests/DiagnosticsSlowSuite.scala b/tests/unit/src/test/scala/tests/DiagnosticsSlowSuite.scala index f75a524263f..42d2172839d 100644 --- a/tests/unit/src/test/scala/tests/DiagnosticsSlowSuite.scala +++ b/tests/unit/src/test/scala/tests/DiagnosticsSlowSuite.scala @@ -304,7 +304,7 @@ object DiagnosticsSlowSuite extends BaseSlowSuite("diagnostics") { |/metals.json |{ | "a": { - | "additionalSources" : [ "weird/path/A.scala" ] + | "additionalSources" : [ "a/weird/path/A.scala" ] | } |} |/a/weird/path/A.scala diff --git a/tests/unit/src/test/scala/tests/FileWatcherSlowSuite.scala b/tests/unit/src/test/scala/tests/FileWatcherSlowSuite.scala index 1cd63544901..cf1155b4e4f 100644 --- a/tests/unit/src/test/scala/tests/FileWatcherSlowSuite.scala +++ b/tests/unit/src/test/scala/tests/FileWatcherSlowSuite.scala @@ -24,7 +24,7 @@ object FileWatcherSlowSuite extends BaseSlowSuite("file-watcher") { """ |/metals.json |{ - | "a": { "additionalSources" : ["weird/path/d/D.scala", "non/existent/one/e/E.scala"] }, + | "a": { "additionalSources" : ["a/weird/path/d/D.scala", "non/existent/one/e/E.scala"] }, | "b": { }, | "c": { "dependsOn": [ "a" ] } |}