From 1c278efe63adfd87e007dcda5c57c92c589f521a Mon Sep 17 00:00:00 2001 From: Howy Perrin Date: Thu, 31 Jan 2019 19:09:36 +0000 Subject: [PATCH 01/19] Move scala-xml related code to separate module --- build.sbt | 14 ++++++++++++-- .../timepit/refined/StringUtilSpecJvm.scala | 9 --------- .../refined/StringValidateSpecJvm.scala | 9 --------- .../timepit/refined/predicates/string.scala | 3 --- .../scala/eu/timepit/refined/string.scala | 8 -------- .../eu/timepit/refined/util/string.scala | 4 ---- .../eu/timepit/refined/scalaxml/string.scala | 13 +++++++++++++ .../eu/timepit/refined/scalaxml/util.scala | 10 ++++++++++ .../refined/scalaxml/XmlUtilSpecJvm.scala | 19 +++++++++++++++++++ .../refined/scalaxml/XmlValidateSpecJvm.scala | 17 +++++++++++++++++ 10 files changed, 71 insertions(+), 35 deletions(-) create mode 100644 modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala create mode 100644 modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala create mode 100644 modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala create mode 100644 modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala diff --git a/build.sbt b/build.sbt index eccd73432..28453bf4b 100644 --- a/build.sbt +++ b/build.sbt @@ -53,7 +53,8 @@ val moduleCrossPlatformMatrix = Map( "scalaz" -> List(JVMPlatform, JSPlatform, NativePlatform), "scodec" -> List(JVMPlatform, JSPlatform), "scopt" -> List(JVMPlatform, JSPlatform), - "shapeless" -> List(JVMPlatform, JSPlatform, NativePlatform) + "shapeless" -> List(JVMPlatform, JSPlatform, NativePlatform), + "scalaxml" -> List(JVMPlatform, JSPlatform, NativePlatform) ) def allSubprojectsOf(platform: sbtcrossproject.Platform): List[String] = @@ -119,7 +120,6 @@ lazy val core = myCrossProject("core") scalaOrganization.value % "scala-reflect" % scalaVersion.value, scalaOrganization.value % "scala-compiler" % scalaVersion.value, "com.chuusai" %%% "shapeless" % shapelessVersion, - "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion, scalaCheckDep.value % Test ), initialCommands += s""" @@ -262,6 +262,16 @@ lazy val shapelessJVM = shapeless.jvm lazy val shapelessJS = shapeless.js lazy val shapelessNative = shapeless.native +lazy val scalaxml = myCrossProject("scalaxml") + .dependsOn(core % "compile->compile;test->test") + .settings( + libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion + ) + +lazy val scalaxmlJVM = scalaxml.jvm +lazy val scalaxmlJS = scalaxml.js +lazy val scalaxmlNative = scalaxml.native + /// settings lazy val commonSettings = Def.settings( diff --git a/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala b/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala index 91ddb6717..a8c674909 100644 --- a/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala +++ b/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala @@ -17,15 +17,6 @@ class StringUtilSpecJvm extends Properties("util.string") { true } - property("xml success") = secure { - xml("") == scala.xml.XML.loadString("") - } - - property("xml failure") = secure { - illTyped("""xml("")""", "Xml predicate failed.*") - true - } - property("xpath success") = secure { xpath("A//B/*[1]") true 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/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/string.scala b/modules/core/shared/src/main/scala/eu/timepit/refined/string.scala index 52e321be4..dd4ce4b1d 100644 --- a/modules/core/shared/src/main/scala/eu/timepit/refined/string.scala +++ b/modules/core/shared/src/main/scala/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( 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 e2dc83bf5..679387bba 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 @@ -43,10 +43,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/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala new file mode 100644 index 000000000..90f782fcb --- /dev/null +++ b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala @@ -0,0 +1,13 @@ +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/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala new file mode 100644 index 000000000..c8377aa01 --- /dev/null +++ b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala @@ -0,0 +1,10 @@ +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/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala b/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala new file mode 100644 index 000000000..1bb068bb6 --- /dev/null +++ b/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala @@ -0,0 +1,19 @@ +package eu.timepit.refined.scalaxml + +import eu.timepit.refined.auto._ +import eu.timepit.refined.scalaxml.util._ +import org.scalacheck.Prop._ +import org.scalacheck.Properties +import shapeless.test.illTyped + +class XmlUtilSpecJvm extends Properties("scalaxml.util.string") { + + property("xml success") = secure { + xml("") == scala.xml.XML.loadString("") + } + + property("xml failure") = secure { + illTyped("""xml("")""", "Xml predicate failed.*") + true + } +} diff --git a/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala b/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala new file mode 100644 index 000000000..033ff6c1e --- /dev/null +++ b/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.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 XmlValidateSpecJvm 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." + } +} From 5c02a232c9d3ca7f0f03838637c505cdab01ab2d Mon Sep 17 00:00:00 2001 From: Howy Perrin Date: Thu, 31 Jan 2019 20:19:35 +0000 Subject: [PATCH 02/19] Add exclusions for binary compatibility failures --- build.sbt | 10 +++++++++- latestVersion.sbt | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 28453bf4b..47b79281f 100644 --- a/build.sbt +++ b/build.sbt @@ -340,7 +340,15 @@ def moduleJvmSettings(name: String): Seq[Def.Setting[_]] = Def.settings( mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._ Seq( - ) + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml$"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml"), + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.predicates.StringPredicates.Xml"), + ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.all.Xml"), + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.predicates.string.Xml"), + ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.util.string.xml") + ) } ) diff --git a/latestVersion.sbt b/latestVersion.sbt index fc176dac2..dc14cad34 100644 --- a/latestVersion.sbt +++ b/latestVersion.sbt @@ -9,4 +9,5 @@ bincompatVersions in ThisBuild := Set( unreleasedModules in ThisBuild := Set( // Example: // "refined-eval" + "refined-scalaxml" ) From 9363d8f203b8072e5a51355171985f373cad4479 Mon Sep 17 00:00:00 2001 From: Howy Perrin Date: Thu, 31 Jan 2019 20:21:12 +0000 Subject: [PATCH 03/19] Try scalaxml module in scala 2.13 build --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 47b79281f..634838a65 100644 --- a/build.sbt +++ b/build.sbt @@ -72,7 +72,7 @@ val Scala213 = "2.13.0-M5" val moduleCrossScalaVersionsMatrix: (String, Platform) => List[String] = { case (_, NativePlatform) => List(Scala211) - case ("cats" | "core" | "scalacheck" | "scalaz" | "shapeless", _) => + case ("cats" | "core" | "scalacheck" | "scalaz" | "shapeless" | "scalaxml", _) => List(Scala211, Scala212, Scala213) case _ => List(Scala211, Scala212) From 6c01d8d7d7a875218879481506fa897056836c4b Mon Sep 17 00:00:00 2001 From: Howy Perrin Date: Fri, 1 Feb 2019 10:07:43 +0000 Subject: [PATCH 04/19] Fix scalafmt errors --- build.sbt | 8 ++++---- .../main/scala/eu/timepit/refined/scalaxml/string.scala | 1 + .../src/main/scala/eu/timepit/refined/scalaxml/util.scala | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index 634838a65..870779e34 100644 --- a/build.sbt +++ b/build.sbt @@ -342,11 +342,11 @@ def moduleJvmSettings(name: String): Seq[Def.Setting[_]] = Def.settings( Seq( ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml$"), ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml"), - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.predicates.StringPredicates.Xml"), + ProblemFilters + .exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.StringPredicates.Xml"), ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.all.Xml"), - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.predicates.string.Xml"), + ProblemFilters + .exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.string.Xml"), ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.util.string.xml") ) } diff --git a/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala index 90f782fcb..711f69311 100644 --- a/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala +++ b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala @@ -3,6 +3,7 @@ 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() diff --git a/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala index c8377aa01..7fee0a2f1 100644 --- a/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala +++ b/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala @@ -4,6 +4,7 @@ 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) From d1eb21272add3cf936bdf64d8d1d9c466d3c6dab Mon Sep 17 00:00:00 2001 From: Howy Perrin Date: Sun, 3 Feb 2019 22:33:07 +0000 Subject: [PATCH 05/19] Lowercase module's directory --- .../jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala | 0 .../jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala | 0 .../test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala | 0 .../scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename modules/{scalaXml => scalaxml}/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala (100%) rename modules/{scalaXml => scalaxml}/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala (100%) rename modules/{scalaXml => scalaxml}/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala (100%) rename modules/{scalaXml => scalaxml}/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala (100%) diff --git a/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala b/modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala similarity index 100% rename from modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala rename to modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala diff --git a/modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala b/modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala similarity index 100% rename from modules/scalaXml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala rename to modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala diff --git a/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala b/modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala similarity index 100% rename from modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala rename to modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala diff --git a/modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala b/modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala similarity index 100% rename from modules/scalaXml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala rename to modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala From 525f20d0e7ad55e03d037e35ed9bd60fbca67495 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 5 Feb 2019 20:30:05 +0100 Subject: [PATCH 06/19] Make scalaxml module JVM-only This makes the scalaxml module only available for the JVM because scala-xml is not available for Scala Native and fails with linking errors on Scala.js: ``` Referring to non-existent class javax.xml.parsers.SAXParserFactory$ called from scala.xml.factory.XMLLoader.parser()javax.xml.parsers.SAXParser called from scala.xml.XML$.parser()javax.xml.parsers.SAXParser called from scala.xml.factory.XMLLoader.loadString(java.lang.String)scala.xml.Node called from scala.xml.XML$.loadString(java.lang.String)scala.xml.Node called from eu.timepit.refined.scalaxml.string$Xml$.$$anonfun$xmlValidate$1(java.lang.String)scala.xml.Elem called from eu.timepit.refined.scalaxml.string$Xml$.xmlValidate()eu.timepit.refined.api.Validate ``` --- build.sbt | 4 +--- .../src/main/scala/eu/timepit/refined/scalaxml/string.scala | 0 .../src/main/scala/eu/timepit/refined/scalaxml/util.scala | 0 .../test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala} | 2 +- .../scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala} | 2 +- 5 files changed, 3 insertions(+), 5 deletions(-) rename modules/scalaxml/{jvm => shared}/src/main/scala/eu/timepit/refined/scalaxml/string.scala (100%) rename modules/scalaxml/{jvm => shared}/src/main/scala/eu/timepit/refined/scalaxml/util.scala (100%) rename modules/scalaxml/{jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala => shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala} (86%) rename modules/scalaxml/{jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala => shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala} (87%) diff --git a/build.sbt b/build.sbt index 870779e34..d8eb6b01e 100644 --- a/build.sbt +++ b/build.sbt @@ -54,7 +54,7 @@ val moduleCrossPlatformMatrix = Map( "scodec" -> List(JVMPlatform, JSPlatform), "scopt" -> List(JVMPlatform, JSPlatform), "shapeless" -> List(JVMPlatform, JSPlatform, NativePlatform), - "scalaxml" -> List(JVMPlatform, JSPlatform, NativePlatform) + "scalaxml" -> List(JVMPlatform) ) def allSubprojectsOf(platform: sbtcrossproject.Platform): List[String] = @@ -269,8 +269,6 @@ lazy val scalaxml = myCrossProject("scalaxml") ) lazy val scalaxmlJVM = scalaxml.jvm -lazy val scalaxmlJS = scalaxml.js -lazy val scalaxmlNative = scalaxml.native /// settings diff --git a/modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala b/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/string.scala similarity index 100% rename from modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/string.scala rename to modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/string.scala diff --git a/modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala b/modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/util.scala similarity index 100% rename from modules/scalaxml/jvm/src/main/scala/eu/timepit/refined/scalaxml/util.scala rename to modules/scalaxml/shared/src/main/scala/eu/timepit/refined/scalaxml/util.scala diff --git a/modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala similarity index 86% rename from modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala rename to modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala index 1bb068bb6..7db449390 100644 --- a/modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpecJvm.scala +++ b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala @@ -6,7 +6,7 @@ import org.scalacheck.Prop._ import org.scalacheck.Properties import shapeless.test.illTyped -class XmlUtilSpecJvm extends Properties("scalaxml.util.string") { +class XmlUtilSpec extends Properties("scalaxml.util") { property("xml success") = secure { xml("") == scala.xml.XML.loadString("") diff --git a/modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala similarity index 87% rename from modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala rename to modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala index 033ff6c1e..ddaa98939 100644 --- a/modules/scalaxml/jvm/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpecJvm.scala +++ b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlValidateSpec.scala @@ -5,7 +5,7 @@ import eu.timepit.refined.scalaxml.string._ import org.scalacheck.Prop._ import org.scalacheck.Properties -class XmlValidateSpecJvm extends Properties("XmlValidate") { +class XmlValidateSpec extends Properties("XmlValidate") { property("Xml.isValid") = secure { isValid[Xml]("") } From d8a8b59bd89c1ccb87f97b5b2761669f2f325e68 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 27 Sep 2020 00:20:17 +0200 Subject: [PATCH 07/19] reformat --- build.sbt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/build.sbt b/build.sbt index dc03a9f13..e6a431ae1 100644 --- a/build.sbt +++ b/build.sbt @@ -51,8 +51,7 @@ val moduleCrossPlatformMatrix: Map[String, List[Platform]] = Map( "scodec" -> List(JVMPlatform, JSPlatform), "scopt" -> List(JVMPlatform), "shapeless" -> List(JVMPlatform, JSPlatform), -"scalaxml" -> List(JVMPlatform) - + "scalaxml" -> List(JVMPlatform) ) val moduleCrossScalaVersionsMatrix: (String, Platform) => List[String] = { @@ -338,11 +337,13 @@ def moduleJvmSettings(name: String): Seq[Def.Setting[_]] = Seq( ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml$"), ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml"), - ProblemFilters - .exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.StringPredicates.Xml"), + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.predicates.StringPredicates.Xml" + ), ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.all.Xml"), - ProblemFilters - .exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.string.Xml"), + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.predicates.string.Xml" + ), ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.util.string.xml"), ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Max.findValid"), ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Min.findValid") From 381d6331c70ce1e426df72996cddb308f4d9f1a0 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 27 Sep 2020 00:23:39 +0200 Subject: [PATCH 08/19] Remove file that has also been removed in master --- .../timepit/refined/StringUtilSpecJvm.scala | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala diff --git a/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala b/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala deleted file mode 100644 index a8c674909..000000000 --- a/modules/core/jvm/src/test/scala/eu/timepit/refined/StringUtilSpecJvm.scala +++ /dev/null @@ -1,29 +0,0 @@ -package eu.timepit.refined - -import eu.timepit.refined.auto._ -import eu.timepit.refined.util.string._ -import org.scalacheck.Prop._ -import org.scalacheck.Properties -import shapeless.test.illTyped - -class StringUtilSpecJvm extends Properties("util.string") { - - property("url success") = secure { - url("http://example.com").toString ?= new java.net.URL("http://example.com").toString - } - - property("url failure") = secure { - illTyped("""url("http//example.com")""", "Url predicate failed.*") - true - } - - property("xpath success") = secure { - xpath("A//B/*[1]") - true - } - - property("xpath failure") = secure { - illTyped("""xpath("A//B/*[1")""", "XPath predicate failed.*") - true - } -} From c00a4622f38c1359dc452791e237b3261ed1e5c8 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 27 Sep 2020 00:55:16 +0200 Subject: [PATCH 09/19] Remove Xml predicate from Scala 3 sources --- .../src/main/scala-3.0+/eu/timepit/refined/string.scala | 8 -------- 1 file changed, 8 deletions(-) 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 877446bdf..f94a3aaea 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 @@ -62,9 +62,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() @@ -229,11 +226,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( From 655f566810afb8a01bf0dff1c7e677d11331e505 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 27 Sep 2020 07:26:29 +0200 Subject: [PATCH 10/19] Remove deprecated generic predicates (#843) * Remove deprecated generic predicates * Remove deprecated methods in RefType --- build.sbt | 20 +++ .../eu/timepit/refined/generic.scala | 79 ----------- .../eu/timepit/refined/api/RefType.scala | 27 ---- .../eu/timepit/refined/generic.scala | 128 ------------------ .../internal/RefineMFullyApplied.scala | 15 -- .../scala/eu/timepit/refined/generic.scala | 29 ++++ 6 files changed, 49 insertions(+), 249 deletions(-) delete mode 100644 modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/generic.scala delete mode 100644 modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/generic.scala delete mode 100644 modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/internal/RefineMFullyApplied.scala create mode 100644 modules/core/shared/src/main/scala/eu/timepit/refined/generic.scala diff --git a/build.sbt b/build.sbt index e6a431ae1..af046fe58 100644 --- a/build.sbt +++ b/build.sbt @@ -335,6 +335,26 @@ def moduleJvmSettings(name: String): Seq[Def.Setting[_]] = mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._ Seq( + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.api.RefType.unsafeWrapM" + ), + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.api.RefType.unsafeRewrapM" + ), + ProblemFilters.exclude[DirectMissingMethodProblem]( + "eu.timepit.refined.api.RefType.refineMF" + ), + ProblemFilters.exclude[MissingClassProblem]( + "eu.timepit.refined.internal.RefineMFullyApplied" + ), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$ConstructorNames"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$ConstructorNames$"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$FieldNames"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$FieldNames$"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Subtype"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Subtype$"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Supertype"), + ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Supertype$"), ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml$"), ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml"), ProblemFilters.exclude[DirectMissingMethodProblem]( 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/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/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/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)})") +} From 3223035a476ce6df7b01a9033b6d2247822afaea Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 27 Sep 2020 15:35:06 +0200 Subject: [PATCH 11/19] Use Int literals for numeric predicates like Positive (#842) * Use Int literals for numeric predicates like Positive See https://github.com/fthomas/refined/pull/841#issuecomment-699502818. * Replace Nat in MaxSize and NonEmptyFiniteString --- .../eu/timepit/refined/collection.scala | 5 +- .../eu/timepit/refined/numeric.scala | 9 +- .../eu/timepit/refined/types/string.scala | 3 +- .../eu/timepit/refined/collection.scala | 349 ++++++++++++++++++ .../eu/timepit/refined/numeric.scala | 9 +- .../eu/timepit/refined/types/string.scala | 4 +- .../refined/CollectionInferenceSpec.scala | 4 +- .../pureconfig/RefTypeConfigConvertSpec.scala | 4 +- .../shapeless/typeable/TypeableSpec.scala | 2 +- 9 files changed, 367 insertions(+), 22 deletions(-) rename modules/core/shared/src/main/{scala => scala-3.0+}/eu/timepit/refined/collection.scala (99%) create mode 100644 modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala diff --git a/modules/core/shared/src/main/scala/eu/timepit/refined/collection.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala similarity index 99% rename from modules/core/shared/src/main/scala/eu/timepit/refined/collection.scala rename to modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/collection.scala index d7beae2db..66008b9b5 100644 --- a/modules/core/shared/src/main/scala/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/numeric.scala b/modules/core/shared/src/main/scala-3.0+/eu/timepit/refined/numeric.scala index 465ecf545..6cccc1080 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. Predicates that take type parameters @@ -51,25 +50,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] 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 c61c3da37..4edd862c9 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/collection.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala new file mode 100644 index 000000000..96e17f2b4 --- /dev/null +++ b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/collection.scala @@ -0,0 +1,349 @@ +package eu.timepit.refined + +import eu.timepit.refined.api.Inference.==> +import eu.timepit.refined.api.{Inference, Result, Validate} +import eu.timepit.refined.boolean.Not +import eu.timepit.refined.collection._ +import eu.timepit.refined.generic.Equal +import eu.timepit.refined.internal.Resources +import eu.timepit.refined.numeric.{GreaterEqual, Interval} +import shapeless.Witness + +/** Module for collection predicates. */ +object collection extends CollectionInference { + + /** + * Predicate that counts the number of elements in an `Iterable` + * which satisfy the predicate `PA` and passes the result to the numeric + * predicate `PC`. + */ + final case class Count[PA, PC](pa: PA, pc: PC) + + /** Predicate that checks if an `Iterable` is empty. */ + final case class Empty() + + /** + * Predicate that checks if the predicate `P` holds for all elements of an + * `Iterable`. + */ + final case class Forall[P](p: P) + + /** + * Predicate that checks if the predicate `P` holds for the first element + * of an `Iterable`. + */ + final case class Head[P](p: P) + + /** + * Predicate that checks if the predicate `P` holds for the element at + * index `N` of a sequence. + */ + final case class Index[N, P](n: N, p: P) + + /** + * Predicate that checks if the predicate `P` holds for all but the last + * element of an `Iterable`. + */ + final case class Init[P](p: P) + + /** + * Predicate that checks if the predicate `P` holds for the last element + * of an `Iterable`. + */ + final case class Last[P](p: P) + + /** + * Predicate that checks if the size of an `Iterable` satisfies the + * predicate `P`. + */ + final case class Size[P](p: P) + + /** + * Predicate that checks if the predicate `P` holds for all but the first + * element of an `Iterable`. + */ + final case class Tail[P](p: P) + + /** + * Predicate that checks if an `Iterable` contains a value + * equal to `U`. + */ + type Contains[U] = Exists[Equal[U]] + + /** + * Predicate that checks if the predicate `P` holds for some elements of an + * `Iterable`. + */ + type Exists[P] = Not[Forall[Not[P]]] + + /** + * Predicate that checks if the size of an `Iterable` is greater than + * or equal to `N`. + */ + type MinSize[N] = Size[GreaterEqual[N]] + + /** + * Predicate that checks if the size of an `Iterable` is less than + * or equal to `N`. + */ + type MaxSize[N] = Size[Interval.Closed[W.`0`.T, N]] + + /** Predicate that checks if an `Iterable` is not empty. */ + type NonEmpty = Not[Empty] + + object Count { + implicit def countValidate[A, PA, RA, PC, RC, T](implicit + va: Validate.Aux[A, PA, RA], + vc: Validate.Aux[Int, PC, RC], + ev: T => Iterable[A] + ): Validate.Aux[T, Count[PA, PC], Count[List[va.Res], vc.Res]] = + new Validate[T, Count[PA, PC]] { + override type R = Count[List[va.Res], vc.Res] + + override def validate(t: T): Res = { + val ra = ev(t).toList.map(va.validate) + val rc = vc.validate(ra.count(_.isPassed)) + rc.as(Count(ra, rc)) + } + + override def showExpr(t: T): String = + vc.showExpr(count(t)) + + override def showResult(t: T, r: Res): String = { + val c = count(t) + val expr = ev(t).map(va.showExpr).mkString("count(", ", ", ")") + Resources.predicateTakingResultDetail(s"$expr = $c", r, vc.showResult(c, r.detail.pc)) + } + + private def count(t: T): Int = + ev(t).count(va.isValid) + } + } + + object Empty { + implicit def emptyValidate[T](implicit ev: T => Iterable[_]): Validate.Plain[T, Empty] = + Validate.fromPredicate(t => ev(t).isEmpty, t => s"isEmpty($t)", Empty()) + } + + object Forall { + implicit def forallValidate[A, P, R, T[a] <: Iterable[a]](implicit + v: Validate.Aux[A, P, R] + ): Validate.Aux[T[A], Forall[P], Forall[List[v.Res]]] = + new Validate[T[A], Forall[P]] { + override type R = Forall[List[v.Res]] + + override def validate(t: T[A]): Res = { + val rt = t.toList.map(v.validate) + Result.fromBoolean(rt.forall(_.isPassed), Forall(rt)) + } + + override def showExpr(t: T[A]): String = + t.map(v.showExpr).mkString("(", " && ", ")") + } + + implicit def forallValidateView[A, P, R, T](implicit + v: Validate.Aux[A, P, R], + ev: T => Iterable[A] + ): Validate.Aux[T, Forall[P], Forall[List[v.Res]]] = + forallValidate[A, P, R, Iterable].contramap(ev) + } + + object Head { + implicit def headValidate[A, P, R, T[a] <: Iterable[a]](implicit + v: Validate.Aux[A, P, R] + ): Validate.Aux[T[A], Head[P], Head[Option[v.Res]]] = + new Validate[T[A], Head[P]] { + override type R = Head[Option[v.Res]] + + override def validate(t: T[A]): Res = { + val ra = t.headOption.map(v.validate) + Result.fromBoolean(ra.fold(false)(_.isPassed), Head(ra)) + } + + override def showExpr(t: T[A]): String = + optElemShowExpr(t.headOption, v.showExpr) + + override def showResult(t: T[A], r: Res): String = + optElemShowResult(t.headOption, r.detail.p, (a: A) => s"head($t) = $a", v.showResult) + } + + implicit def headValidateView[A, P, R, T](implicit + v: Validate.Aux[A, P, R], + ev: T => Iterable[A] + ): Validate.Aux[T, Head[P], Head[Option[v.Res]]] = + headValidate[A, P, R, Iterable].contramap(ev) + } + + object Index { + implicit def indexValidate[A, P, R, N <: Int, T](implicit + v: Validate.Aux[A, P, R], + ev: T => PartialFunction[Int, A], + wn: Witness.Aux[N] + ): Validate.Aux[T, Index[N, P], Index[N, Option[v.Res]]] = + new Validate[T, Index[N, P]] { + override type R = Index[N, Option[v.Res]] + + override def validate(t: T): Res = { + val ra = ev(t).lift(wn.value).map(v.validate) + Result.fromBoolean(ra.fold(false)(_.isPassed), Index(wn.value, ra)) + } + + override def showExpr(t: T): String = + optElemShowExpr(ev(t).lift(wn.value), v.showExpr) + + override def showResult(t: T, r: Res): String = + optElemShowResult( + ev(t).lift(wn.value), + r.detail.p, + (a: A) => s"index($t, ${wn.value}) = $a", + v.showResult + ) + } + } + + object Init { + implicit def initValidate[A, P, R, T[a] <: Iterable[a]](implicit + v: Validate.Aux[A, P, R] + ): Validate.Aux[T[A], Init[P], Init[List[v.Res]]] = + new Validate[T[A], Init[P]] { + override type R = Init[List[v.Res]] + + override def validate(t: T[A]): Res = { + val ra = t.toList.dropRight(1).map(v.validate) + Result.fromBoolean(ra.forall(_.isPassed), Init(ra)) + } + + override def showExpr(t: T[A]): String = + t.toList.dropRight(1).map(v.showExpr).mkString("(", " && ", ")") + } + + implicit def initValidateView[A, P, R, T](implicit + v: Validate.Aux[A, P, R], + ev: T => Iterable[A] + ): Validate.Aux[T, Init[P], Init[List[v.Res]]] = + initValidate[A, P, R, Iterable].contramap(ev) + } + + object Last { + implicit def lastValidate[A, P, R, T[a] <: Iterable[a]](implicit + v: Validate.Aux[A, P, R] + ): Validate.Aux[T[A], Last[P], Last[Option[v.Res]]] = + new Validate[T[A], Last[P]] { + override type R = Last[Option[v.Res]] + + override def validate(t: T[A]): Res = { + val ra = t.lastOption.map(v.validate) + Result.fromBoolean(ra.fold(false)(_.isPassed), Last(ra)) + } + + override def showExpr(t: T[A]): String = + optElemShowExpr(t.lastOption, v.showExpr) + + override def showResult(t: T[A], r: Res): String = + optElemShowResult(t.lastOption, r.detail.p, (a: A) => s"last($t) = $a", v.showResult) + } + + implicit def lastValidateView[A, P, R, T](implicit + v: Validate.Aux[A, P, R], + ev: T => Iterable[A] + ): Validate.Aux[T, Last[P], Last[Option[v.Res]]] = + lastValidate[A, P, R, Iterable].contramap(ev) + } + + object Size { + implicit def sizeValidate[T, P, RP](implicit + v: Validate.Aux[Int, P, RP], + ev: T => Iterable[_] + ): Validate.Aux[T, Size[P], Size[v.Res]] = + new Validate[T, Size[P]] { + override type R = Size[v.Res] + + override def validate(t: T): Res = { + val r = v.validate(ev(t).size) + r.as(Size(r)) + } + + override def showExpr(t: T): String = + v.showExpr(ev(t).size) + + override def showResult(t: T, r: Res): String = { + val size = ev(t).size + val nested = v.showResult(size, r.detail.p) + Resources.predicateTakingResultDetail(s"size($t) = $size", r, nested) + } + } + } + + object Tail { + implicit def tailValidate[A, P, R, T[a] <: Iterable[a]](implicit + v: Validate.Aux[A, P, R] + ): Validate.Aux[T[A], Tail[P], Tail[List[v.Res]]] = + new Validate[T[A], Tail[P]] { + override type R = Tail[List[v.Res]] + + override def validate(t: T[A]): Res = { + val ra = t.toList.drop(1).map(v.validate) + Result.fromBoolean(ra.forall(_.isPassed), Tail(ra)) + } + + override def showExpr(t: T[A]): String = + t.toList.drop(1).map(v.showExpr).mkString("(", " && ", ")") + } + + implicit def tailValidateView[A, P, R, T](implicit + v: Validate.Aux[A, P, R], + ev: T => Iterable[A] + ): Validate.Aux[T, Tail[P], Tail[List[v.Res]]] = + tailValidate[A, P, R, Iterable].contramap(ev) + } + + private def optElemShowExpr[A](elem: Option[A], f: A => String): String = + elem.fold(Resources.showExprEmptyCollection)(f) + + private def optElemShowResult[A, R]( + elem: Option[A], + res: Option[Result[R]], + f: A => String, + g: (A, Result[R]) => String + ): String = + (elem, res) match { + case (Some(a), Some(r)) => + Resources.predicateTakingResultDetail(f(a), r, g(a, r)) + case _ => Resources.showResultEmptyCollection + } +} + +private[refined] trait CollectionInference { + + implicit def existsInference[A, B](implicit p1: A ==> B): Exists[A] ==> Exists[B] = + p1.adapt("existsInference(%s)") + + implicit def existsNonEmptyInference[P]: Exists[P] ==> NonEmpty = + Inference.alwaysValid("existsNonEmptyInference") + + implicit def headInference[A, B](implicit p1: A ==> B): Head[A] ==> Head[B] = + p1.adapt("headInference(%s)") + + implicit def headExistsInference[P]: Head[P] ==> Exists[P] = + Inference.alwaysValid("headExistsInference") + + implicit def indexInference[N, A, B](implicit p1: A ==> B): Index[N, A] ==> Index[N, B] = + p1.adapt("indexInference(%s)") + + implicit def indexExistsInference[N, P]: Index[N, P] ==> Exists[P] = + Inference.alwaysValid("indexExistsInference") + + implicit def lastInference[A, B](implicit p1: A ==> B): Last[A] ==> Last[B] = + p1.adapt("lastInference(%s)") + + implicit def lastExistsInference[P]: Last[P] ==> Exists[P] = + Inference.alwaysValid("lastExistsInference") + + implicit def sizeInference[A, B](implicit p1: A ==> B): Size[A] ==> Size[B] = + p1.adapt("sizeInference(%s)") + + implicit def sizeGreaterEqual1NonEmptyInference[A](implicit + 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/numeric.scala b/modules/core/shared/src/main/scala-3.0-/eu/timepit/refined/numeric.scala index 42b8d02c9..9aab069ad 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 /** @@ -51,25 +50,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] 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 9f0ee802d..214fce066 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/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala b/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala index 4d2ff13c0..fdf44e557 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 @@ -64,8 +64,8 @@ class CollectionInferenceSpec extends Properties("CollectionInference") { Inference[Size[Greater[_5]], Size[Greater[_4]]].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 { diff --git a/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala b/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala index c5ecbf70a..313d4846d 100644 --- a/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala +++ b/modules/pureconfig/shared/src/test/scala/eu/timepit/refined/pureconfig/RefTypeConfigConvertSpec.scala @@ -24,7 +24,7 @@ class RefTypeConfigConvertSpec extends Properties("RefTypeConfigConvert") { reason = CannotConvert( value = "0", toType = - "eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Greater[shapeless.nat._0]]", + "eu.timepit.refined.api.Refined[Int,eu.timepit.refined.numeric.Greater[Int(0)]]", because = "Predicate failed: (0 > 0)." ), origin = Some(ConfigOriginFactory.newSimple("String").withLineNumber(1)), @@ -41,7 +41,7 @@ class RefTypeConfigConvertSpec extends Properties("RefTypeConfigConvert") { reason = CannotConvert( value = "0", toType = - "eu.timepit.refined.api.Refined[scala.Int,eu.timepit.refined.numeric.Greater[shapeless.nat._0]]", + "eu.timepit.refined.api.Refined[scala.Int,eu.timepit.refined.numeric.Greater[Int(0)]]", because = "Predicate failed: (0 > 0)." ), origin = Some(ConfigOriginFactory.newSimple("String").withLineNumber(1)), 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 { From dafa09c2a5b0c0ff38f77f23a61c74f09a91b435 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 28 Sep 2020 21:57:31 +0200 Subject: [PATCH 12/19] Deprecate support for Nat as arguments for predicates --- .../eu/timepit/refined/internal/WitnessAs.scala | 5 +++++ .../main/scala-3.0+/eu/timepit/refined/numeric.scala | 10 ++++++++++ .../eu/timepit/refined/internal/WitnessAs.scala | 5 +++++ .../main/scala-3.0-/eu/timepit/refined/numeric.scala | 10 ++++++++++ .../eu/timepit/refined/CollectionInferenceSpec.scala | 5 ++--- 5 files changed, 32 insertions(+), 3 deletions(-) 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 0011833a0..7bedf164e 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 6262e6ecf..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 @@ -134,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] @@ -147,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/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 9af9b2950..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 @@ -134,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] @@ -147,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/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala b/modules/core/shared/src/test/scala-3.0-/eu/timepit/refined/CollectionInferenceSpec.scala index f5eb22c12..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") { @@ -68,7 +67,7 @@ class CollectionInferenceSpec extends Properties("CollectionInference") { 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 } } From 34a9da850242072a22f60a369ea3748559d56ab1 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 19 May 2021 09:17:33 +0200 Subject: [PATCH 13/19] Add back scalaXmlVersion val --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index 2eaf23ce7..2e1d432f8 100644 --- a/build.sbt +++ b/build.sbt @@ -20,6 +20,7 @@ val macroParadiseVersion = "2.1.1" val pureconfigVersion = "0.15.0" val shapelessVersion = "2.3.7" val scalaCheckVersion = "1.15.4" +val scalaXmlVersion = "2.0.0" val scalazVersion = "7.3.3" val scodecVersion = "1.11.8" val scoptVersion = "4.0.1" From 3e407810a76d13137677d2a9b07c129308367550 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 27 Jul 2021 09:40:24 +0200 Subject: [PATCH 14/19] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 07c9436c9526a34841fe18adf3d46276b2f85ebc Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 27 Jul 2021 09:44:49 +0200 Subject: [PATCH 15/19] Remove xmlNonEmptyInference --- .../shared/src/main/scala-3.0+/eu/timepit/refined/string.scala | 3 --- 1 file changed, 3 deletions(-) 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 62144fc25..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 @@ -287,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") } From afde92935ba9d89c847ab84f2ec704a1a9d89d3c Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 27 Jul 2021 09:49:08 +0200 Subject: [PATCH 16/19] Auto-refining literals does not work with Scala 3 --- .../refined/scalaxml/XmlUtilSpec.scala | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala diff --git a/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala b/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala deleted file mode 100644 index 7db449390..000000000 --- a/modules/scalaxml/shared/src/test/scala/eu/timepit/refined/scalaxml/XmlUtilSpec.scala +++ /dev/null @@ -1,19 +0,0 @@ -package eu.timepit.refined.scalaxml - -import eu.timepit.refined.auto._ -import eu.timepit.refined.scalaxml.util._ -import org.scalacheck.Prop._ -import org.scalacheck.Properties -import shapeless.test.illTyped - -class XmlUtilSpec extends Properties("scalaxml.util") { - - property("xml success") = secure { - xml("") == scala.xml.XML.loadString("") - } - - property("xml failure") = secure { - illTyped("""xml("")""", "Xml predicate failed.*") - true - } -} From 371374facb1a2922d99d6bfc8f682d202fefed93 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 27 Jul 2021 10:25:28 +0200 Subject: [PATCH 17/19] Set libraryDependencySchemes in scalaxml module --- build.sbt | 3 ++- .../shared/src/main/scala-3.0-/eu/timepit/refined/string.scala | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build.sbt b/build.sbt index da053cc85..742babd59 100644 --- a/build.sbt +++ b/build.sbt @@ -290,7 +290,8 @@ lazy val shapelessJS = shapeless.js lazy val scalaxml = myCrossProject("scalaxml") .dependsOn(core % "compile->compile;test->test") .settings( - libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion + libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % scalaXmlVersion, + libraryDependencySchemes += "org.scala-lang.modules" %% "scala-xml" % "always" ) lazy val scalaxmlJVM = scalaxml.jvm 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 4ca5ea607..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 @@ -287,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") } From 28574e5b0732bf256cfe49517964ac8758368746 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 27 Jul 2021 11:08:32 +0200 Subject: [PATCH 18/19] More MiMa exclusions --- build.sbt | 54 ++++++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/build.sbt b/build.sbt index 742babd59..290349f0d 100644 --- a/build.sbt +++ b/build.sbt @@ -365,39 +365,29 @@ def moduleJvmSettings(name: String): Seq[Def.Setting[_]] = }, mimaBinaryIssueFilters ++= { import com.typesafe.tools.mima.core._ + import com.typesafe.tools.mima.core.ProblemFilters.exclude Seq( - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.api.RefType.unsafeWrapM" - ), - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.api.RefType.unsafeRewrapM" - ), - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.api.RefType.refineMF" - ), - ProblemFilters.exclude[MissingClassProblem]( - "eu.timepit.refined.internal.RefineMFullyApplied" - ), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$ConstructorNames"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$ConstructorNames$"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$FieldNames"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$FieldNames$"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Subtype"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Subtype$"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Supertype"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.generic$Supertype$"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml$"), - ProblemFilters.exclude[MissingClassProblem]("eu.timepit.refined.string$Xml"), - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.predicates.StringPredicates.Xml" - ), - ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.predicates.all.Xml"), - ProblemFilters.exclude[DirectMissingMethodProblem]( - "eu.timepit.refined.predicates.string.Xml" - ), - ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.util.string.xml"), - ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Max.findValid"), - ProblemFilters.exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Min.findValid") + exclude[DirectMissingMethodProblem]("eu.timepit.refined.api.Max.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") ) } ) From 30d667e68078015e5ada87d958856c9fe1646f1b Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 27 Jul 2021 11:14:21 +0200 Subject: [PATCH 19/19] Remove test --- .../scala-3.0-/eu/timepit/refined/StringInferenceSpec.scala | 4 ---- 1 file changed, 4 deletions(-) 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 }