From 7cc949da2dc312d26896e6be20b8c4ae4f258c51 Mon Sep 17 00:00:00 2001 From: Vadim Chelyshov Date: Tue, 8 Mar 2022 19:32:24 +0300 Subject: [PATCH] fix: adjust testes for 3.2.0-NIGHTLY Also, exnteded the `compat` inn tests cases. Now it's possible to specify matching version not only as starts with but as greater or equal. For example: ``` check( "input ... ", "default expected ...", compat = Map( ">=3.1.0" -> "expected for version gte than 3.1.0", "3" -> "any otherversion that starts from 3" ) ) ``` --- .../pc/completions/CompletionValue.scala | 4 +- .../scala/meta/internal/semver/SemVer.scala | 85 ++++++++----------- .../tests/hover/HoverScala3TypeSuite.scala | 4 +- .../tests/pc/CompletionBacktickSuite.scala | 3 +- .../test/scala/tests/pc/CompletionSuite.scala | 4 +- .../src/main/scala/tests/BaseSuite.scala | 7 +- tests/mtest/src/main/scala/tests/Compat.scala | 39 +++++++++ .../test/scala/tests/ScalaVersionsSuite.scala | 9 ++ .../src/test/scala/tests/SemVerSuite.scala | 35 ++++++++ 9 files changed, 130 insertions(+), 60 deletions(-) create mode 100644 tests/mtest/src/main/scala/tests/Compat.scala create mode 100644 tests/unit/src/test/scala/tests/SemVerSuite.scala diff --git a/mtags/src/main/scala-3/scala/meta/internal/pc/completions/CompletionValue.scala b/mtags/src/main/scala-3/scala/meta/internal/pc/completions/CompletionValue.scala index c9773c6ed3d..2c1497453e0 100644 --- a/mtags/src/main/scala-3/scala/meta/internal/pc/completions/CompletionValue.scala +++ b/mtags/src/main/scala-3/scala/meta/internal/pc/completions/CompletionValue.scala @@ -72,7 +72,9 @@ object CompletionValue: case class Keyword(label: String, insertText: String) extends CompletionValue def fromCompiler(completion: Completion): List[CompletionValue] = - completion.symbols.map(Compiler(completion.label, _)) + def undoBacktick(label: String): String = + label.stripPrefix("`").stripSuffix("`") + completion.symbols.map(Compiler(undoBacktick(completion.label), _)) def namedArg(label: String, sym: Symbol)(using Context): CompletionValue = NamedArg(label, sym.info.widenTermRefExpr) diff --git a/mtags/src/main/scala/scala/meta/internal/semver/SemVer.scala b/mtags/src/main/scala/scala/meta/internal/semver/SemVer.scala index 3ba9411cc70..36a8fb17626 100644 --- a/mtags/src/main/scala/scala/meta/internal/semver/SemVer.scala +++ b/mtags/src/main/scala/scala/meta/internal/semver/SemVer.scala @@ -1,79 +1,66 @@ package scala.meta.internal.semver -import scala.util.Try - object SemVer { case class Version( major: Int, minor: Int, patch: Int, - releaseCandidate: Option[Int], - milestone: Option[Int] + releaseCandidate: Option[Int] = None, + milestone: Option[Int] = None, + nightlyDate: Option[Int] = None ) { def >(that: Version): Boolean = { - lazy val baseVersionEqual = - this.major == this.major && this.minor == that.minor && this.patch == that.patch + val diff = toList + .zip(that.toList) + .collectFirst { + case (a, b) if a - b != 0 => a - b + } + .getOrElse(0) + diff > 0 + } + + def <(that: Version): Boolean = + that > this - this.major > that.major || - (this.major == that.major && this.minor > that.minor) || - (this.major == that.major && this.minor == that.minor && this.patch > that.patch) || - // 3.0.0-RC1 > 3.0.0-M1 - baseVersionEqual && this.releaseCandidate.isDefined && that.milestone.isDefined || - // 3.0.0 > 3.0.0-M2 and 3.0.0 > 3.0.0-RC1 - baseVersionEqual && (this.milestone.isEmpty && this.releaseCandidate.isEmpty && (that.milestone.isDefined || that.releaseCandidate.isDefined)) || - // 3.0.0-RC2 > 3.0.0-RC1 - baseVersionEqual && comparePreRelease( - that, - (v: Version) => v.releaseCandidate - ) || - // 3.0.0-M2 > 3.0.0-M1 - baseVersionEqual && comparePreRelease(that, (v: Version) => v.milestone) + private def toList: List[Int] = { + val rcMilestonePart = + releaseCandidate + .map(v => List(1, v)) + .orElse(milestone.map(v => List(0, v))) + .getOrElse(List(2, 0)) + List(major, minor, patch) ++ rcMilestonePart ++ + List(nightlyDate.getOrElse(Int.MaxValue)) } def >=(that: Version): Boolean = this > that || this == that - private def comparePreRelease( - that: Version, - preRelease: Version => Option[Int] - ): Boolean = { - val thisPrerelease = preRelease(this) - val thatPrerelease = preRelease(that) - this.major == that.major && this.minor == that.minor && this.patch == that.patch && - thisPrerelease.isDefined && thatPrerelease.isDefined && thisPrerelease - .zip(thatPrerelease) - .exists { case (a, b) => a > b } - } - override def toString: String = List( Some(s"$major.$minor.$patch"), releaseCandidate.map(s => s"-RC$s"), - milestone.map(s => s"-M$s") + milestone.map(s => s"-M$s"), + nightlyDate.map(d => s"-$d-NIGHTLY") ).flatten.mkString("") } object Version { def fromString(version: String): Version = { - val Array(major, minor, patch) = - version.replaceAll("(-|\\+).+$", "").split('.').map(_.toInt) - - val prereleaseString = version.stripPrefix(s"$major.$minor.$patch") - - def fromSuffix(name: String) = { - if (prereleaseString.startsWith(name)) - Try( - prereleaseString.stripPrefix(name).replaceAll("\\-.*", "").toInt - ).toOption - else None - } - val releaseCandidate = fromSuffix("-RC") - val milestone = fromSuffix("-M") - - Version(major, minor, patch, releaseCandidate, milestone) + val parts = version.split("\\.|-") + val Array(major, minor, patch) = parts.take(3).map(_.toInt) + val (rc, milestone) = parts + .lift(3) + .map { v => + if (v.startsWith("RC")) (Some(v.stripPrefix("RC").toInt), None) + else (None, Some(v.stripPrefix("M").toInt)) + } + .getOrElse((None, None)) + val date = parts.lift(5).map(_.toInt) + Version(major, minor, patch, rc, milestone, date) } + } def isCompatibleVersion(minimumVersion: String, version: String): Boolean = { diff --git a/tests/cross/src/test/scala/tests/hover/HoverScala3TypeSuite.scala b/tests/cross/src/test/scala/tests/hover/HoverScala3TypeSuite.scala index a0ff0642245..d3529101481 100644 --- a/tests/cross/src/test/scala/tests/hover/HoverScala3TypeSuite.scala +++ b/tests/cross/src/test/scala/tests/hover/HoverScala3TypeSuite.scala @@ -54,7 +54,7 @@ class HoverScala3TypeSuite extends BaseHoverSuite { """|case Red: Red |""".stripMargin.hover, compat = Map( - "3.1.3-RC1" -> + ">=3.1.3-RC1-bin-20220301-fae7c09-NIGHTLY" -> """|case Red: Color |""".stripMargin.hover ) @@ -81,7 +81,7 @@ class HoverScala3TypeSuite extends BaseHoverSuite { |""".stripMargin, "", compat = Map( - "3.1.3-RC1" -> + ">=3.1.3-RC1-bin-20220301-fae7c09-NIGHTLY" -> """|case Blue: Color |""".stripMargin.hover ) diff --git a/tests/cross/src/test/scala/tests/pc/CompletionBacktickSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionBacktickSuite.scala index 784145e0abc..5764a2ac075 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionBacktickSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionBacktickSuite.scala @@ -15,7 +15,8 @@ class CompletionBacktickSuite extends BaseCompletionSuite { |""".stripMargin, filterText = "type", compat = Map( - "3" -> "type: Int" + "3" -> "type: Int", + ">=3.2.0" -> "`type`: Int" ) ) diff --git a/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala b/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala index f7913da5b23..56827474156 100644 --- a/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala +++ b/tests/cross/src/test/scala/tests/pc/CompletionSuite.scala @@ -949,7 +949,7 @@ class CompletionSuite extends BaseCompletionSuite { """|Some scala |""".stripMargin, compat = Map( - "3.1" -> + ">=3.1.0" -> """|Some scala |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] @@ -976,7 +976,7 @@ class CompletionSuite extends BaseCompletionSuite { """|Some scala |""".stripMargin, compat = Map( - "3.1" -> + ">=3.1.0" -> """|Some scala |SomeToExpr[T: Type: ToExpr]: SomeToExpr[T] |SomeFromExpr[T](using Type[T], FromExpr[T]): SomeFromExpr[T] diff --git a/tests/mtest/src/main/scala/tests/BaseSuite.scala b/tests/mtest/src/main/scala/tests/BaseSuite.scala index 49e3055fcc7..18dee737fac 100644 --- a/tests/mtest/src/main/scala/tests/BaseSuite.scala +++ b/tests/mtest/src/main/scala/tests/BaseSuite.scala @@ -86,11 +86,8 @@ abstract class BaseSuite extends munit.FunSuite with Assertions { compat: Map[String, A], scalaVersion: String ): A = - compat - .collect { - case (ver, compatCode) if scalaVersion.startsWith(ver) => compatCode - } - .headOption + Compat + .forScalaVersion(scalaVersion, compat) .getOrElse(default) protected def toJsonArray(list: List[String]): String = { diff --git a/tests/mtest/src/main/scala/tests/Compat.scala b/tests/mtest/src/main/scala/tests/Compat.scala new file mode 100644 index 00000000000..567109b7698 --- /dev/null +++ b/tests/mtest/src/main/scala/tests/Compat.scala @@ -0,0 +1,39 @@ +package tests + +import scala.meta.internal.semver.SemVer + +object Compat { + + /** + * Cases might be described as: + * - Starts swith: "3.0.1" -> value | "3.0" -> value | "3" + * - Greater or equal: ">=3.0.0" -> value + */ + def forScalaVersion[A]( + scalaVersion: String, + cases: Map[String, A] + ): Option[A] = { + val (startsWith, gt) = + cases.partition({ case (v, _) => !v.startsWith(">=") }) + + val fromStartWith = startsWith.collectFirst({ + case (v, a) if scalaVersion.startsWith(v) => a + }) + matchesGte(scalaVersion, gt) orElse fromStartWith + } + + private def matchesGte[A]( + version: String, + gtCases: Map[String, A] + ): Option[A] = { + val parsed = SemVer.Version.fromString(version) + val less = gtCases + .map { case (v, a) => + (SemVer.Version.fromString(v.stripPrefix(">=")), a) + } + .filter({ case (v, _) => parsed >= v }) + + less.toList.sortWith(_._1 < _._1).lastOption.map(_._2) + } + +} diff --git a/tests/unit/src/test/scala/tests/ScalaVersionsSuite.scala b/tests/unit/src/test/scala/tests/ScalaVersionsSuite.scala index e48430a1f5e..f71176f614a 100644 --- a/tests/unit/src/test/scala/tests/ScalaVersionsSuite.scala +++ b/tests/unit/src/test/scala/tests/ScalaVersionsSuite.scala @@ -276,6 +276,15 @@ class ScalaVersionsSuite extends BaseSuite { ) } + test("compare-NIGTLY") { + assert( + SemVer.isLaterVersion( + "3.0.0-RC1-bin-20201125-1c3538a-NIGHTLY", + "3.0.0-RC1-bin-20201126-1c3538a-NIGHTLY" + ) + ) + } + test("not-future-3-M1") { assert( !ScalaVersions.isFutureVersion("3.0.0-M1") diff --git a/tests/unit/src/test/scala/tests/SemVerSuite.scala b/tests/unit/src/test/scala/tests/SemVerSuite.scala new file mode 100644 index 00000000000..90f2df3837c --- /dev/null +++ b/tests/unit/src/test/scala/tests/SemVerSuite.scala @@ -0,0 +1,35 @@ +package tests + +import scala.meta.internal.semver.SemVer + +import munit.FunSuite + +class SemVerSuite extends FunSuite { + + val expected: List[(String, SemVer.Version)] = List( + ("3.0.0", SemVer.Version(3, 0, 0)), + ("3.0.0-M1", SemVer.Version(3, 0, 0, milestone = Some(1))), + ("3.0.0-RC1", SemVer.Version(3, 0, 0, releaseCandidate = Some(1))), + ( + "3.2.0-RC1-bin-20220307-6dc591a-NIGHTLY", + SemVer.Version( + 3, + 2, + 0, + releaseCandidate = Some(1), + nightlyDate = Some(20220307) + ) + ) + ) + + test("fromString") { + val incorrect = expected + .map { case (s, e) => (SemVer.Version.fromString(s), e) } + .filter({ case (parsed, expected) => parsed != expected }) + + assert( + incorrect.isEmpty, + incorrect.mkString("Failed to parse versions(expected, got):", "\n", "") + ) + } +}