diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8df29fde0..deab8f3bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: uses: codecov/codecov-action@v1 - name: Compress target directories - run: tar cf targets.tar modules/jsonpath/jvm/target modules/shapeless/js/target target modules/docs/target modules/pureconfig/jvm/target modules/core/js/target modules/core/jvm/target modules/scodec/jvm/target modules/scodec/js/target modules/shapeless/jvm/target modules/cats/js/target modules/cats/jvm/target modules/eval/jvm/target modules/scopt/jvm/target modules/scalaz/jvm/target modules/scalacheck/jvm/target modules/scalacheck/js/target modules/benchmark/target project/target + run: tar cf targets.tar modules/jsonpath/jvm/target modules/shapeless/js/target target modules/scalaxml/jvm/target modules/docs/target modules/pureconfig/jvm/target modules/core/js/target modules/core/jvm/target modules/scodec/jvm/target modules/scodec/js/target modules/shapeless/jvm/target modules/cats/js/target modules/cats/jvm/target modules/eval/jvm/target modules/scopt/jvm/target modules/scalaz/jvm/target modules/scalacheck/jvm/target modules/scalacheck/js/target modules/benchmark/target project/target - name: Upload target directories uses: actions/upload-artifact@v2 diff --git a/build.sbt b/build.sbt index ba8a7ce4c..a78414557 100644 --- a/build.sbt +++ b/build.sbt @@ -20,7 +20,6 @@ val macroParadiseVersion = "2.1.1" val pureconfigVersion = "0.16.0" val shapelessVersion = "2.3.7" val scalaCheckVersion = "1.15.4" -val scalaXml1Version = "1.3.0" val scalaXml2Version = "2.0.1" val scalazVersion = "7.3.4" val scodecVersion = "1.11.8" @@ -50,7 +49,8 @@ val moduleCrossPlatformMatrix: Map[String, List[Platform]] = Map( "scalaz" -> List(JVMPlatform), "scodec" -> List(JVMPlatform, JSPlatform), "scopt" -> List(JVMPlatform), - "shapeless" -> List(JVMPlatform, JSPlatform) + "shapeless" -> List(JVMPlatform, JSPlatform), + "scalaxml" -> List(JVMPlatform) ) val moduleCrossScalaVersionsMatrix: (String, Platform) => List[String] = { @@ -167,14 +167,11 @@ lazy val core = myCrossProject("core") libraryDependencies ++= { macroParadise(Compile).value ++ ( if (isScala3Setting.value) - Seq( - "org.scala-lang.modules" %% "scala-xml" % scalaXml2Version - ) + Seq() else Seq( scalaOrganization.value % "scala-reflect" % scalaVersion.value, - scalaOrganization.value % "scala-compiler" % scalaVersion.value, - "org.scala-lang.modules" %% "scala-xml" % scalaXml1Version + scalaOrganization.value % "scala-compiler" % scalaVersion.value ) ) ++ Seq( ("com.chuusai" %%% "shapeless" % shapelessVersion).cross(CrossVersion.for3Use2_13), @@ -290,6 +287,15 @@ lazy val shapeless = myCrossProject("shapeless") lazy val shapelessJVM = shapeless.jvm lazy val shapelessJS = shapeless.js +lazy val scalaxml = myCrossProject("scalaxml") + .dependsOn(core % "compile->compile;test->test") + .settings( + libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % scalaXml2Version, + libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % "always" + ) + +lazy val scalaxmlJVM = scalaxml.jvm + /// settings lazy val commonSettings = Def.settings( @@ -362,7 +368,26 @@ def moduleJvmSettings(name: String): Seq[Def.Setting[_]] = import com.typesafe.tools.mima.core.ProblemFilters.exclude Seq( exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Max.findValid"), - exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Min.findValid") + exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Min.findValid"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.RefType.unsafeWrapM"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.RefType.unsafeRewrapM"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.RefType.refineMF"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.StringPredicates.Xml"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.all.Xml"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.string.Xml"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.string.xmlNonEmptyInference"), + exclude[DirectMissingMethodProblem]("eu.timepit.refined.util.string.xml"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$ConstructorNames"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$ConstructorNames$"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$FieldNames"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$FieldNames$"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$Subtype"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$Subtype$"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$Supertype"), + exclude[MissingClassProblem]("eu.timepit.refined.generic$Supertype$"), + exclude[MissingClassProblem]("eu.timepit.refined.internal.RefineMFullyApplied"), + exclude[MissingClassProblem]("eu.timepit.refined.string$Xml$"), + exclude[MissingClassProblem]("eu.timepit.refined.string$Xml") ) } ) diff --git a/latestVersion.sbt b/latestVersion.sbt index 8f5670375..2c103d138 100644 --- a/latestVersion.sbt +++ b/latestVersion.sbt @@ -53,4 +53,5 @@ ThisBuild / bincompatVersions := Map( ThisBuild / unreleasedModules := Set( // Example: // "refined-eval" + "refined-scalaxml" ) diff --git a/modules/core/jvm/src/test/scala/eu/timepit/refined/StringValidateSpecJvm.scala b/modules/core/jvm/src/test/scala/eu/timepit/refined/StringValidateSpecJvm.scala index 23ff4e312..c2cc7f828 100644 --- a/modules/core/jvm/src/test/scala/eu/timepit/refined/StringValidateSpecJvm.scala +++ b/modules/core/jvm/src/test/scala/eu/timepit/refined/StringValidateSpecJvm.scala @@ -21,15 +21,6 @@ class StringValidateSpecJvm extends Properties("StringValidate") { showResult[Url]("htp://example.com") ?= "Url predicate failed: unknown protocol: htp" } - property("Xml.isValid") = secure { - isValid[Xml]("") - } - - property("Xml.showResult") = secure { - showResult[Xml]("") ?= - "Xml predicate failed: XML document structures must start and end within the same entity." - } - property("XPath.isValid") = secure { isValid[XPath]("A//B/*[1]") } diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala index d7beae2db..66008b9b5 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala @@ -8,7 +8,6 @@ import eu.timepit.refined.generic.Equal import eu.timepit.refined.internal.Resources import eu.timepit.refined.numeric.{GreaterEqual, Interval} import shapeless.Witness -import shapeless.nat.{_0, _1} /** Module for collection predicates. */ object collection extends CollectionInference { @@ -87,7 +86,7 @@ object collection extends CollectionInference { * Predicate that checks if the size of an `Iterable` is less than * or equal to `N`. */ - type MaxSize[N] = Size[Interval.Closed[_0, N]] + type MaxSize[N] = Size[Interval.Closed[0, N]] /** Predicate that checks if an `Iterable` is not empty. */ type NonEmpty = Not[Empty] @@ -344,7 +343,7 @@ private[refined] trait CollectionInference { p1.adapt("sizeInference(%s)") implicit def sizeGreaterEqual1NonEmptyInference[A](implicit - p1: A ==> GreaterEqual[_1] + p1: A ==> GreaterEqual[1] ): Size[A] ==> NonEmpty = p1.adapt("sizeGreaterEqual1NonEmptyInference(%s)") } diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/generic.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/generic.scala deleted file mode 100644 index 424152213..000000000 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/generic.scala +++ /dev/null @@ -1,79 +0,0 @@ -package eu.timepit.refined - -import eu.timepit.refined.api.{Inference, Validate} -import eu.timepit.refined.api.Inference.==> -import eu.timepit.refined.generic._ -import eu.timepit.refined.internal.WitnessAs - -/** Module for generic predicates. */ -object generic extends GenericInference { - - /** Predicate that checks if a value is equal to `U`. */ - final case class Equal[U](u: U) - - @deprecated( - "Deprecated because ConstructorNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - final case class ConstructorNames[P](p: P) - - @deprecated( - "Deprecated because FieldNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - final case class FieldNames[P](p: P) - - @deprecated( - "The Subtype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - final case class Subtype[U]() - - @deprecated( - "The Supertype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - final case class Supertype[U]() - - object Equal { - implicit def equalValidate[T, U](implicit - wu: WitnessAs[U, T] - ): Validate.Plain[T, Equal[U]] = - Validate.fromPredicate(_ == wu.snd, t => s"($t == ${wu.snd})", Equal(wu.fst)) - } - - @deprecated( - "The Subtype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - object Subtype { - @deprecated( - "The Subtype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - implicit def subtypeValidate[T, U >: T]: Validate.Plain[T, Subtype[U]] = - Validate.alwaysPassed(Subtype()) - } - - @deprecated( - "The Supertype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - object Supertype { - @deprecated( - "The Supertype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - implicit def supertypeValidate[T, U <: T]: Validate.Plain[T, Supertype[U]] = - Validate.alwaysPassed(Supertype()) - } -} - -private[refined] trait GenericInference { - - implicit def equalValidateInference[T, U, P](implicit - v: Validate[T, P], - wu: WitnessAs[U, T] - ): Equal[U] ==> P = - Inference(v.isValid(wu.snd), s"equalValidateInference(${v.showExpr(wu.snd)})") -} diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala index 63b7c7466..8bc88e3e6 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/internal/WitnessAs.scala @@ -28,6 +28,11 @@ final case class WitnessAs[A, B](fst: A, snd: B) object WitnessAs extends WitnessAs1 { def apply[A, B](implicit ev: WitnessAs[A, B]): WitnessAs[A, B] = ev + @deprecated( + "Support for shapeless.Nat as arguments for predicates has been deprecated. " + + "Use Int literals for any base type or Double literals for fractional base types instead.", + "0.10.0" + ) implicit def natWitnessAs[B, A <: Nat](implicit wa: Witness.Aux[A], ta: ToInt[A], diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala index c4c10337d..45add1d0f 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala @@ -7,7 +7,6 @@ import eu.timepit.refined.internal.ToInt import eu.timepit.refined.internal.WitnessAs import eu.timepit.refined.numeric._ import shapeless.Nat -import shapeless.nat.{_0, _2} /** * Module for numeric predicates. @@ -50,25 +49,25 @@ object numeric extends NumericInference { type GreaterEqual[N] = Not[Less[N]] /** Predicate that checks if a numeric value is positive (> 0). */ - type Positive = Greater[_0] + type Positive = Greater[0] /** Predicate that checks if a numeric value is zero or negative (<= 0). */ type NonPositive = Not[Positive] /** Predicate that checks if a numeric value is negative (< 0). */ - type Negative = Less[_0] + type Negative = Less[0] /** Predicate that checks if a numeric value is zero or positive (>= 0). */ type NonNegative = Not[Negative] /** Predicate that checks if an integral value is evenly divisible by `N`. */ - type Divisible[N] = Modulo[N, _0] + type Divisible[N] = Modulo[N, 0] /** Predicate that checks if an integral value is not evenly divisible by `N`. */ type NonDivisible[N] = Not[Divisible[N]] /** Predicate that checks if an integral value is evenly divisible by 2. */ - type Even = Divisible[_2] + type Even = Divisible[2] /** Predicate that checks if an integral value is not evenly divisible by 2. */ type Odd = Not[Even] @@ -135,6 +134,11 @@ private[refined] trait NumericInference { ): Less[A] ==> Less[B] = Inference(nc.lt(wa.snd, wb.snd), s"lessInference(${wa.snd}, ${wb.snd})") + @deprecated( + "Support for shapeless.Nat as arguments for predicates has been deprecated. " + + "Use Int literals for any base type or Double literals for fractional base types instead.", + "0.10.0" + ) implicit def lessInferenceNat[A <: Nat, B <: Nat](implicit ta: ToInt[A], tb: ToInt[B] @@ -148,6 +152,11 @@ private[refined] trait NumericInference { ): Greater[A] ==> Greater[B] = Inference(nc.gt(wa.snd, wb.snd), s"greaterInference(${wa.snd}, ${wb.snd})") + @deprecated( + "Support for shapeless.Nat as arguments for predicates has been deprecated. " + + "Use Int literals for any base type or Double literals for fractional base types instead.", + "0.10.0" + ) implicit def greaterInferenceNat[A <: Nat, B <: Nat](implicit ta: ToInt[A], tb: ToInt[B] diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/string.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/string.scala index 5e473565c..34dc7aa77 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/string.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/string.scala @@ -63,9 +63,6 @@ object string extends StringInference { /** Predicate that checks if a `String` is a parsable `BigDecimal`. */ final case class ValidBigDecimal() - /** Predicate that checks if a `String` is well-formed XML. */ - final case class Xml() - /** Predicate that checks if a `String` is a valid XPath expression. */ final case class XPath() @@ -230,11 +227,6 @@ object string extends StringInference { Validate.fromPartial(BigDecimal(_), "ValidBigDecimal", ValidBigDecimal()) } - object Xml { - implicit def xmlValidate: Validate.Plain[String, Xml] = - Validate.fromPartial(scala.xml.XML.loadString, "Xml", Xml()) - } - object XPath { implicit def xpathValidate: Validate.Plain[String, XPath] = Validate.fromPartial( @@ -295,9 +287,6 @@ private[refined] trait StringInference { implicit def validBigDecimalNonEmptyInference: ValidBigDecimal ==> NonEmpty = Inference.alwaysValid("validBigDecimalNonEmptyInference") - implicit def xmlNonEmptyInference: Xml ==> NonEmpty = - Inference.alwaysValid("xmlNonEmptyInference") - implicit def xPathNonEmptyInference: XPath ==> NonEmpty = Inference.alwaysValid("xPathNonEmptyInference") } diff --git a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala index 025fd281f..5b678caf8 100644 --- a/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala +++ b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/types/string.scala @@ -4,7 +4,6 @@ import eu.timepit.refined.api.{Refined, RefinedType, RefinedTypeOps} import eu.timepit.refined.collection.{MaxSize, NonEmpty, Size} import eu.timepit.refined.numeric.Interval import eu.timepit.refined.string.{HexStringSpec, Trimmed} -import shapeless.Nat._1 /** Module for `String` refined types. */ object string { @@ -59,7 +58,7 @@ object string { object NonEmptyString extends RefinedTypeOps[NonEmptyString, String] /** A `String` that is not empty with length less than or equal to `N`. */ - type NonEmptyFiniteString[N] = String Refined Size[Interval.Closed[_1, N]] + type NonEmptyFiniteString[N] = String Refined Size[Interval.Closed[1, N]] object NonEmptyFiniteString { class NonEmptyFiniteStringOps[N <: Int](implicit diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/api/RefType.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/api/RefType.scala index acfd208fb..9479b74c8 100644 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/api/RefType.scala +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/api/RefType.scala @@ -1,7 +1,6 @@ package eu.timepit.refined.api import eu.timepit.refined.internal._ -import scala.reflect.macros.blackbox import shapeless.tag.@@ /** @@ -24,24 +23,6 @@ trait RefType[F[_, _]] extends Serializable { def unsafeRewrap[T, A, B](ta: F[T, A]): F[T, B] - @deprecated( - "unsafeWrapM has been deprecated in favor of the non-macro variant unsafeWrap", - "0.9.16" - ) - def unsafeWrapM[T: c.WeakTypeTag, P: c.WeakTypeTag]( - c: blackbox.Context - )(t: c.Expr[T]): c.Expr[F[T, P]] = - c.universe.reify(unsafeWrap(t.splice)) - - @deprecated( - "unsafeRewrapM has been deprecated in favor of the non-macro variant unsafeRewrap", - "0.9.16" - ) - def unsafeRewrapM[T: c.WeakTypeTag, A: c.WeakTypeTag, B: c.WeakTypeTag]( - c: blackbox.Context - )(ta: c.Expr[F[T, A]]): c.Expr[F[T, B]] = - c.universe.reify(unsafeRewrap(ta.splice)) - /** * Returns a value of type `T` refined as `F[T, P]` on the right if * it satisfies the predicate `P`, or an error message on the left @@ -83,14 +64,6 @@ trait RefType[F[_, _]] extends Serializable { def refineM[P]: RefineMPartiallyApplied[F, P] = new RefineMPartiallyApplied - @deprecated( - "refineMF has been replaced in favor or RefinedTypeOps. " + - "Replace 'RefType[F].refineMF[T, P]' with 'new RefinedTypeOps[F[T, P], T]'.", - "0.9.1" - ) - def refineMF[T, P]: RefineMFullyApplied[F, T, P] = - new RefineMFullyApplied - def mapRefine[T, P, U]( tp: F[T, P] )(f: T => U)(implicit v: Validate[U, P]): Either[String, F[U, P]] = diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala index e3fd386f2..96e17f2b4 100644 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala @@ -8,7 +8,6 @@ import eu.timepit.refined.generic.Equal import eu.timepit.refined.internal.Resources import eu.timepit.refined.numeric.{GreaterEqual, Interval} import shapeless.Witness -import shapeless.nat.{_0, _1} /** Module for collection predicates. */ object collection extends CollectionInference { @@ -87,7 +86,7 @@ object collection extends CollectionInference { * Predicate that checks if the size of an `Iterable` is less than * or equal to `N`. */ - type MaxSize[N] = Size[Interval.Closed[_0, N]] + type MaxSize[N] = Size[Interval.Closed[W.`0`.T, N]] /** Predicate that checks if an `Iterable` is not empty. */ type NonEmpty = Not[Empty] @@ -344,7 +343,7 @@ private[refined] trait CollectionInference { p1.adapt("sizeInference(%s)") implicit def sizeGreaterEqual1NonEmptyInference[A](implicit - p1: A ==> GreaterEqual[_1] + p1: A ==> GreaterEqual[W.`1`.T] ): Size[A] ==> NonEmpty = p1.adapt("sizeGreaterEqual1NonEmptyInference(%s)") } diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/generic.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/generic.scala deleted file mode 100644 index db31baf59..000000000 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/generic.scala +++ /dev/null @@ -1,128 +0,0 @@ -package eu.timepit.refined - -import eu.timepit.refined.api.{Inference, Validate} -import eu.timepit.refined.api.Inference.==> -import eu.timepit.refined.generic._ -import eu.timepit.refined.internal.WitnessAs -import shapeless._ -import shapeless.ops.coproduct.ToHList -import shapeless.ops.hlist.ToList -import shapeless.ops.record.Keys - -/** Module for generic predicates. */ -object generic extends GenericInference { - - /** Predicate that checks if a value is equal to `U`. */ - final case class Equal[U](u: U) - - @deprecated( - "Deprecated because ConstructorNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - final case class ConstructorNames[P](p: P) - - @deprecated( - "Deprecated because FieldNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - final case class FieldNames[P](p: P) - - @deprecated( - "The Subtype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - final case class Subtype[U]() - - @deprecated( - "The Supertype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - final case class Supertype[U]() - - object Equal { - implicit def equalValidate[T, U](implicit - wu: WitnessAs[U, T] - ): Validate.Plain[T, Equal[U]] = - Validate.fromPredicate(_ == wu.snd, t => s"($t == ${wu.snd})", Equal(wu.fst)) - } - - @deprecated( - "Deprecated because ConstructorNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - object ConstructorNames { - @deprecated( - "Deprecated because ConstructorNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - implicit def ctorNamesValidate[T, R0 <: Coproduct, R1 <: HList, K <: HList, NP, NR](implicit - lg: LabelledGeneric.Aux[T, R0], - cthl: ToHList.Aux[R0, R1], - keys: Keys.Aux[R1, K], - ktl: ToList[K, Symbol], - v: Validate.Aux[List[String], NP, NR] - ): Validate.Aux[T, ConstructorNames[NP], ConstructorNames[v.Res]] = { - - val ctorNames = keys().toList.map(_.name) - val rn = v.validate(ctorNames) - Validate.constant(rn.as(ConstructorNames(rn)), v.showExpr(ctorNames)) - } - } - - @deprecated( - "Deprecated because FieldNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - object FieldNames { - @deprecated( - "Deprecated because FieldNames operates on types and not values and refined focuses on refining values.", - "0.9.0" - ) - implicit def fieldNamesValidate[T, R <: HList, K <: HList, NP, NR](implicit - lg: LabelledGeneric.Aux[T, R], - keys: Keys.Aux[R, K], - ktl: ToList[K, Symbol], - v: Validate.Aux[List[String], NP, NR] - ): Validate.Aux[T, FieldNames[NP], FieldNames[v.Res]] = { - - val fieldNames = keys().toList.map(_.name) - val rn = v.validate(fieldNames) - Validate.constant(rn.as(FieldNames(rn)), v.showExpr(fieldNames)) - } - } - - @deprecated( - "The Subtype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - object Subtype { - @deprecated( - "The Subtype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - implicit def subtypeValidate[T, U >: T]: Validate.Plain[T, Subtype[U]] = - Validate.alwaysPassed(Subtype()) - } - - @deprecated( - "The Supertype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - object Supertype { - @deprecated( - "The Supertype predicate is deprecated without replacement because it is lacking practical relevance.", - "0.9.0" - ) - implicit def supertypeValidate[T, U <: T]: Validate.Plain[T, Supertype[U]] = - Validate.alwaysPassed(Supertype()) - } -} - -private[refined] trait GenericInference { - - implicit def equalValidateInference[T, U, P](implicit - v: Validate[T, P], - wu: WitnessAs[U, T] - ): Equal[U] ==> P = - Inference(v.isValid(wu.snd), s"equalValidateInference(${v.showExpr(wu.snd)})") -} diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/RefineMFullyApplied.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/RefineMFullyApplied.scala deleted file mode 100644 index 750261303..000000000 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/RefineMFullyApplied.scala +++ /dev/null @@ -1,15 +0,0 @@ -package eu.timepit.refined.internal - -import eu.timepit.refined.api.{RefType, Validate} -import eu.timepit.refined.macros.RefineMacro - -@deprecated( - "RefineMFullyApplied has been replaced in favor or RefinedTypeOps. " + - "Replace 'new RefineMFullyApplied[F, T, P]' with 'new RefinedTypeOps[F[T, P], T]'.", - "0.9.1" -) -final class RefineMFullyApplied[F[_, _], T, P] { - - def apply(t: T)(implicit rt: RefType[F], v: Validate[T, P]): F[T, P] = - macro RefineMacro.impl[F, T, P] -} diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/WitnessAs.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/WitnessAs.scala index 9ebc52ec9..4dcae8c79 100644 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/WitnessAs.scala +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/WitnessAs.scala @@ -28,6 +28,11 @@ final case class WitnessAs[A, B](fst: A, snd: B) object WitnessAs extends WitnessAs1 { def apply[A, B](implicit ev: WitnessAs[A, B]): WitnessAs[A, B] = ev + @deprecated( + "Support for shapeless.Nat as arguments for predicates has been deprecated. " + + "Use Int literals for any base type or Double literals for fractional base types instead.", + "0.10.0" + ) implicit def natWitnessAs[B, A <: Nat](implicit wa: Witness.Aux[A], ta: ToInt[A], diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/numeric.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/numeric.scala index 5be3486b3..ec7291d04 100644 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/numeric.scala +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/numeric.scala @@ -6,7 +6,6 @@ import eu.timepit.refined.boolean.{And, Not} import eu.timepit.refined.internal.WitnessAs import eu.timepit.refined.numeric._ import shapeless.Nat -import shapeless.nat.{_0, _2} import shapeless.ops.nat.ToInt /** @@ -50,25 +49,25 @@ object numeric extends NumericInference { type GreaterEqual[N] = Not[Less[N]] /** Predicate that checks if a numeric value is positive (> 0). */ - type Positive = Greater[_0] + type Positive = Greater[W.`0`.T] /** Predicate that checks if a numeric value is zero or negative (<= 0). */ type NonPositive = Not[Positive] /** Predicate that checks if a numeric value is negative (< 0). */ - type Negative = Less[_0] + type Negative = Less[W.`0`.T] /** Predicate that checks if a numeric value is zero or positive (>= 0). */ type NonNegative = Not[Negative] /** Predicate that checks if an integral value is evenly divisible by `N`. */ - type Divisible[N] = Modulo[N, _0] + type Divisible[N] = Modulo[N, W.`0`.T] /** Predicate that checks if an integral value is not evenly divisible by `N`. */ type NonDivisible[N] = Not[Divisible[N]] /** Predicate that checks if an integral value is evenly divisible by 2. */ - type Even = Divisible[_2] + type Even = Divisible[W.`2`.T] /** Predicate that checks if an integral value is not evenly divisible by 2. */ type Odd = Not[Even] @@ -135,6 +134,11 @@ private[refined] trait NumericInference { ): Less[A] ==> Less[B] = Inference(nc.lt(wa.snd, wb.snd), s"lessInference(${wa.snd}, ${wb.snd})") + @deprecated( + "Support for shapeless.Nat as arguments for predicates has been deprecated. " + + "Use Int literals for any base type or Double literals for fractional base types instead.", + "0.10.0" + ) implicit def lessInferenceNat[A <: Nat, B <: Nat](implicit ta: ToInt[A], tb: ToInt[B] @@ -148,6 +152,11 @@ private[refined] trait NumericInference { ): Greater[A] ==> Greater[B] = Inference(nc.gt(wa.snd, wb.snd), s"greaterInference(${wa.snd}, ${wb.snd})") + @deprecated( + "Support for shapeless.Nat as arguments for predicates has been deprecated. " + + "Use Int literals for any base type or Double literals for fractional base types instead.", + "0.10.0" + ) implicit def greaterInferenceNat[A <: Nat, B <: Nat](implicit ta: ToInt[A], tb: ToInt[B] diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/string.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/string.scala index 6e983f50f..aec975e8d 100644 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/string.scala +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/string.scala @@ -64,9 +64,6 @@ object string extends StringInference { /** Predicate that checks if a `String` is a parsable `BigDecimal`. */ final case class ValidBigDecimal() - /** Predicate that checks if a `String` is well-formed XML. */ - final case class Xml() - /** Predicate that checks if a `String` is a valid XPath expression. */ final case class XPath() @@ -231,11 +228,6 @@ object string extends StringInference { Validate.fromPartial(BigDecimal(_), "ValidBigDecimal", ValidBigDecimal()) } - object Xml { - implicit def xmlValidate: Validate.Plain[String, Xml] = - Validate.fromPartial(scala.xml.XML.loadString, "Xml", Xml()) - } - object XPath { implicit def xpathValidate: Validate.Plain[String, XPath] = Validate.fromPartial( @@ -295,9 +287,6 @@ private[refined] trait StringInference { implicit def validBigDecimalNonEmptyInference: ValidBigDecimal ==> NonEmpty = Inference.alwaysValid("validBigDecimalNonEmptyInference") - implicit def xmlNonEmptyInference: Xml ==> NonEmpty = - Inference.alwaysValid("xmlNonEmptyInference") - implicit def xPathNonEmptyInference: XPath ==> NonEmpty = Inference.alwaysValid("xPathNonEmptyInference") } diff --git a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/types/string.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/types/string.scala index e70bb8d63..0fbe4bcae 100644 --- a/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/types/string.scala +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/types/string.scala @@ -1,10 +1,10 @@ package eu.timepit.refined.types +import eu.timepit.refined.W import eu.timepit.refined.api.{Refined, RefinedType, RefinedTypeOps} import eu.timepit.refined.collection.{MaxSize, NonEmpty, Size} import eu.timepit.refined.numeric.Interval import eu.timepit.refined.string.{HexStringSpec, Trimmed} -import shapeless.Nat._1 import shapeless.Witness /** Module for `String` refined types. */ @@ -62,7 +62,7 @@ object string { object NonEmptyString extends RefinedTypeOps[NonEmptyString, String] /** A `String` that is not empty with length less than or equal to `N`. */ - type NonEmptyFiniteString[N] = String Refined Size[Interval.Closed[_1, N]] + type NonEmptyFiniteString[N] = String Refined Size[Interval.Closed[W.`1`.T, N]] object NonEmptyFiniteString { class NonEmptyFiniteStringOps[N <: Int](implicit diff --git a/modules/core/shared/src/main/scala/eu/timepit/refined/generic.scala b/modules/core/shared/src/main/scala/eu/timepit/refined/generic.scala new file mode 100644 index 000000000..1b6d7b755 --- /dev/null +++ b/modules/core/shared/src/main/scala/eu/timepit/refined/generic.scala @@ -0,0 +1,29 @@ +package eu.timepit.refined + +import eu.timepit.refined.api.{Inference, Validate} +import eu.timepit.refined.api.Inference.==> +import eu.timepit.refined.generic._ +import eu.timepit.refined.internal.WitnessAs + +/** Module for generic predicates. */ +object generic extends GenericInference { + + /** Predicate that checks if a value is equal to `U`. */ + final case class Equal[U](u: U) + + object Equal { + implicit def equalValidate[T, U](implicit + wu: WitnessAs[U, T] + ): Validate.Plain[T, Equal[U]] = + Validate.fromPredicate(_ == wu.snd, t => s"($t == ${wu.snd})", Equal(wu.fst)) + } +} + +private[refined] trait GenericInference { + + implicit def equalValidateInference[T, U, P](implicit + v: Validate[T, P], + wu: WitnessAs[U, T] + ): Equal[U] ==> P = + Inference(v.isValid(wu.snd), s"equalValidateInference(${v.showExpr(wu.snd)})") +} diff --git a/modules/core/shared/src/main/scala/eu/timepit/refined/predicates/string.scala b/modules/core/shared/src/main/scala/eu/timepit/refined/predicates/string.scala index d6a645007..27cb6c142 100644 --- a/modules/core/shared/src/main/scala/eu/timepit/refined/predicates/string.scala +++ b/modules/core/shared/src/main/scala/eu/timepit/refined/predicates/string.scala @@ -47,9 +47,6 @@ trait StringPredicates { final type ValidBigDecimal = refined.string.ValidBigDecimal final val ValidBigDecimal = refined.string.ValidBigDecimal - final type Xml = refined.string.Xml - final val Xml = refined.string.Xml - final type XPath = refined.string.XPath final val XPath = refined.string.XPath } diff --git a/modules/core/shared/src/main/scala/eu/timepit/refined/util/string.scala b/modules/core/shared/src/main/scala/eu/timepit/refined/util/string.scala index a7751a104..3f48bcb4e 100644 --- a/modules/core/shared/src/main/scala/eu/timepit/refined/util/string.scala +++ b/modules/core/shared/src/main/scala/eu/timepit/refined/util/string.scala @@ -27,10 +27,6 @@ object string { def uuid(s: String Refined Uuid): java.util.UUID = java.util.UUID.fromString(s.value) - /** Creates a `scala.xml.Elem` from a validated string. */ - def xml(s: String Refined Xml): scala.xml.Elem = - scala.xml.XML.loadString(s.value) - /** Creates a `javax.xml.xpath.XPathExpression` from a validated string. */ def xpath(s: String Refined XPath): javax.xml.xpath.XPathExpression = javax.xml.xpath.XPathFactory.newInstance().newXPath().compile(s.value) diff --git a/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala b/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala index c18258a36..f20cf1577 100644 --- a/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala +++ b/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala @@ -7,7 +7,6 @@ import eu.timepit.refined.collection._ import eu.timepit.refined.numeric.{Greater, Interval} import org.scalacheck.Prop._ import org.scalacheck.Properties -import shapeless.nat._ import shapeless.test.illTyped class CollectionInferenceSpec extends Properties("CollectionInference") { @@ -64,11 +63,11 @@ class CollectionInferenceSpec extends Properties("CollectionInference") { Inference[Size[Greater[W.`5`.T]], Size[Greater[W.`4`.T]]].isValid } - property("Size[Greater[_1]] ==> NonEmpty") = secure { - Inference[Size[Greater[_1]], NonEmpty].isValid + property("Size[Greater[1]] ==> NonEmpty") = secure { + Inference[Size[Greater[W.`1`.T]], NonEmpty].isValid } - property("Size[Interval.Closed[_2, _5]] ==> NonEmpty") = secure { - Inference[Size[Interval.Closed[_2, _5]], NonEmpty].isValid + property("Size[Interval.Closed[2, 5]] ==> NonEmpty") = secure { + Inference[Size[Interval.Closed[W.`2`.T, W.`5`.T]], NonEmpty].isValid } } diff --git a/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/StringInferenceSpec.scala b/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/StringInferenceSpec.scala index 2174f8edc..455ef715e 100644 --- a/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/StringInferenceSpec.scala +++ b/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/StringInferenceSpec.scala @@ -32,10 +32,6 @@ class StringInferenceSpec extends Properties("StringInference") { Inference[Url, NonEmpty].isValid } - property("Xml ==> NonEmpty ") = secure { - Inference[Xml, NonEmpty].isValid - } - property("ValidByte ==> NonEmpty ") = secure { Inference[ValidByte, NonEmpty].isValid } diff --git a/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/string.scala b/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/string.scala new file mode 100644 index 000000000..711f69311 --- /dev/null +++ b/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/string.scala @@ -0,0 +1,14 @@ +package eu.timepit.refined.scalaxml + +import eu.timepit.refined.api.Validate + +object string { + + /** Predicate that checks if a `String` is well-formed XML. */ + final case class Xml() + + object Xml { + implicit def xmlValidate: Validate.Plain[String, Xml] = + Validate.fromPartial(scala.xml.XML.loadString, "Xml", Xml()) + } +} diff --git a/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/util.scala b/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/util.scala new file mode 100644 index 000000000..7fee0a2f1 --- /dev/null +++ b/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/util.scala @@ -0,0 +1,11 @@ +package eu.timepit.refined.scalaxml + +import eu.timepit.refined.api.Refined +import eu.timepit.refined.scalaxml.string.Xml + +object util { + + /** Creates a `scala.xml.Elem` from a validated string. */ + def xml(s: String Refined Xml): scala.xml.Elem = + scala.xml.XML.loadString(s.value) +} diff --git a/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala new file mode 100644 index 000000000..ddaa98939 --- /dev/null +++ b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala @@ -0,0 +1,17 @@ +package eu.timepit.refined.scalaxml + +import eu.timepit.refined.TestUtils._ +import eu.timepit.refined.scalaxml.string._ +import org.scalacheck.Prop._ +import org.scalacheck.Properties + +class XmlValidateSpec extends Properties("XmlValidate") { + property("Xml.isValid") = secure { + isValid[Xml]("") + } + + property("Xml.showResult") = secure { + showResult[Xml]("") ?= + "Xml predicate failed: XML document structures must start and end within the same entity." + } +} diff --git a/modules/shapeless/shared/src/test/scala/eu/timepit/refined/shapeless/typeable/TypeableSpec.scala b/modules/shapeless/shared/src/test/scala/eu/timepit/refined/shapeless/typeable/TypeableSpec.scala index b981ed812..1f5b794e2 100644 --- a/modules/shapeless/shared/src/test/scala/eu/timepit/refined/shapeless/typeable/TypeableSpec.scala +++ b/modules/shapeless/shared/src/test/scala/eu/timepit/refined/shapeless/typeable/TypeableSpec.scala @@ -20,7 +20,7 @@ class TypeableSpec extends Properties("shapeless") { } property("Typeable describe") = secure { - typeableDescribe[PosInt] ?= "Refined[Int, Greater[_0]]" + typeableDescribe[PosInt] ?= "Refined[Int, Greater[Int(0)]]" } property("Typeable cast success string regex") = secure {