Skip to content

Commit 2e2b637

Browse files
committed
Close #223 - [just-semver-decver] Add DecVerExt which is DecVer with pre-release and build metadata
1 parent 0b08cb7 commit 2e2b637

File tree

14 files changed

+1582
-73
lines changed

14 files changed

+1582
-73
lines changed

build.sbt

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import sbtcrossproject.CrossProject
5353

5454
lazy val core = module("core", crossProject(JVMPlatform, JSPlatform, NativePlatform))
5555
.settings(
56+
libraryDependencies ++= List(libs.tests.scalaCollectionCompat),
5657
// (Compile / compile) / scalacOptions ++= (if (isGhaPublishing) List.empty[String]
5758
// else ProjectInfo.commonWarts(scalaVersion.value)),
5859
// (Test / compile) / scalacOptions ++= (if (isGhaPublishing) List.empty[String]
@@ -94,7 +95,10 @@ lazy val coreJs = core.js.settings(Test / fork := false)
9495
lazy val coreNative = core.native.settings(nativeSettings)
9596

9697
lazy val decver = module("decver", crossProject(JVMPlatform, JSPlatform, NativePlatform))
97-
.dependsOn(core)
98+
.settings(
99+
libraryDependencies ++= List(libs.tests.scalaCollectionCompat),
100+
)
101+
.dependsOn(core % props.IncludeTest)
98102

99103
lazy val decverJvm = decver.jvm
100104
lazy val decverJs = decver.js.settings(Test / fork := false)
@@ -168,10 +172,11 @@ lazy val props =
168172
val isWartRemover: ModuleID => Boolean =
169173
m => m.name == "wartremover"
170174

171-
// final val ProjectScalaVersion: String = "3.1.3"
172-
// final val ProjectScalaVersion: String = "3.3.1"
173-
final val ProjectScalaVersion: String = "2.13.12"
174-
final val CrossScalaVersions: List[String] =
175+
// val ProjectScalaVersion: String = "2.12.18"
176+
// val ProjectScalaVersion: String = "3.1.3"
177+
// val ProjectScalaVersion: String = "3.3.1"
178+
val ProjectScalaVersion: String = "2.13.12"
179+
val CrossScalaVersions: List[String] =
175180
(
176181
if (isGhaPublishing) {
177182
// Publish version and the project version are the same so this logic is no longer required.
@@ -189,30 +194,40 @@ lazy val props =
189194
).distinct
190195
)
191196

197+
val IncludeTest = "compile->compile;test->test"
198+
192199
val SonatypeCredentialHost = "s01.oss.sonatype.org"
193200
val SonatypeRepository = s"https://$SonatypeCredentialHost/service/local"
194201

195202
final val HedgehogVersion = "0.9.0"
196203

197204
final val HedgehogLatestVersion = "0.10.1"
198205

206+
val ScalaCollectionCompatVersion = "2.12.0"
207+
199208
}
200209

