diff --git a/build.sbt b/build.sbt
index 00356db6..a59d5f34 100644
--- a/build.sbt
+++ b/build.sbt
@@ -6,15 +6,15 @@ val repo = "git@github.com:jto/validation.git"
val org = "io.github.jto"
val license = ("Apache License", url("http://www.apache.org/licenses/LICENSE-2.0.txt"))
-val catsVersion = "1.2.0"
-val jodaConvertVersion = "2.1.1"
-val jodaTimeVersion = "2.10"
-val kindProjectorVersion = "0.9.7"
-val parserCombinatorsVersion = "1.1.1"
-val playVersion = "2.6.3"
-val scalacVersion = "2.12.6"
-val scalatestVersion = "3.2.0-SNAP10"
-val scalaXmlVersion = "1.1.0"
+val catsVersion = "2.0.0"
+val jodaConvertVersion = "2.2.1"
+val jodaTimeVersion = "2.10.4"
+val kindProjectorVersion = "0.10.3"
+val parserCombinatorsVersion = "1.1.2"
+val playVersion = "2.7.4"
+val scalacVersion = "2.13.0"
+val scalatestVersion = "3.0.8"
+val scalaXmlVersion = "1.2.0"
lazy val root = aggregate("validation", validationJVM, validationJS, docs).in(file("."))
lazy val validationJVM = aggregate("validationJVM", coreJVM, formJVM, delimitedJVM, jsonAstJVM, `validation-playjson`, `validation-xml`, `date-tests`)
@@ -25,6 +25,7 @@ lazy val `validation-core` =
.crossType(CrossType.Pure)
.settings(validationSettings: _*)
.settings(generateBoilerplate: _*)
+ .settings(libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value)
lazy val coreJVM = `validation-core`.jvm
lazy val coreJS = `validation-core`.js
lazy val core = aggregate("validation-core", coreJVM, coreJS)
@@ -111,16 +112,17 @@ lazy val validationSettings = settings ++ dependencies ++ doPublish ++ scoverage
lazy val settings = Seq(
scalaVersion := scalacVersion,
- crossScalaVersions := Seq(scalacVersion, "2.11.12"),
+ crossScalaVersions := Seq(scalacVersion, "2.12.10", "2.11.12"),
organization := org,
scalacOptions ++= commonScalacOptions,
scalacOptions in (Compile, console) ~= (_ filterNot (_ == "-Ywarn-unused-import")),
scalacOptions in (Test, console) := (scalacOptions in (Compile, console)).value.filterNot(_ == "-Xfatal-warnings"),
+ scalacOptions -= "-Xfatal-warnings",
resolvers ++= commonResolvers,
testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-oDF"),
scalaJSStage in Global := FastOptStage,
parallelExecution := false,
- libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.14.0" % "test"
+ libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.14.1" % "test"
)
val commonScalacOptions = Seq(
@@ -136,13 +138,11 @@ val commonScalacOptions = Seq(
"-Xfatal-warnings",
"-Xlint",
// "-Yinline-warnings",
- "-Yno-adapted-args",
"-Ywarn-dead-code",
"-Ywarn-numeric-widen",
"-Ywarn-value-discard",
- "-Ywarn-unused-import",
"-Xfuture",
- "-Ypartial-unification"
+ //"-Ypartial-unification"
)
val commonResolvers = Seq(
@@ -157,7 +157,7 @@ val dependencies = Seq(
"joda-time" % "joda-time" % jodaTimeVersion,
"org.joda" % "joda-convert" % jodaConvertVersion
),
- addCompilerPlugin("org.spire-math" %% "kind-projector" % kindProjectorVersion)
+ addCompilerPlugin("org.typelevel" %% "kind-projector" % kindProjectorVersion)
)
val generateBoilerplate = Seq(
diff --git a/project/build.properties b/project/build.properties
index 5620cc50..8522443d 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=1.2.1
+sbt.version=1.3.2
diff --git a/project/plugins.sbt b/project/plugins.sbt
index e2ca7f44..6def02a7 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,15 +1,28 @@
resolvers += Resolver.url(
"tpolecat-sbt-plugin-releases",
- url("http://dl.bintray.com/content/tpolecat/sbt-plugin-releases"))(
+ url("https://dl.bintray.com/content/tpolecat/sbt-plugin-releases"))(
Resolver.ivyStylePatterns)
-addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.6.7")
+addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.6.12")
+
+addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.6.1")
+
+addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.29")
+
+addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.5.1")
+
+addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.0")
+
+addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.2.7")
+
+addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.4.2")
+
+addSbtPlugin("org.wartremover" % "sbt-wartremover" % "2.4.3")
+
+addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.8")
+
+addSbtPlugin("org.duhemm" % "sbt-errors-summary" % "0.6.3")
-addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.6.0")
-addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.24")
-addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.15")
-addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.5.1")
-addSbtPlugin("org.scoverage" % "sbt-coveralls" % "1.2.5")
\ No newline at end of file
diff --git a/validation-core/src/main/scala/Formatter.scala b/validation-core/src/main/scala/Formatter.scala
index 8e945c66..1cff4a90 100644
--- a/validation-core/src/main/scala/Formatter.scala
+++ b/validation-core/src/main/scala/Formatter.scala
@@ -65,7 +65,7 @@ object To {
w.writes(o)
}
-case class Reader[I](path: Path = Path(Nil)) {
+final case class Reader[I](path: Path = Path(Nil)) {
/**
* When applied, the rule will lookup for data at the given path, and apply the `sub` Rule on it
@@ -112,7 +112,7 @@ case class Reader[I](path: Path = Path(Nil)) {
def \(child: PathNode): Reader[I] = Reader(path \ child)
}
-case class Writer[I](path: Path = Path(Nil)) {
+final case class Writer[I](path: Path = Path(Nil)) {
/**
* Create a Write that convert data to type `I`, and put it at Path `path`
@@ -156,7 +156,7 @@ object Formatting {
def apply[IR, IW] = new Formatting[IR, IW] {}
}
-case class Formatter[IR, IW](path: Path = Path(Nil)) {
+final case class Formatter[IR, IW](path: Path = Path(Nil)) {
def format[JJ, J, O](subR: => RuleLike[J, O], subW: => WriteLike[O, JJ])(
implicit r: Path => RuleLike[IR, J],
diff --git a/validation-core/src/main/scala/Path.scala b/validation-core/src/main/scala/Path.scala
index 67bea24d..ba820a80 100644
--- a/validation-core/src/main/scala/Path.scala
+++ b/validation-core/src/main/scala/Path.scala
@@ -1,11 +1,11 @@
package jto.validation
sealed trait PathNode
-case class KeyPathNode(key: String) extends PathNode {
+final case class KeyPathNode(key: String) extends PathNode {
override def toString = key
}
-case class IdxPathNode(idx: Int) extends PathNode {
+final case class IdxPathNode(idx: Int) extends PathNode {
override def toString = s"[$idx]"
}
diff --git a/validation-core/src/main/scala/SyntaxObs.scala b/validation-core/src/main/scala/SyntaxObs.scala
index fb40327e..31c51be1 100644
--- a/validation-core/src/main/scala/SyntaxObs.scala
+++ b/validation-core/src/main/scala/SyntaxObs.scala
@@ -1,6 +1,6 @@
package jto.validation
-case class ~[A, B](_1: A, _2: B)
+final case class ~[A, B](_1: A, _2: B)
trait SyntaxCombine[M[_]] {
def apply[A, B](ma: M[A], mb: M[B]): M[A ~ B]
diff --git a/validation-core/src/main/scala/ValidationError.scala b/validation-core/src/main/scala/ValidationError.scala
index df4caf0b..92961637 100644
--- a/validation-core/src/main/scala/ValidationError.scala
+++ b/validation-core/src/main/scala/ValidationError.scala
@@ -6,7 +6,7 @@ package jto.validation
* @param message the error message
* @param args the error message arguments
*/
-case class ValidationError(messages: Seq[String], args: Any*) {
+final case class ValidationError(messages: Seq[String], args: Any*) {
lazy val message = messages.last
}
diff --git a/validation-delimited/src/test/scala/RulesSpec.scala b/validation-delimited/src/test/scala/RulesSpec.scala
index 65fee8c5..bf0fc30f 100644
--- a/validation-delimited/src/test/scala/RulesSpec.scala
+++ b/validation-delimited/src/test/scala/RulesSpec.scala
@@ -6,7 +6,7 @@ import org.scalatest._
class RulesSpec extends WordSpec with Matchers {
"Rules" should {
"demonstrate typical usage" in {
- case class Contact(name: String, email: String, birthday: Option[String])
+ final case class Contact(name: String, email: String, birthday: Option[String])
val contactReads = From[Delimited] { __ =>
(
diff --git a/validation-form/src/main/scala/Writes.scala b/validation-form/src/main/scala/Writes.scala
index 1014293d..3d116843 100644
--- a/validation-form/src/main/scala/Writes.scala
+++ b/validation-form/src/main/scala/Writes.scala
@@ -34,7 +34,7 @@ trait Writes
implicit def mapW[I](implicit w: WriteLike[I, Seq[String]]) =
Write[Map[String, I], PM] { m =>
- toPM(m.mapValues(w.writes))
+ toPM(m.map { case (k,v) => k -> w.writes(v) } )
}
implicit def spm[O](implicit w: WriteLike[O, PM]) =
diff --git a/validation-form/src/test/scala/FormatSpec.scala b/validation-form/src/test/scala/FormatSpec.scala
index e0cd47b1..e2a6a828 100644
--- a/validation-form/src/test/scala/FormatSpec.scala
+++ b/validation-form/src/test/scala/FormatSpec.scala
@@ -4,7 +4,7 @@ import org.scalatest._
import scala.Function.unlift
class FormatSpec extends WordSpec with Matchers {
- case class User(id: Long, name: String)
+ final case class User(id: Long, name: String)
val luigi = User(1, "Luigi")
"Format" should {
@@ -389,7 +389,7 @@ class FormatSpec extends WordSpec with Matchers {
}
"format recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m = Map("name" -> Seq("bob"),
diff --git a/validation-form/src/test/scala/MacroSpec.scala b/validation-form/src/test/scala/MacroSpec.scala
index 92080650..33d84c3d 100644
--- a/validation-form/src/test/scala/MacroSpec.scala
+++ b/validation-form/src/test/scala/MacroSpec.scala
@@ -2,28 +2,28 @@ import jto.validation._
import jto.validation.forms._
import org.scalatest._
-case class User(age: Int, name: String)
-case class Dog(name: String, master: User)
-case class Cat(name: String)
-case class RecUser(name: String,
+final case class User(age: Int, name: String)
+final case class Dog(name: String, master: User)
+final case class Cat(name: String)
+final case class RecUser(name: String,
cat: Option[Cat] = None,
hobbies: Seq[String] = Seq(),
friends: Seq[RecUser] = Seq())
-case class User1(name: String, friend: Option[User1] = None)
-case class UserMap(name: String, friends: Map[String, UserMap] = Map())
+final case class User1(name: String, friend: Option[User1] = None)
+final case class UserMap(name: String, friends: Map[String, UserMap] = Map())
-case class Toto(name: String)
-case class Toto2(name: Option[String])
-case class Toto3(name: List[Double])
-case class Toto4(name: Set[Long])
-case class Toto5(name: Map[String, Int])
-case class Toto6(name: Seq[Dog])
-case class UserFail(name: String, bd: Toto)
+final case class Toto(name: String)
+final case class Toto2(name: Option[String])
+final case class Toto3(name: List[Double])
+final case class Toto4(name: Set[Long])
+final case class Toto5(name: Map[String, Int])
+final case class Toto6(name: Seq[Dog])
+final case class UserFail(name: String, bd: Toto)
-case class Id[A](id: A)
-case class C1[A](id: Id[A], name: String)
+final case class Id[A](id: A)
+final case class C1[A](id: Id[A], name: String)
-case class X(
+final case class X(
_1: String,
_2: String,
_3: String,
@@ -47,7 +47,7 @@ case class X(
_21: String
)
-case class Program(id: Long,
+final case class Program(id: Long,
name: String,
logoPath: Option[String],
logoThumb: Option[String])
@@ -55,7 +55,7 @@ object Program {
def programs = List.empty[Program]
}
-case class Person(name: String, age: Int)
+final case class Person(name: String, age: Int)
object Person {
implicit val personRule = {
import Rules._
@@ -67,7 +67,7 @@ object Person {
}
}
-case class Person2(names: List[String])
+final case class Person2(names: List[String])
object Person2 {
implicit val personRule = {
diff --git a/validation-form/src/test/scala/RulesSpec.scala b/validation-form/src/test/scala/RulesSpec.scala
index c72d80c0..b0f768c7 100644
--- a/validation-form/src/test/scala/RulesSpec.scala
+++ b/validation-form/src/test/scala/RulesSpec.scala
@@ -450,9 +450,9 @@ class RulesSpec extends WordSpec with Matchers {
"validate subclasses (and parse the concrete class)" when {
- trait A
- case class B(foo: Int) extends A
- case class C(bar: Int) extends A
+ sealed trait A
+ final case class B(foo: Int) extends A
+ final case class C(bar: Int) extends A
val b = Map("name" -> Seq("B"), "foo" -> Seq("4"))
val c = Map("name" -> Seq("C"), "bar" -> Seq("6"))
@@ -498,12 +498,12 @@ class RulesSpec extends WordSpec with Matchers {
}
"perform complex validation" in {
- case class Contact(firstname: String,
+ final case class Contact(firstname: String,
lastname: String,
company: Option[String],
informations: Seq[ContactInformation])
- case class ContactInformation(
+ final case class ContactInformation(
label: String, email: Option[String], phones: Seq[String])
val validM = Map("firstname" -> Seq("Julien"),
@@ -596,14 +596,14 @@ class RulesSpec extends WordSpec with Matchers {
}
"read recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m = Map("name" -> Seq("bob"),
"friends[0].name" -> Seq("tom"),
"friends[0].friends" -> Seq())
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = Map("name" -> Seq("bob"), "friend.name" -> Seq("tom"))
diff --git a/validation-form/src/test/scala/WritesSpec.scala b/validation-form/src/test/scala/WritesSpec.scala
index 7311a348..a5aa573e 100644
--- a/validation-form/src/test/scala/WritesSpec.scala
+++ b/validation-form/src/test/scala/WritesSpec.scala
@@ -5,12 +5,12 @@ import scala.Function.unlift
class WritesSpec extends WordSpec with Matchers {
- case class Contact(firstname: String,
+ final case class Contact(firstname: String,
lastname: String,
company: Option[String],
informations: Seq[ContactInformation])
- case class ContactInformation(
+ final case class ContactInformation(
label: String, email: Option[String], phones: Seq[String])
val contact = Contact(
@@ -53,7 +53,7 @@ class WritesSpec extends WordSpec with Matchers {
"n" -> Seq("5"))
(Path \ "n").write(optionW(intW)).writes(None) shouldBe Map.empty
- case class Foo(name: String)
+ final case class Foo(name: String)
implicit val wf =
(Path \ "name").write[String, UrlFormEncoded].contramap((_: Foo).name)
val wmf = (Path \ "maybe").write[Option[Foo], UrlFormEncoded]
@@ -346,12 +346,12 @@ class WritesSpec extends WordSpec with Matchers {
}
"write recursive" when {
- case class RecUser(name: String, friends: List[RecUser] = Nil)
+ final case class RecUser(name: String, friends: List[RecUser] = Nil)
val u = RecUser("bob", List(RecUser("tom")))
val m = Map("name" -> Seq("bob"), "friends[0].name" -> Seq("tom"))
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = Map("name" -> Seq("bob"), "friend.name" -> Seq("tom"))
@@ -404,7 +404,7 @@ class WritesSpec extends WordSpec with Matchers {
}
object TestValueClass {
- case class Id(value: String) extends AnyVal
+ final case class Id(value: String) extends AnyVal
object Id {
implicit val writes: Write[Id, String] = Write(id => id.value)
}
diff --git a/validation-jsjson/src/main/scala/Rules.scala b/validation-jsjson/src/main/scala/Rules.scala
index 7ade375e..470ded7a 100644
--- a/validation-jsjson/src/main/scala/Rules.scala
+++ b/validation-jsjson/src/main/scala/Rules.scala
@@ -12,7 +12,7 @@ trait Rules extends DefaultRules[js.Dynamic] {
case j => Invalid(Seq(ValidationError(msg, args: _*)))
})
- implicit def stringR =
+ implicit def stringR: Rule[js.Dynamic, String] =
jsonAs[String] {
case v if (v: Any).isInstanceOf[String] => Valid(v.asInstanceOf[String])
}("error.invalid", "String")
@@ -46,29 +46,29 @@ trait Rules extends DefaultRules[js.Dynamic] {
Valid(v.asInstanceOf[js.Dictionary[js.Dynamic]])
}("error.invalid", "Object")
- implicit def jsArrayR[A] =
+ implicit def jsArrayR[A]: Rule[js.Dynamic, js.Array[A]] =
jsonAs[js.Array[A]] {
case v: js.Array[_] => Valid(v.asInstanceOf[js.Array[A]])
}("error.invalid", "Array")
- implicit def floatR =
+ implicit def floatR: Rule[js.Dynamic, Float] =
jsonAs[Float] {
case v if v.isInstanceOf[Float] => Valid(v.asInstanceOf[Float])
}("error.number", "Float")
- implicit def doubleR =
+ implicit def doubleR: Rule[js.Dynamic, Double] =
jsonAs[Double] {
case v if v.isInstanceOf[Double] => Valid(v.asInstanceOf[Double])
}("error.number", "Double")
- implicit def bigDecimal =
+ implicit def bigDecimal: Rule[js.Dynamic, BigDecimal] =
jsonAs[BigDecimal] {
case v if Try(BigDecimal(v.toString)).isSuccess =>
Valid(BigDecimal(v.toString))
}("error.number", "BigDecimal")
import java.{math => jm}
- implicit def javaBigDecimal =
+ implicit def javaBigDecimal: Rule[js.Dynamic, java.math.BigDecimal] =
jsonAs[jm.BigDecimal] {
case v if Try(new jm.BigDecimal(v.toString)).isSuccess =>
Valid(new jm.BigDecimal(v.toString))
@@ -129,7 +129,7 @@ trait Rules extends DefaultRules[js.Dynamic] {
// XXX: a bit of boilerplate
private def pickInS[T](
implicit r: RuleLike[Seq[js.Dynamic], T]): Rule[js.Dynamic, T] =
- jsArrayR[js.Dynamic].map(fs => Seq(fs: _*)).andThen(r)
+ jsArrayR[js.Dynamic].map(_.toSeq).andThen(r)
implicit def pickSeq[O](implicit r: RuleLike[js.Dynamic, O]) =
pickInS(seqR[js.Dynamic, O])
implicit def pickSet[O](implicit r: RuleLike[js.Dynamic, O]) =
diff --git a/validation-jsjson/src/test/scala/FormatSpec.scala b/validation-jsjson/src/test/scala/FormatSpec.scala
index 32a38b1b..8f99eb01 100644
--- a/validation-jsjson/src/test/scala/FormatSpec.scala
+++ b/validation-jsjson/src/test/scala/FormatSpec.scala
@@ -1,3 +1,7 @@
+package jto.validation
+package jsjson
+package test
+
import jto.validation._
import jto.validation.jsjson.Rules._
import jto.validation.jsjson.Writes._
@@ -5,9 +9,9 @@ import org.scalatest._
import scala.scalajs.js
import scala.Function.unlift
-class FormatSpec extends WordSpec with Matchers with JsAnyEquality {
+final class FormatSpec extends WordSpec with Matchers with JsAnyEquality {
- case class User(id: Long, name: String)
+ final case class User(id: Long, name: String)
val luigi = User(1, "Luigi")
"Format" should {
@@ -362,7 +366,7 @@ class FormatSpec extends WordSpec with Matchers with JsAnyEquality {
}
"format recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m = js.Dynamic.literal(
@@ -370,7 +374,7 @@ class FormatSpec extends WordSpec with Matchers with JsAnyEquality {
"friends" -> js.Array(
js.Dynamic.literal("name" -> "tom", "friends" -> js.Array())))
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = js.Dynamic.literal(
"name" -> "bob", "friend" -> js.Dynamic.literal("name" -> "tom"))
diff --git a/validation-jsjson/src/test/scala/JsAnyEquality.scala b/validation-jsjson/src/test/scala/JsAnyEquality.scala
index f39e803a..8284298a 100644
--- a/validation-jsjson/src/test/scala/JsAnyEquality.scala
+++ b/validation-jsjson/src/test/scala/JsAnyEquality.scala
@@ -1,10 +1,33 @@
+package jto.validation
+package jsjson
+package test
+
import scala.scalajs.js
import org.scalatest._
trait JsAnyEquality {
this: Matchers =>
implicit class ShouldBeEqualAfterStringify(val dynamic: js.Any) {
+
def shouldBe(otherDynamic: js.Any): Assertion =
- js.JSON.stringify(dynamic) shouldBe js.JSON.stringify(otherDynamic)
+ (dynamic, otherDynamic) match {
+ case (d1 : js.Object, d2: js.Object) =>
+
+ def props(d: js.Object): Map[String, js.Any] =
+ d.asInstanceOf[js.Dictionary[js.Any]].toMap[String, js.Any]
+
+ val props1 = props(d1)
+ val props2 = props(d2)
+
+ (props1.keySet should ===(props2.keySet))
+ for (k <- props1.keySet) props1(k).shouldBe(props2(k))
+ succeed
+
+ case _ =>
+ js.JSON.stringify(dynamic) shouldBe js.JSON.stringify(otherDynamic)
+ }
+
+
+
}
}
diff --git a/validation-jsjson/src/test/scala/RulesSpec.scala b/validation-jsjson/src/test/scala/RulesSpec.scala
index 543bd189..840a3111 100644
--- a/validation-jsjson/src/test/scala/RulesSpec.scala
+++ b/validation-jsjson/src/test/scala/RulesSpec.scala
@@ -1,3 +1,7 @@
+package jto.validation
+package jsjson
+package test
+
import jto.validation._
import jto.validation.jsjson._
import jto.validation.jsjson.Rules._
@@ -496,9 +500,9 @@ class RulesSpec extends WordSpec with Matchers {
"validate subclasses (and parse the concrete class)" when {
- trait A
- case class B(foo: Int) extends A
- case class C(bar: Int) extends A
+ sealed trait A
+ final case class B(foo: Int) extends A
+ final case class C(bar: Int) extends A
val b = js.Dynamic.literal("name" -> "B", "foo" -> 4)
val c = js.Dynamic.literal("name" -> "C", "bar" -> 6)
diff --git a/validation-jsjson/src/test/scala/WritesSpec.scala b/validation-jsjson/src/test/scala/WritesSpec.scala
index 845e8a17..8cc66b9d 100644
--- a/validation-jsjson/src/test/scala/WritesSpec.scala
+++ b/validation-jsjson/src/test/scala/WritesSpec.scala
@@ -1,3 +1,7 @@
+package jto.validation
+package jsjson
+package test
+
import jto.validation._
import jto.validation.jsjson.Writes._
import org.scalatest._
diff --git a/validation-jsonast/js/src/main/scala/Ast.scala b/validation-jsonast/js/src/main/scala/Ast.scala
index de15dc5b..c794fd9b 100644
--- a/validation-jsonast/js/src/main/scala/Ast.scala
+++ b/validation-jsonast/js/src/main/scala/Ast.scala
@@ -7,7 +7,7 @@ import scala.scalajs.js.JSConverters._
object Ast {
val to: Write[JValue, js.Dynamic] = Write[JValue, js.Any] {
case JNull => null
- case JObject (value) => value.mapValues(to.writes).toJSDictionary
+ case JObject (value) => value.map{case (k,v) => k -> to.writes(v)}.toJSDictionary
case JArray (value) => value.map(to.writes).toJSArray
case JBoolean(value) => value
case JString (value) => value
@@ -17,7 +17,7 @@ object Ast {
}.map(_.asInstanceOf[js.Dynamic])
private val undefined = scala.scalajs.js.undefined
- private case class FunctionInJsonException(path: Path) extends Exception
+ private final case class FunctionInJsonException(path: Path) extends Exception
private def unsafeAny2JValue(input: Any, path: Path): JValue = input match {
case null => JNull
@@ -27,7 +27,7 @@ object Ast {
case `undefined` => JNull
case a: js.Array[js.Dynamic @unchecked] =>
- JArray(a.map(v => unsafeAny2JValue(v, path \ 0)))
+ JArray(a.map(v => unsafeAny2JValue(v, path \ 0)).toSeq)
case o: js.Object =>
JObject(o.asInstanceOf[js.Dictionary[js.Dynamic]]
diff --git a/validation-jsonast/jvm/src/main/scala/Ast.scala b/validation-jsonast/jvm/src/main/scala/Ast.scala
index 2644cdb2..56399e1f 100644
--- a/validation-jsonast/jvm/src/main/scala/Ast.scala
+++ b/validation-jsonast/jvm/src/main/scala/Ast.scala
@@ -6,7 +6,7 @@ import play.api.libs.json._
object Ast {
val to: Write[JValue, JsValue] = Write[JValue, JsValue] {
case JNull => JsNull
- case JObject (value) => JsObject(value.mapValues(to.writes))
+ case JObject (value) => JsObject(value.map { case (k,v) => k -> to.writes(v) })
case JArray (value) => JsArray(value.map(to.writes))
case JBoolean(value) => JsBoolean(value)
case JString (value) => JsString(value)
diff --git a/validation-jsonast/shared/src/main/scala/JValue.scala b/validation-jsonast/shared/src/main/scala/JValue.scala
index ee0f0878..454a0a16 100644
--- a/validation-jsonast/shared/src/main/scala/JValue.scala
+++ b/validation-jsonast/shared/src/main/scala/JValue.scala
@@ -2,12 +2,12 @@ package jto.validation
package jsonast
sealed trait JValue
-case object JNull extends JValue
-case class JObject (value: Map[String, JValue] = Map.empty) extends JValue
-case class JArray (value: Seq[JValue] = Seq.empty) extends JValue
-case class JBoolean(value: Boolean) extends JValue
-case class JString (value: String) extends JValue
-case class JNumber (value: String) extends JValue {
+final case object JNull extends JValue
+final case class JObject (value: Map[String, JValue] = Map.empty) extends JValue
+final case class JArray (value: Seq[JValue] = Seq.empty) extends JValue
+final case class JBoolean(value: Boolean) extends JValue
+final case class JString (value: String) extends JValue
+final case class JNumber (value: String) extends JValue {
require(JNumber.regex.matcher(value).matches)
}
diff --git a/validation-jsonast/shared/src/main/scala/Writes.scala b/validation-jsonast/shared/src/main/scala/Writes.scala
index be7c4a15..f6fbd971 100644
--- a/validation-jsonast/shared/src/main/scala/Writes.scala
+++ b/validation-jsonast/shared/src/main/scala/Writes.scala
@@ -73,7 +73,7 @@ trait Writes
implicit def mapW[I](implicit w: WriteLike[I, JValue]) =
Write[Map[String, I], JObject] { m =>
- JObject(m.mapValues(w.writes))
+ JObject(m.map { case (k,v) => k -> w.writes(v) })
}
implicit def vaW[I](implicit w: WriteLike[I, JValue]) =
diff --git a/validation-jsonast/shared/src/test/scala/AstSpec.scala b/validation-jsonast/shared/src/test/scala/AstSpec.scala
index 55b9d17a..79025572 100644
--- a/validation-jsonast/shared/src/test/scala/AstSpec.scala
+++ b/validation-jsonast/shared/src/test/scala/AstSpec.scala
@@ -1,3 +1,7 @@
+package jto.validation
+package jsonast
+package test
+
import jto.validation.Valid
import jto.validation.jsonast._
import org.scalatest._
diff --git a/validation-jsonast/shared/src/test/scala/FormatSpec.scala b/validation-jsonast/shared/src/test/scala/FormatSpec.scala
index 3629ffac..d430ea71 100644
--- a/validation-jsonast/shared/src/test/scala/FormatSpec.scala
+++ b/validation-jsonast/shared/src/test/scala/FormatSpec.scala
@@ -1,10 +1,14 @@
+package jto.validation
+package jsonast
+package test
+
import jto.validation._
import jto.validation.jsonast._
import org.scalatest._
import scala.Function.unlift
class FormatSpec extends WordSpec with Matchers {
- case class User(id: Long, name: String)
+ final case class User(id: Long, name: String)
val luigi = User(1, "Luigi")
"Format" should {
@@ -413,7 +417,7 @@ class FormatSpec extends WordSpec with Matchers {
}
"format recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m = JObject(
@@ -421,7 +425,7 @@ class FormatSpec extends WordSpec with Matchers {
"friends" -> JArray(Seq(JObject(Map("name" -> JString("tom"),
"friends" -> JArray()))))))
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = JObject(Map("name" -> JString("bob"),
"friend" -> JObject(Map("name" -> JString("tom")))))
diff --git a/validation-jsonast/shared/src/test/scala/MacroSpec.scala b/validation-jsonast/shared/src/test/scala/MacroSpec.scala
index 9ced6b76..49614d6c 100644
--- a/validation-jsonast/shared/src/test/scala/MacroSpec.scala
+++ b/validation-jsonast/shared/src/test/scala/MacroSpec.scala
@@ -1,29 +1,33 @@
+package jto.validation
+package jsonast
+package test
+
import jto.validation._
import jto.validation.jsonast._
import org.scalatest._
-case class User(age: Int, name: String)
-case class Dog(name: String, master: User)
-case class Cat(name: String)
-case class RecUser(name: String,
+final case class User(age: Int, name: String)
+final case class Dog(name: String, master: User)
+final case class Cat(name: String)
+final case class RecUser(name: String,
cat: Option[Cat] = None,
hobbies: Seq[String] = Seq(),
friends: Seq[RecUser] = Seq())
-case class User1(name: String, friend: Option[User1] = None)
-case class UserMap(name: String, friends: Map[String, UserMap] = Map())
+final case class User1(name: String, friend: Option[User1] = None)
+final case class UserMap(name: String, friends: Map[String, UserMap] = Map())
-case class Toto(name: String)
-case class Toto2(name: Option[String])
-case class Toto3(name: List[Double])
-case class Toto4(name: Set[Long])
-case class Toto5(name: Map[String, Int])
-case class Toto6(name: Seq[Dog])
-case class UserFail(name: String, bd: Toto)
+final case class Toto(name: String)
+final case class Toto2(name: Option[String])
+final case class Toto3(name: List[Double])
+final case class Toto4(name: Set[Long])
+final case class Toto5(name: Map[String, Int])
+final case class Toto6(name: Seq[Dog])
+final case class UserFail(name: String, bd: Toto)
-case class Id[A](id: A)
-case class C1[A](id: Id[A], name: String)
+final case class Id[A](id: A)
+final case class C1[A](id: Id[A], name: String)
-case class X(
+final case class X(
_1: String,
_2: String,
_3: String,
@@ -47,7 +51,7 @@ case class X(
_21: String
)
-case class Program(id: Long,
+final case class Program(id: Long,
name: String,
logoPath: Option[String],
logoThumb: Option[String])
@@ -55,7 +59,7 @@ object Program {
def programs = List.empty[Program]
}
-case class Person(name: String, age: Int)
+final case class Person(name: String, age: Int)
object Person {
implicit val personRule = {
import Rules._
@@ -67,7 +71,7 @@ object Person {
}
}
-case class Person2(names: List[String])
+final case class Person2(names: List[String])
object Person2 {
implicit val personRule = {
@@ -80,20 +84,20 @@ object Person2 {
}
}
-case class ManyApplies(foo: String, bar: Int)
+final case class ManyApplies(foo: String, bar: Int)
object ManyApplies {
def apply(x: Option[Int]) = 9
def apply(y: String) = 4
def apply(x: String, y: String) = 10
}
-trait NotAClass
-case class AClass(foo: Int) extends NotAClass
+sealed trait NotAClass
+final case class AClass(foo: Int) extends NotAClass
object NotAClass {
def apply(x: Int): NotAClass = AClass(x)
}
-class MacroSpec extends WordSpec with Matchers {
+final class MacroSpec extends WordSpec with Matchers {
"MappingMacros" should {
"create a Rule[User]" in {
diff --git a/validation-jsonast/shared/src/test/scala/RulesSpec.scala b/validation-jsonast/shared/src/test/scala/RulesSpec.scala
index 50d70ed4..8352b258 100644
--- a/validation-jsonast/shared/src/test/scala/RulesSpec.scala
+++ b/validation-jsonast/shared/src/test/scala/RulesSpec.scala
@@ -1,3 +1,7 @@
+package jto.validation
+package jsonast
+package test
+
import jto.validation._
import jto.validation.jsonast._
import org.scalatest._
@@ -541,9 +545,9 @@ class RulesSpec extends WordSpec with Matchers {
"validate subclasses (and parse the concrete class)" when {
- trait A
- case class B(foo: Int) extends A
- case class C(bar: Int) extends A
+ sealed trait A
+ final case class B(foo: Int) extends A
+ final case class C(bar: Int) extends A
val b = JObject(Map("name" -> JString("B"), "foo" -> JNumber(4)))
val c = JObject(Map("name" -> JString("C"), "bar" -> JNumber(6)))
@@ -594,12 +598,12 @@ class RulesSpec extends WordSpec with Matchers {
"perform complex validation" in {
- case class Contact(firstname: String,
+ final case class Contact(firstname: String,
lastname: String,
company: Option[String],
informations: Seq[ContactInformation])
- case class ContactInformation(
+ final case class ContactInformation(
label: String, email: Option[String], phones: Seq[String])
val validJson = JObject(
@@ -648,14 +652,14 @@ class RulesSpec extends WordSpec with Matchers {
}
"read recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m = JObject(
Map("name" -> JString("bob"),
"friends" -> JArray(Seq(JObject(Map("name" -> JString("tom"), "friends" -> JArray()))))))
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = JObject(Map("name" -> JString("bob"),
"friend" -> JObject(Map("name" -> JString("tom")))))
diff --git a/validation-jsonast/shared/src/test/scala/WritesSpec.scala b/validation-jsonast/shared/src/test/scala/WritesSpec.scala
index 52a6f41e..a737c758 100644
--- a/validation-jsonast/shared/src/test/scala/WritesSpec.scala
+++ b/validation-jsonast/shared/src/test/scala/WritesSpec.scala
@@ -1,17 +1,21 @@
+package jto.validation
+package jsonast
+package test
+
import jto.validation._
import jto.validation.jsonast._
import jto.validation.jsonast.Writes._
import org.scalatest._
import scala.Function.unlift
-class WritesSpec extends WordSpec with Matchers {
+final class WritesSpec extends WordSpec with Matchers {
- case class Contact(firstname: String,
+ final case class Contact(firstname: String,
lastname: String,
company: Option[String],
informations: Seq[ContactInformation])
- case class ContactInformation(
+ final case class ContactInformation(
label: String, email: Option[String], phones: Seq[String])
val contact = Contact(
@@ -286,10 +290,11 @@ class WritesSpec extends WordSpec with Matchers {
}
"compose" in {
- val w = To[JObject] { __ =>
- ((__ \ "email").write[Option[String]] ~
- (__ \ "phones").write[Seq[String]]).tupled
- }
+ val w: Write[(Option[String], Seq[String]), JObject] =
+ To[JObject] { __ =>
+ ((__ \ "email").write[Option[String]] ~
+ (__ \ "phones").write[Seq[String]]).tupled
+ }
val v = Some("jto@foobar.com") -> Seq("01.23.45.67.89", "98.76.54.32.10")
@@ -339,7 +344,7 @@ class WritesSpec extends WordSpec with Matchers {
}
"write recursive" when {
- case class RecUser(name: String, friends: List[RecUser] = Nil)
+ final case class RecUser(name: String, friends: List[RecUser] = Nil)
val u = RecUser("bob", List(RecUser("tom")))
val m = JObject(
@@ -347,7 +352,7 @@ class WritesSpec extends WordSpec with Matchers {
"friends" -> JArray(Seq(JObject(Map("name" -> JString("tom"),
"friends" -> JArray()))))))
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = JObject(Map("name" -> JString("bob"),
"friend" -> JObject(Map("name" -> JString("tom")))))
@@ -408,7 +413,7 @@ class WritesSpec extends WordSpec with Matchers {
}
object TestValueClass {
- case class Id(value: String) extends AnyVal
+ final case class Id(value: String) extends AnyVal
object Id {
implicit val writes: Write[Id, JString] = Write(id => JString(id.value))
}
diff --git a/validation-playjson/src/test/scala/MacroSpec.scala b/validation-playjson/src/test/scala/MacroSpec.scala
index 68cc4481..449a3fe4 100644
--- a/validation-playjson/src/test/scala/MacroSpec.scala
+++ b/validation-playjson/src/test/scala/MacroSpec.scala
@@ -3,28 +3,28 @@ import jto.validation.playjson._
import org.scalatest._
import play.api.libs.json.{JsValue, JsObject, Json}
-case class User(age: Int, name: String)
-case class Dog(name: String, master: User)
-case class Cat(name: String)
-case class RecUser(name: String,
+final case class User(age: Int, name: String)
+final case class Dog(name: String, master: User)
+final case class Cat(name: String)
+final case class RecUser(name: String,
cat: Option[Cat] = None,
hobbies: Seq[String] = Seq(),
friends: Seq[RecUser] = Seq())
-case class User1(name: String, friend: Option[User1] = None)
-case class UserMap(name: String, friends: Map[String, UserMap] = Map())
+final case class User1(name: String, friend: Option[User1] = None)
+final case class UserMap(name: String, friends: Map[String, UserMap] = Map())
-case class Toto(name: String)
-case class Toto2(name: Option[String])
-case class Toto3(name: List[Double])
-case class Toto4(name: Set[Long])
-case class Toto5(name: Map[String, Int])
-case class Toto6(name: Seq[Dog])
-case class UserFail(name: String, bd: Toto)
+final case class Toto(name: String)
+final case class Toto2(name: Option[String])
+final case class Toto3(name: List[Double])
+final case class Toto4(name: Set[Long])
+final case class Toto5(name: Map[String, Int])
+final case class Toto6(name: Seq[Dog])
+final case class UserFail(name: String, bd: Toto)
-case class Id[A](id: A)
-case class C1[A](id: Id[A], name: String)
+final case class Id[A](id: A)
+final case class C1[A](id: Id[A], name: String)
-case class X(
+final case class X(
_1: String,
_2: String,
_3: String,
@@ -48,7 +48,7 @@ case class X(
_21: String
)
-case class Program(id: Long,
+final case class Program(id: Long,
name: String,
logoPath: Option[String],
logoThumb: Option[String])
@@ -56,7 +56,7 @@ object Program {
def programs = List.empty[Program]
}
-case class Person(name: String, age: Int)
+final case class Person(name: String, age: Int)
object Person {
implicit val personRule = {
import Rules._
@@ -68,7 +68,7 @@ object Person {
}
}
-case class Person2(names: List[String])
+final case class Person2(names: List[String])
object Person2 {
implicit val personRule = {
@@ -81,15 +81,15 @@ object Person2 {
}
}
-case class ManyApplies(foo: String, bar: Int)
+final case class ManyApplies(foo: String, bar: Int)
object ManyApplies {
def apply(x: Option[Int]) = 9
def apply(y: String) = 4
def apply(x: String, y: String) = 10
}
-trait NotAClass
-case class AClass(foo: Int) extends NotAClass
+sealed trait NotAClass
+final case class AClass(foo: Int) extends NotAClass
object NotAClass {
def apply(x: Int): NotAClass = AClass(x)
}
diff --git a/validation-playjson/src/test/scala/RulesSpec.scala b/validation-playjson/src/test/scala/RulesSpec.scala
index a868cbc2..b1d883f0 100644
--- a/validation-playjson/src/test/scala/RulesSpec.scala
+++ b/validation-playjson/src/test/scala/RulesSpec.scala
@@ -463,9 +463,9 @@ class RulesSpec extends WordSpec with Matchers {
"validate subclasses (and parse the concrete class)" when {
- trait A
- case class B(foo: Int) extends A
- case class C(bar: Int) extends A
+ sealed trait A
+ final case class B(foo: Int) extends A
+ final case class C(bar: Int) extends A
val b = Json.obj("name" -> "B", "foo" -> 4)
val c = Json.obj("name" -> "C", "bar" -> 6)
@@ -516,12 +516,12 @@ class RulesSpec extends WordSpec with Matchers {
"perform complex validation" in {
- case class Contact(firstname: String,
+ final case class Contact(firstname: String,
lastname: String,
company: Option[String],
informations: Seq[ContactInformation])
- case class ContactInformation(
+ final case class ContactInformation(
label: String, email: Option[String], phones: Seq[String])
val validJson = Json.obj(
@@ -568,7 +568,7 @@ class RulesSpec extends WordSpec with Matchers {
}
"read recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m =
@@ -576,7 +576,7 @@ class RulesSpec extends WordSpec with Matchers {
"friends" -> Seq(
Json.obj("name" -> "tom", "friends" -> Seq[JsObject]())))
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = Json.obj("name" -> "bob", "friend" -> Json.obj("name" -> "tom"))
diff --git a/validation-xml/src/test/scala/RulesSpec.scala b/validation-xml/src/test/scala/RulesSpec.scala
index c215d64c..45710643 100644
--- a/validation-xml/src/test/scala/RulesSpec.scala
+++ b/validation-xml/src/test/scala/RulesSpec.scala
@@ -311,9 +311,9 @@ class RulesSpec extends WordSpec with Matchers {
"validate subclasses (and parse the concrete class)" when {
- trait A
- case class B(foo: Int) extends A
- case class C(bar: Int) extends A
+ sealed trait A
+ final case class B(foo: Int) extends A
+ final case class C(bar: Int) extends A
val b = B4
val c = C6
@@ -366,12 +366,12 @@ class RulesSpec extends WordSpec with Matchers {
"perform complex validation" in {
- case class Contact(firstname: String,
+ final case class Contact(firstname: String,
lastname: String,
company: Option[String],
informations: ContactInformation)
- case class ContactInformation(label: String,
+ final case class ContactInformation(label: String,
email: Option[String],
phones: Seq[String])
@@ -404,7 +404,7 @@ class RulesSpec extends WordSpec with Matchers {
}
"read recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m =
@@ -417,7 +417,7 @@ class RulesSpec extends WordSpec with Matchers {
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 =
diff --git a/validation-xml/src/test/scala/WritesSpec.scala b/validation-xml/src/test/scala/WritesSpec.scala
index 38d3b7c9..f64aaace 100644
--- a/validation-xml/src/test/scala/WritesSpec.scala
+++ b/validation-xml/src/test/scala/WritesSpec.scala
@@ -7,14 +7,14 @@ import scala.Function.unlift
class WritesSpec extends WordSpec with Matchers {
- case class Contact(
+ final case class Contact(
firstname: String,
lastname: String,
company: Option[String],
informations: Seq[ContactInformation]
)
- case class ContactInformation(
+ final case class ContactInformation(
label: String,
email: Option[String],
phones: Seq[String]
@@ -181,13 +181,13 @@ class WritesSpec extends WordSpec with Matchers {
}
"write recursive" when {
- case class RecUser(name: String, friends: Seq[RecUser] = Nil)
+ final case class RecUser(name: String, friends: Seq[RecUser] = Nil)
val u = RecUser("bob", Seq(RecUser("tom")))
val m =
bobtom
- case class User1(name: String, friend: Option[User1] = None)
+ final case class User1(name: String, friend: Option[User1] = None)
val u1 = User1("bob", Some(User1("tom")))
val m1 = bobtom