Skip to content

Commit

Permalink
special case for scala lib and look for tasty files when discovering …
Browse files Browse the repository at this point in the history
…scala version for source jar
  • Loading branch information
kasiaMarek committed Aug 22, 2024
1 parent 2d05355 commit 087940c
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,14 @@ final class BuildTargets private (
* @return path to the source jar for that jar
*/
private def sourceJarPathFallback(
sourceJarPath: AbsolutePath
sourceJarPath: AbsolutePath,
inputIsSourceJar: Boolean = false,
): Option[AbsolutePath] = {
val (from, to) =
if (inputIsSourceJar) ("-sources.jar", ".jar")
else (".jar", "-sources.jar")
val fallback = sourceJarPath.parent.resolve(
sourceJarPath.filename.replace(".jar", "-sources.jar")
sourceJarPath.filename.replace(from, to)
)
if (fallback.exists) Some(fallback)
else None
Expand Down Expand Up @@ -578,18 +582,29 @@ final class BuildTargets private (
jar: AbsolutePath,
): Option[AbsolutePath] = {
data
.fromOptions(_.findSourceJarOf(jar, Some(id)))
.fromOptions(_.findConnectedArtifact(jar, Some(id)))
.orElse(sourceJarPathFallback(jar))
}

def sourceJarFor(
jar: AbsolutePath
): Option[AbsolutePath] = {
data
.fromOptions(_.findSourceJarOf(jar, targetId = None))
.fromOptions(_.findConnectedArtifact(jar, targetId = None))
.orElse(sourceJarPathFallback(jar))
}

def findJarFor(
id: BuildTargetIdentifier,
sourceJar: AbsolutePath,
): Option[AbsolutePath] = {
data
.fromOptions(
_.findConnectedArtifact(sourceJar, Some(id), classifier = null)
)
.orElse(sourceJarPathFallback(sourceJar, inputIsSourceJar = true))
}

def inverseDependencySource(
sourceJar: AbsolutePath
): collection.Set[BuildTargetIdentifier] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package scala.meta.internal.metals

import java.io.UncheckedIOException

import scala.collection.concurrent.TrieMap

import scala.meta.Dialect
import scala.meta.dialects._
import scala.meta.internal.io.FileIO
import scala.meta.internal.metals.MetalsEnrichments._
import scala.meta.internal.semver.SemVer
import scala.meta.io.AbsolutePath

Expand All @@ -14,6 +20,8 @@ class ScalaVersions(
scala3: String,
) {

private val jarScalaVersionIndex = TrieMap[String, String]()

def isScala3Milestone(version: String): Boolean =
version.startsWith("3.0.0-M") || version.startsWith("3.0.0-RC")

Expand Down Expand Up @@ -148,7 +156,9 @@ class ScalaVersions(
}

private val scalaVersionRegex =
raw"(_)(\d)(\.\d{1,2})?(\.\d(-(RC|M)\d)?)?".r
raw"_(\d)(\.\d{1,2})?(\.\d(-(RC|M)\d)?)?".r
private val scalaLibraryRegex =
raw"scala-library-(\d)(\.\d{1,2})(\.\d(-(RC|M)\d)?)".r

/**
* Extract scala binary version from dependency jar name.
Expand All @@ -162,40 +172,59 @@ class ScalaVersions(
val dropEnding = filename
.stripSuffix(".jar")

scalaVersionRegex
.findAllMatchIn(dropEnding)
.toList
List(scalaLibraryRegex, scalaVersionRegex)
.flatMap(_.findAllMatchIn(dropEnding).toList)
.flatMap { m =>
val hasUnderscorePrefix = Option(m.group(1)).isDefined
val major = m.group(2)
val minor = Option(m.group(3)).getOrElse("")
val ending = Option(m.group(4)).getOrElse("")
val major = m.group(1)
val minor = Option(m.group(2)).getOrElse("")
val ending = Option(m.group(3)).getOrElse("")
val version = s"$major$minor$ending"

if (isSupportedScalaBinaryVersion(version))
Some(version -> hasUnderscorePrefix)
Some(version)
else None
}
.sortBy(_._2)(Ordering.Boolean.reverse)
.headOption
.map { case (version, _) => scalaBinaryVersionFromFullVersion(version) }
.map(scalaBinaryVersionFromFullVersion)
}

def dialectForDependencyJar(
jar: AbsolutePath,
buildTargets: BuildTargets,
): Dialect = {
lazy val buildTargetAndScalaVersion =
buildTargets
.inverseDependencySource(jar)
.flatMap(id => buildTargets.scalaTarget(id))
.map(target => (target.scalaBinaryVersion, target.id))
.toList
.sortBy(_._1)
.headOption

def fromTastyExistance = {
val fromTasty = buildTargetAndScalaVersion
.flatMap { case (_, id) => buildTargets.findJarFor(id, jar) }
.flatMap(
FileIO.withJarFileSystem(_, create = false) { root =>
try {
root.listRecursive
.find(f => f.isFile && f.filename.endsWith(".tasty"))
.map(_ => "3")
.orElse(Some("2.13"))
} catch {
case _: UncheckedIOException => None
}
}
)
fromTasty.foreach(jarScalaVersionIndex.put(jar.toURI.toString(), _))
fromTasty
}

val scalaVersion =
scalaBinaryVersionFromJarName(jar.toNIO.getFileName().toString())
.orElse(
buildTargets
.inverseDependencySource(jar)
.flatMap(id => buildTargets.scalaTarget(id))
.map(_.scalaBinaryVersion)
.toList
.sorted
.headOption
)
.orElse(jarScalaVersionIndex.get(jar.toURI.toString()))
.orElse(fromTastyExistance)
.orElse(buildTargetAndScalaVersion.map(_._1))
.getOrElse("2.13")
dialectForScalaVersion(scalaVersion, includeSource3 = true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,10 @@ final class TargetData {
}
}

def findSourceJarOf(
def findConnectedArtifact(
jar: AbsolutePath,
targetId: Option[BuildTargetIdentifier],
classifier: String = "sources",
): Option[AbsolutePath] = {
val jarUri = jar.toURI.toString()
def depModules: Iterator[MavenDependencyModule] = targetId match {
Expand All @@ -228,10 +229,10 @@ final class TargetData {
module <- depModules
artifacts = module.getArtifacts().asScala
if artifacts.exists(artifact => isUriEqual(artifact.getUri(), jarUri))
sourceJar <- artifacts.find(_.getClassifier() == "sources")
sourceJarPath = sourceJar.getUri().toAbsolutePath
if sourceJarPath.exists
} yield sourceJarPath
foundJar <- artifacts.find(_.getClassifier() == classifier)
foundJarPath = foundJar.getUri().toAbsolutePath
if foundJarPath.exists
} yield foundJarPath
allFound.headOption
}

Expand Down

0 comments on commit 087940c

Please sign in to comment.