201210
lazy val libs =
202211
new {
203212

204-
def hedgehogLibs(scalaVersion: String): List[ModuleID] = {
205-
val hedgehogVersion =
206-
if (scalaVersion.startsWith("3.0"))
207-
props.HedgehogVersion
208-
else
209-
props.HedgehogLatestVersion
213+
lazy val tests = new {
210214

211-
List(
212-
"qa.hedgehog" %% "hedgehog-core" % hedgehogVersion % Test,
213-
"qa.hedgehog" %% "hedgehog-runner" % hedgehogVersion % Test,
214-
"qa.hedgehog" %% "hedgehog-sbt" % hedgehogVersion % Test
215-
)
215+
def hedgehogLibs(scalaVersion: String): List[ModuleID] = {
216+
val hedgehogVersion =
217+
if (scalaVersion.startsWith("3.0"))
218+
props.HedgehogVersion
219+
else
220+
props.HedgehogLatestVersion
221+
222+
List(
223+
"qa.hedgehog" %% "hedgehog-core" % hedgehogVersion % Test,
224+
"qa.hedgehog" %% "hedgehog-runner" % hedgehogVersion % Test,
225+
"qa.hedgehog" %% "hedgehog-sbt" % hedgehogVersion % Test
226+
)
227+
}
228+
229+
val scalaCollectionCompat =
230+
"org.scala-lang.modules" %% "scala-collection-compat" % props.ScalaCollectionCompatVersion % Test
216231
}
217232
}
218233

@@ -237,7 +252,6 @@ def module(projectName: String, crossProject: CrossProject.Builder): CrossProjec
237252
.in(file(s"modules/$prefixedName"))
238253
.settings(
239254
name := prefixedName,
240-
testFrameworks ~= (testFws => (TestFramework("hedgehog.sbt.Framework") +: testFws).distinct),
241255
)
242256
.settings(
243257
libraryDependencies ++= {
@@ -265,14 +279,14 @@ def module(projectName: String, crossProject: CrossProject.Builder): CrossProjec
265279
libraryDependencies :=
266280
crossVersionProps(Seq.empty[ModuleID], SemVer.parseUnsafe(scalaVersion.value)) {
267281
case (SemVer.Major(3), SemVer.Minor(0), _) =>
268-
libs.hedgehogLibs(scalaVersion.value) ++ libraryDependencies.value ++
282+
libs.tests.hedgehogLibs(scalaVersion.value) ++ libraryDependencies.value ++
269283
libraryDependencies.value.filterNot(m => m.organization == "org.wartremover" && m.name == "wartremover")
270284

271285
case (Major(3), _, _) =>
272-
libs.hedgehogLibs(scalaVersion.value) ++ libraryDependencies.value
286+
libs.tests.hedgehogLibs(scalaVersion.value) ++ libraryDependencies.value
273287

274288
case x =>
275-
libs.hedgehogLibs(scalaVersion.value) ++ libraryDependencies.value
289+
libs.tests.hedgehogLibs(scalaVersion.value) ++ libraryDependencies.value
276290
},
277291
libraryDependencies := (
278292
if (isScala3(scalaVersion.value)) {

modules/just-semver-core/shared/src/main/scala-2/just/semver/AdditionalInfo.scala

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,49 @@ object AdditionalInfo extends Compat {
2727
buildMetaInfo.identifier.map(Dsv.render).mkString(".")
2828
}
2929

30-
def parsePreRelease(value: String): Either[ParseError, Option[PreRelease]] =
30+
def parsePreRelease(value: String): Either[AdditionalInfoParseError, Option[PreRelease]] =
3131
parse(
3232
value,
3333
{
3434
case a @ Dsv(Num(n) :: Nil) =>
3535
if ((n === "0") || n.takeWhile(_ === '0').length === 0)
3636
Right(a)
3737
else
38-
Left(ParseError.leadingZeroNumError(n))
38+
Left(AdditionalInfoParseError.leadingZeroNumError(n))
3939
case a @ Dsv(_) =>
4040
Right(a)
4141
}
4242
).map(_.map(PreRelease.apply))
4343

44-
def parseBuildMetaInfo(value: String): Either[ParseError, Option[BuildMetaInfo]] =
44+
def parseBuildMetaInfo(value: String): Either[AdditionalInfoParseError, Option[BuildMetaInfo]] =
4545
parse(value, Right.apply).map(_.map(BuildMetaInfo.apply))
4646

4747
def parse(
4848
value: String,
49-
validator: Dsv => Either[ParseError, Dsv]
50-
): Either[ParseError, Option[List[Dsv]]] = {
51-
val alphaNumHyphens: Either[ParseError, List[Dsv]] =
49+
validator: Dsv => Either[AdditionalInfoParseError, Dsv]
50+
): Either[AdditionalInfoParseError, Option[List[Dsv]]] = {
51+
val alphaNumHyphens: Either[AdditionalInfoParseError, List[Dsv]] =
5252
Option(value)
5353
.map(_.split("\\."))
5454
.map(_.map(Dsv.parse)) match {
5555
case Some(preRelease) =>
56-
preRelease.foldRight(List.empty[Dsv].asRight[ParseError]) { (x, acc) =>
57-
x.flatMap(validator) match {
56+
preRelease.foldRight(List.empty[Dsv].asRight[AdditionalInfoParseError]) { (x, acc) =>
57+
x.left
58+
.map {
59+
case Dsv.DsvParseError.InvalidAlphaNumHyphenError(c, rest) =>
60+
AdditionalInfoParseError.invalidAlphaNumHyphenError(c, rest)
61+
case Dsv.DsvParseError.EmptyAlphaNumHyphenError =>
62+
AdditionalInfoParseError.emptyAlphaNumHyphenError
63+
}
64+
.flatMap(validator) match {
5865
case Right(alp) =>
5966
acc.map(alps => alp :: alps)
6067
case Left(error) =>
6168
error.asLeft[List[Dsv]]
6269
}
6370
}
6471
case None =>
65-
List.empty[Dsv].asRight[ParseError]
72+
List.empty[Dsv].asRight[AdditionalInfoParseError]
6673
}
6774
alphaNumHyphens.map {
6875
case Nil =>
@@ -71,4 +78,20 @@ object AdditionalInfo extends Compat {
7178
xs.some
7279
}
7380
}
81+
82+
sealed trait AdditionalInfoParseError
83+
object AdditionalInfoParseError {
84+
final case class LeadingZeroNumError(n: String) extends AdditionalInfoParseError
85+
86+
final case class InvalidAlphaNumHyphenError(c: Char, rest: List[Char]) extends AdditionalInfoParseError
87+
case object EmptyAlphaNumHyphenError extends AdditionalInfoParseError
88+
89+
def leadingZeroNumError(n: String): AdditionalInfoParseError = LeadingZeroNumError(n)
90+
91+
def invalidAlphaNumHyphenError(c: Char, rest: List[Char]): AdditionalInfoParseError =
92+
InvalidAlphaNumHyphenError(c, rest)
93+
94+
def emptyAlphaNumHyphenError: AdditionalInfoParseError = EmptyAlphaNumHyphenError
95+
}
96+
7497
}

modules/just-semver-core/shared/src/main/scala-2/just/semver/Dsv.scala

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ object Dsv extends Compat {
2121
@inline def render: String = Dsv.render(dsv)
2222
}
2323

24-
def render(alphaNumHyphenGroup: Dsv): String =
25-
alphaNumHyphenGroup.values.map(Anh.render).mkString
24+
def render(dsv: Dsv): String =
25+
dsv.values.map(Anh.render).mkString
2626

27-
def parse(value: String): Either[ParseError, Dsv] = {
27+
def parse(value: String): Either[DsvParseError, Dsv] = {
2828

2929
@tailrec
30-
def accumulate(cs: List[Char], chars: Anh, acc: Vector[Anh]): Either[ParseError, Vector[Anh]] =
30+
def accumulate(cs: List[Char], chars: Anh, acc: Vector[Anh]): Either[DsvParseError, Vector[Anh]] =
3131
cs match {
3232
case x :: xs =>
3333
if (x.isDigit) {
@@ -50,7 +50,7 @@ object Dsv extends Compat {
5050
}
5151
} else {
5252
Left(
53-
ParseError.invalidAlphaNumHyphenError(x, xs)
53+
DsvParseError.invalidAlphaNumHyphenError(x, xs)
5454
)
5555
}
5656

@@ -69,14 +69,25 @@ object Dsv extends Compat {
6969
accumulate(xs, Alphabet(x.toString), Vector.empty)
7070
else
7171
Left(
72-
ParseError.invalidAlphaNumHyphenError(x, xs)
72+
DsvParseError.invalidAlphaNumHyphenError(x, xs)
7373
)
7474

7575
result.map(groups => Dsv(groups.toList))
7676

7777
case Nil =>
78-
Left(ParseError.emptyAlphaNumHyphenError)
78+
Left(DsvParseError.emptyAlphaNumHyphenError)
7979
}
8080

8181
}
82+
83+
sealed trait DsvParseError
84+
object DsvParseError {
85+
final case class InvalidAlphaNumHyphenError(c: Char, rest: List[Char]) extends DsvParseError
86+
case object EmptyAlphaNumHyphenError extends DsvParseError
87+
88+
def invalidAlphaNumHyphenError(c: Char, rest: List[Char]): DsvParseError = InvalidAlphaNumHyphenError(c, rest)
89+
90+
def emptyAlphaNumHyphenError: DsvParseError = EmptyAlphaNumHyphenError
91+
92+
}
8293
}

modules/just-semver-core/shared/src/main/scala-2/just/semver/ParseError.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ object ParseError {
4949

5050
def semVerMatchersParseErrors(error: SemVerMatchers.ParseErrors): ParseError = SemVerMatchersParseErrors(error)
5151

52+
def fromAdditionalInfoParserError(additionalInfoParseError: AdditionalInfo.AdditionalInfoParseError): ParseError =
53+
additionalInfoParseError match {
54+
case AdditionalInfo.AdditionalInfoParseError.LeadingZeroNumError(n) =>
55+
ParseError.leadingZeroNumError(n)
56+
case AdditionalInfo.AdditionalInfoParseError.InvalidAlphaNumHyphenError(c, rest) =>
57+
ParseError.invalidAlphaNumHyphenError(c, rest)
58+
case AdditionalInfo.AdditionalInfoParseError.EmptyAlphaNumHyphenError =>
59+
ParseError.emptyAlphaNumHyphenError
60+
}
61+
5262
@SuppressWarnings(Array("org.wartremover.warts.Recursion"))
5363
def render(parseError: ParseError): String = parseError match {
5464
case InvalidAlphaNumHyphenError(c, rest) =>

modules/just-semver-core/shared/src/main/scala-2/just/semver/SemVer.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,11 @@ object SemVer {
135135
val metaInfo = AdditionalInfo.parseBuildMetaInfo(meta)
136136
(preRelease, metaInfo) match {
137137
case (Left(preError), Left(metaError)) =>
138-
Left(ParseError.combine(preError, metaError))
138+
Left(ParseError.combine(ParseError.fromAdditionalInfoParserError(preError), ParseError.fromAdditionalInfoParserError(metaError)))
139139
case (Left(preError), _) =>
140-
Left(ParseError.preReleaseParseError(preError))
140+
Left(ParseError.preReleaseParseError(ParseError.fromAdditionalInfoParserError(preError)))
141141
case (_, Left(metaError)) =>
142-
Left(ParseError.buildMetadataParseError(metaError))
142+
Left(ParseError.buildMetadataParseError(ParseError.fromAdditionalInfoParserError(metaError)))
143143
case (Right(preR), Right(metaI)) =>
144144
Right(
145145
SemVer(
Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package just.semver
22

3-
import just.Common._
3+
import just.Common.*
44

55
/** @author Kevin Lee
66
* @since 2018-10-21
@@ -25,49 +25,49 @@ object AdditionalInfo extends Compat {
2525
}
2626
}
2727

28-
def parsePreRelease(value: String): Either[ParseError, Option[PreRelease]] =
28+
def parsePreRelease(value: String): Either[AdditionalInfoParseError, Option[PreRelease]] =
2929
parse(
3030
value,
3131
{
3232
case a @ Dsv(Num(n) :: Nil) =>
33-
if ((n === "0") || n.takeWhile(_ === '0').length == 0)
33+
if ((n === "0") || n.takeWhile(_ === '0').length === 0)
3434
Right(a)
3535
else
36-
Left(ParseError.leadingZeroNumError(n))
36+
Left(AdditionalInfoParseError.leadingZeroNumError(n))
3737
case a @ Dsv(_) =>
3838
Right(a)
3939
}
4040
).map(_.map(PreRelease.apply))
4141

42-
def parseBuildMetaInfo(value: String): Either[ParseError, Option[BuildMetaInfo]] =
42+
def parseBuildMetaInfo(value: String): Either[AdditionalInfoParseError, Option[BuildMetaInfo]] =
4343
parse(value, Right.apply).map(_.map(BuildMetaInfo.apply))
4444

4545
def parse(
4646
value: String,
47-
validator: Dsv => Either[ParseError, Dsv]
48-
): Either[ParseError, Option[List[Dsv]]] = {
49-
val alphaNumHyphens: Either[ParseError, List[Dsv]] =
47+
validator: Dsv => Either[AdditionalInfoParseError, Dsv]
48+
): Either[AdditionalInfoParseError, Option[List[Dsv]]] = {
49+
val alphaNumHyphens: Either[AdditionalInfoParseError, List[Dsv]] =
5050
Option(value)
51-
.flatMap { s =>
52-
Option(s.split("\\.")).map { array =>
53-
array.nn.toList.collect {
54-
case s: String =>
55-
s
56-
}
57-
}
58-
}
51+
.map(_.split("\\."))
5952
.map(_.map(Dsv.parse)) match {
6053
case Some(preRelease) =>
61-
preRelease.foldRight(List.empty[Dsv].asRight[ParseError]) { (x, acc) =>
62-
x.flatMap(validator) match {
54+
preRelease.foldRight(List.empty[Dsv].asRight[AdditionalInfoParseError]) { (x, acc) =>
55+
x.left
56+
.map {
57+
case Dsv.DsvParseError.InvalidAlphaNumHyphenError(c, rest) =>
58+
AdditionalInfoParseError.invalidAlphaNumHyphenError(c, rest)
59+
case Dsv.DsvParseError.EmptyAlphaNumHyphenError =>
60+
AdditionalInfoParseError.emptyAlphaNumHyphenError
61+
}
62+
.flatMap(validator) match {
6363
case Right(alp) =>
6464
acc.map(alps => alp :: alps)
6565
case Left(error) =>
6666
error.asLeft[List[Dsv]]
6767
}
6868
}
6969
case None =>
70-
List.empty[Dsv].asRight[ParseError]
70+
List.empty[Dsv].asRight[AdditionalInfoParseError]
7171
}
7272
alphaNumHyphens.map {
7373
case Nil =>
@@ -76,4 +76,20 @@ object AdditionalInfo extends Compat {
7676
xs.some
7777
}
7878
}
79+
80+
sealed trait AdditionalInfoParseError
81+
object AdditionalInfoParseError {
82+
final case class LeadingZeroNumError(n: String) extends AdditionalInfoParseError
83+
84+
final case class InvalidAlphaNumHyphenError(c: Char, rest: List[Char]) extends AdditionalInfoParseError
85+
case object EmptyAlphaNumHyphenError extends AdditionalInfoParseError
86+
87+
def leadingZeroNumError(n: String): AdditionalInfoParseError = LeadingZeroNumError(n)
88+
89+
def invalidAlphaNumHyphenError(c: Char, rest: List[Char]): AdditionalInfoParseError =
90+
InvalidAlphaNumHyphenError(c, rest)
91+
92+
def emptyAlphaNumHyphenError: AdditionalInfoParseError = EmptyAlphaNumHyphenError
93+
}
94+
7995
}

0 commit comments

Comments
 (0)