forked from scalacenter/scaladex
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Badge showing notable Scala support/Artifact versions
Fixes scalacenter#659 - adding support for a badge that summarises, for a given artifact, which versions of Scala it supports (and what the latest artifact version is for each of those Scala versions). ``` $ curl --silent -I http://localhost:8080/typelevel/cats/cats-core/latest-by-scala-version.svg | grep Location Location: https://img.shields.io/badge/cats--core-0.9.0_(Scala_2.12,_2.11,_2.10)-green.svg? $ curl --silent -I http://localhost:8080/typelevel/cats/cats-core/latest-by-scala-version.svg | grep Location Location: https://img.shields.io/badge/cats--core-0.9.0_(Scala_2.12,_2.11,_2.10)-green.svg? ```
- Loading branch information
Showing
7 changed files
with
313 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
server/src/main/scala/ch.epfl.scala.index.server/ArtifactScalaVersionSupport.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package ch.epfl.scala.index.server | ||
|
||
import ch.epfl.scala.index.model.{Release, SemanticVersion} | ||
import ch.epfl.scala.index.model.release._ | ||
import ch.epfl.scala.index.server.ArtifactScalaVersionSupport.ScalaSupport | ||
|
||
import scala.collection.immutable.{SortedMap, SortedSet} | ||
|
||
case class ArtifactScalaVersionSupport( | ||
scalaTargetsForAllArtifactVersions: Map[SemanticVersion, Seq[ScalaTarget]] | ||
) { | ||
|
||
val allTargets: Set[ScalaTarget] = | ||
scalaTargetsForAllArtifactVersions.values.flatten.toSet | ||
|
||
val latestScalaVersionsOfAvailableBinaryVersions: Set[LanguageVersion] = | ||
allTargets | ||
.map(_.languageVersion) | ||
.groupBy(_.family) | ||
.view | ||
.mapValues(_.max) | ||
.values | ||
.toSet | ||
|
||
val latestArtifactVersionByLanguageVersion | ||
: Map[LanguageVersion, SemanticVersion] = (for { | ||
(artifactVersion, scalaTargets) <- scalaTargetsForAllArtifactVersions.toSeq | ||
scalaTarget <- scalaTargets | ||
if latestScalaVersionsOfAvailableBinaryVersions.contains( | ||
scalaTarget.languageVersion | ||
) | ||
} yield scalaTarget.languageVersion -> artifactVersion) | ||
.groupMap(_._1)(_._2) | ||
.view | ||
.mapValues(_.max) | ||
.toMap | ||
|
||
val scalaSupportByLatestSupportingArtifactVersion | ||
: SortedMap[SemanticVersion, ScalaSupport] = | ||
SortedMap.from( | ||
latestArtifactVersionByLanguageVersion.groupMap(_._2)(_._1).view.map { | ||
case (artifactVersion, notableLanguageVersions) => | ||
val notableLanguageVersionsSet = notableLanguageVersions.toSet | ||
artifactVersion -> ScalaSupport( | ||
scalaTargetsForAllArtifactVersions(artifactVersion) | ||
.filter(st => notableLanguageVersionsSet(st.languageVersion)) | ||
.toSet | ||
) | ||
} | ||
)(SemanticVersion.ordering.reverse) | ||
|
||
val summaryOfLatestArtifactsSupportingScalaVersions: String = (for ( | ||
(artifactVersion, scalaSupport) <- | ||
scalaSupportByLatestSupportingArtifactVersion | ||
) yield s"$artifactVersion (${scalaSupport.summary})").mkString(", ") | ||
} | ||
|
||
object ArtifactScalaVersionSupport { | ||
def forSpecifiedArtifactAndTargetType( | ||
allAvailableReleases: Seq[Release], | ||
specificArtifact: String, | ||
specificTargetType: ScalaTargetType | ||
): ArtifactScalaVersionSupport = { | ||
|
||
val scalaTargetsByArtifactVersion = (for { | ||
release <- allAvailableReleases if release.isValid | ||
ref = release.reference if ref.artifact == specificArtifact | ||
scalaTarget <- ref.target if scalaTarget.targetType == specificTargetType | ||
} yield ref.version -> scalaTarget).groupMap(_._1)(_._2) | ||
|
||
ArtifactScalaVersionSupport(scalaTargetsByArtifactVersion) | ||
} | ||
|
||
case class ScalaSupport( | ||
scalaTargets: Set[ScalaTarget] | ||
) { | ||
val scalaTargetsByLanguageVersion: Map[LanguageVersion, Set[ScalaTarget]] = | ||
scalaTargets.groupBy(_.languageVersion) | ||
|
||
val languageVersions: SortedSet[LanguageVersion] = | ||
SortedSet.from(scalaTargetsByLanguageVersion.keySet)( | ||
LanguageVersion.ordering.reverse | ||
) | ||
|
||
val platformEditionsSupportedForAllLanguageVersions: Set[PlatformEdition] = | ||
scalaTargetsByLanguageVersion.values | ||
.map(_.collect { case st: ScalaTargetWithPlatformBinaryVersion => | ||
st.platformEdition | ||
}) | ||
.reduce(_ & _) | ||
|
||
val platformBinaryVersionsByTargetType | ||
: SortedMap[ScalaTargetType, SortedSet[BinaryVersion]] = | ||
SortedMap.from( | ||
platformEditionsSupportedForAllLanguageVersions | ||
.groupMap(_.targetType)(_.version) | ||
.view | ||
.mapValues(SortedSet.from(_)(BinaryVersion.ordering.reverse)) | ||
) | ||
|
||
val targetsSummary: Option[String] = | ||
Option.when(platformBinaryVersionsByTargetType.nonEmpty)( | ||
" - " + platformBinaryVersionsByTargetType | ||
.map { case (targetType, platformBinaryVersions) => | ||
s"$targetType ${platformBinaryVersions.mkString("+")}" | ||
} | ||
.mkString(", ") | ||
) | ||
|
||
val summary: String = | ||
s"Scala ${languageVersions.mkString(", ")}${targetsSummary.mkString}" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 128 additions & 0 deletions
128
server/src/test/scala/ch.epfl.scala.index.server/ArtifactScalaVersionSupportTest.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package ch.epfl.scala.index.server | ||
|
||
import ch.epfl.scala.index.model.release.ScalaVersion._ | ||
import ch.epfl.scala.index.model.release.{ | ||
Js, | ||
LanguageVersion, | ||
Native, | ||
PreReleaseBinary, | ||
Scala3Version, | ||
ScalaJs, | ||
ScalaJvm, | ||
ScalaNative | ||
} | ||
import ch.epfl.scala.index.model.{Milestone, ReleaseCandidate, SemanticVersion} | ||
import org.apache.commons.lang3.StringUtils.countMatches | ||
import org.scalatest.{FunSpec, Matchers} | ||
|
||
class ArtifactScalaVersionSupportTest extends FunSpec with Matchers { | ||
|
||
val `3.0.0-M3`: LanguageVersion = Scala3Version( | ||
PreReleaseBinary(3, 0, Some(0), Milestone(3)) | ||
) | ||
val `3.0.0-RC2`: LanguageVersion = Scala3Version( | ||
PreReleaseBinary(3, 0, Some(0), ReleaseCandidate(2)) | ||
) | ||
val `3.0.0-RC3`: LanguageVersion = Scala3Version( | ||
PreReleaseBinary(3, 0, Some(0), ReleaseCandidate(3)) | ||
) | ||
|
||
val `7.0.0`: SemanticVersion = SemanticVersion(7, 0, 0) | ||
val `7.1.0`: SemanticVersion = SemanticVersion(7, 1, 0) | ||
val `7.2.0`: SemanticVersion = SemanticVersion(7, 2, 0) | ||
val `7.3.0`: SemanticVersion = SemanticVersion(7, 3, 0) | ||
|
||
it("should provide a concise summary of Scala support by the artifact") { | ||
ArtifactScalaVersionSupport( | ||
Map( | ||
`7.0.0` -> Seq(ScalaJvm(`2.11`)), | ||
`7.1.0` -> Seq(ScalaJvm(`2.11`), ScalaJvm(`2.12`)), | ||
`7.2.0` -> Seq(ScalaJvm(`2.12`), ScalaJvm(`2.13`)) | ||
) | ||
).summaryOfLatestArtifactsSupportingScalaVersions shouldBe "7.2.0 (Scala 2.13, 2.12), 7.1.0 (Scala 2.11)" | ||
} | ||
|
||
it( | ||
"should concisely convey which versions of Scala are supported, most recent Scala version first" | ||
) { | ||
ArtifactScalaVersionSupport( | ||
Map( | ||
`7.0.0` -> Seq( | ||
ScalaJvm(`2.12`), | ||
ScalaJvm(`2.13`), | ||
ScalaJvm(`3.0.0-RC3`) | ||
) | ||
) | ||
).summaryOfLatestArtifactsSupportingScalaVersions should include( | ||
"Scala 3.0.0-RC3, 2.13, 2.12" | ||
) | ||
} | ||
|
||
it( | ||
"should convey the latest artifact version available for each Scala language version" | ||
) { | ||
val summary = ArtifactScalaVersionSupport( | ||
Map( | ||
`7.0.0` -> Seq(ScalaJvm(`2.11`)), | ||
`7.1.0` -> Seq(ScalaJvm(`2.11`)), | ||
`7.2.0` -> Seq(ScalaJvm(`2.12`)), | ||
`7.3.0` -> Seq(ScalaJvm(`2.12`)) | ||
) | ||
).summaryOfLatestArtifactsSupportingScalaVersions | ||
|
||
// these artifact versions are not the latest available support for any Scala language version, so uninteresting: | ||
summary should not(include("7.0.0") or include("7.2.0")) | ||
|
||
summary should include("7.1.0 (Scala 2.11)") | ||
summary should include("7.3.0 (Scala 2.12)") | ||
} | ||
|
||
it( | ||
"should, for brevity, not mention a Scala language version more than once, even if it occurs in multiple artifact versions being mentioned" | ||
) { | ||
val summary = ArtifactScalaVersionSupport( | ||
Map( | ||
`7.1.0` -> Seq(ScalaJvm(`2.11`), ScalaJvm(`2.12`)), | ||
`7.2.0` -> Seq(ScalaJvm(`2.12`)) | ||
) | ||
).summaryOfLatestArtifactsSupportingScalaVersions | ||
|
||
// it happens that two artifact versions that support Scala 2.12 will be mentioned... | ||
assert(summary.contains("7.1.0") && summary.contains("7.2.0")) | ||
|
||
// ...but for brevity no Scala language version (eg Scala 2.12 in this case) should be mentioned more than once... | ||
countMatches(summary, "2.12") shouldBe 1 | ||
|
||
// ...specifically it should be listed against the *latest* artifact that supports that Scala language version | ||
summary should include("7.2.0 (Scala 2.12)") | ||
} | ||
|
||
it( | ||
"should, for brevity, only mention the *latest* Scala language versions available for any given Scala binary version family" | ||
) { | ||
ArtifactScalaVersionSupport( | ||
Map( | ||
`7.0.0` -> Seq(ScalaJvm(`2.13`), ScalaJvm(`3.0.0-M3`)), | ||
`7.1.0` -> Seq(ScalaJvm(`2.13`), ScalaJvm(`3.0.0-RC2`)), | ||
`7.2.0` -> Seq(ScalaJvm(`2.13`), ScalaJvm(`3.0.0-RC3`)) | ||
) | ||
).summaryOfLatestArtifactsSupportingScalaVersions shouldBe "7.2.0 (Scala 3.0.0-RC3, 2.13)" | ||
} | ||
|
||
it( | ||
"should list the Scala platform editions that support all cited versions of the Scala language" | ||
) { | ||
ArtifactScalaVersionSupport( | ||
Map( | ||
`7.1.0` -> Seq( | ||
ScalaNative(`3.0.0-M3`, Native.`0.3`), | ||
ScalaNative(`2.13`, Native.`0.3`), | ||
ScalaNative(`3.0.0-M3`, Native.`0.4`), | ||
ScalaNative(`2.13`, Native.`0.4`) | ||
) | ||
) | ||
).summaryOfLatestArtifactsSupportingScalaVersions shouldBe "7.1.0 (Scala 3.0.0-M3, 2.13 - Native 0.4+0.3)" | ||
|
||
} | ||
|
||
} |