From 41c86172683c7f6fdd5968f7906138a4c7482b6d Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 8 Nov 2023 18:44:37 +0100 Subject: [PATCH 01/24] Cross-build scalacheck module on scala 3 --- .github/workflows/ci.yml | 2 +- build.sbt | 4 +- .../scalacheck/ArbitraryDerivation.scala | 58 +++++++++++++ .../scalacheck}/CogenDerivation.scala | 20 ++--- .../scalacheck/ScalacheckMacros.scala | 24 ++++++ .../scalacheck/ArbitraryDerivation.scala | 54 ++++++++++++ .../scalacheck/CogenDerivation.scala | 40 +++++++++ .../scalacheck/ScalacheckMacros.scala | 9 ++ .../magnolify/scalacheck/auto/package.scala | 21 +---- .../semiauto/ArbitraryDerivation.scala | 82 ------------------- .../scalacheck/semiauto/package.scala | 16 ++++ .../scalacheck/MoreCollectionsBuildable.scala | 19 +++++ .../scalacheck/ArbitraryDerivationSuite.scala | 48 +++-------- .../scalacheck/CogenDerivationSuite.scala | 33 +++++--- .../scalacheck/FunctionDerivationSuite.scala | 17 ++-- .../magnolify/scalacheck/ScopeTest.scala | 13 ++- .../magnolify/scalacheck/TestArbitrary.scala | 56 +++++++------ .../magnolify/scalacheck/TestCogen.scala | 46 ++++++----- .../magnolify/shared/EnumTypeDerivation.scala | 8 +- .../magnolify/shared/EnumTypeMacros.scala | 7 +- .../magnolify/shared/EnumTypeDerivation.scala | 2 + .../magnolify/shared/EnumTypeMacros.scala | 4 +- 22 files changed, 345 insertions(+), 238 deletions(-) create mode 100644 scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala rename scalacheck/src/main/{scala/magnolify/scalacheck/semiauto => scala-2/magnolify/scalacheck}/CogenDerivation.scala (61%) create mode 100644 scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala create mode 100644 scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala create mode 100644 scalacheck/src/main/scala-3/magnolify/scalacheck/CogenDerivation.scala create mode 100644 scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala delete mode 100644 scalacheck/src/main/scala/magnolify/scalacheck/semiauto/ArbitraryDerivation.scala create mode 100644 scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala create mode 100644 scalacheck/src/test/scala-3/magnolify/scalacheck/MoreCollectionsBuildable.scala diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cff0905a4..0eb1171ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,7 @@ jobs: - name: Test if: matrix.scala == '3' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' shared/test test/test + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' shared/test test/test scalacheck/test - name: Check binary compatibility if: '!(matrix.scala == ''3'')' diff --git a/build.sbt b/build.sbt index 9fa0c7bed..e42c30350 100644 --- a/build.sbt +++ b/build.sbt @@ -110,7 +110,8 @@ val scala212 = "2.12.19" val scalaDefault = scala213 val scala3Projects = List( "shared", - "test" + "test", + "scalacheck" ) // github actions @@ -373,6 +374,7 @@ lazy val scalacheck = project commonSettings, moduleName := "magnolify-scalacheck", description := "Magnolia add-on for ScalaCheck", + crossScalaVersions := Seq(scala3, scala213, scala212), libraryDependencies += "org.scalacheck" %% "scalacheck" % scalacheckVersion % Provided ) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala new file mode 100644 index 000000000..9ef51531f --- /dev/null +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.scalacheck + +import magnolia1.* +import org.scalacheck.{Arbitrary, Gen} + +object ArbitraryDerivation { + type Typeclass[T] = Arbitrary[T] + + private implicit val monadicGen: Monadic[Gen] = new Monadic[Gen] { + override def point[A](value: A): Gen[A] = Gen.const(value) + override def map[A, B](from: Gen[A])(fn: A => B): Gen[B] = from.map(fn) + override def flatMap[A, B](from: Gen[A])(fn: A => Gen[B]): Gen[B] = from.flatMap(fn) + } + + def join[T](caseClass: CaseClass[Arbitrary, T]): Arbitrary[T] = Arbitrary { + caseClass.constructMonadic(_.typeclass.arbitrary) + } + + def split[T](sealedTrait: SealedTrait[Arbitrary, T]): Arbitrary[T] = Arbitrary { + Gen.lzy { + Gen.sized { size => + val subtypes = sealedTrait.subtypes + for { + i <- + if (size >= 0) { + // pick any subtype + Gen.choose(0, subtypes.size - 1) + } else { + // pick a fixed subtype to have a chance to stop recursion + Gen.const(subtypes.size + size) + } + subtypeGen <- Gen.resize(size - 1, sealedTrait.subtypes(i).typeclass.arbitrary) + } yield subtypeGen + } + } + } + + implicit def gen[T]: Arbitrary[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Arbitrary[T] = macro Magnolia.gen[T] +} diff --git a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/CogenDerivation.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/CogenDerivation.scala similarity index 61% rename from scalacheck/src/main/scala/magnolify/scalacheck/semiauto/CogenDerivation.scala rename to scalacheck/src/main/scala-2/magnolify/scalacheck/CogenDerivation.scala index 3f29618b2..88e5b4f93 100644 --- a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/CogenDerivation.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/CogenDerivation.scala @@ -14,29 +14,29 @@ * limitations under the License. */ -package magnolify.scalacheck.semiauto +package magnolify.scalacheck -import magnolia1._ +import magnolia1.* import org.scalacheck.Cogen object CogenDerivation { type Typeclass[T] = Cogen[T] - def join[T](caseClass: ReadOnlyCaseClass[Typeclass, T]): Typeclass[T] = Cogen { (seed, t) => - caseClass.parameters.foldLeft(seed) { (seed, p) => + def join[T](caseClass: CaseClass[Cogen, T]): Cogen[T] = Cogen { (seed, t) => + caseClass.parameters.foldLeft(seed) { (s, p) => // inject index to distinguish cases like `(Some(false), None)` and `(None, Some(0))` - val s = Cogen.cogenInt.perturb(seed, p.index) - p.typeclass.perturb(s, p.dereference(t)) + p.typeclass.perturb(Cogen.perturb(s, p.index), p.dereference(t)) } } - def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = Cogen { (seed, t: T) => + def split[T](sealedTrait: SealedTrait[Cogen, T]): Cogen[T] = Cogen { (seed, t) => sealedTrait.split(t) { sub => // inject index to distinguish case objects instances - val s = Cogen.cogenInt.perturb(seed, sub.index) - sub.typeclass.perturb(s, sub.cast(t)) + sub.typeclass.perturb(Cogen.perturb(seed, sub.index), sub.cast(t)) } } - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Cogen[T] = macro Magnolia.gen[T] + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Cogen[T] = macro Magnolia.gen[T] } diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala new file mode 100644 index 000000000..3e503f5bc --- /dev/null +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala @@ -0,0 +1,24 @@ +package magnolify.scalacheck + +import org.scalacheck.{Arbitrary, Cogen} + +import scala.reflect.macros.* +object ScalaCheckMacros { + def genArbitraryMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { + import c.universe._ + val wtt = weakTypeTag[T] + q"""_root_.magnolify.scalacheck.ArbitraryDerivation.gen[$wtt]""" + } + + def genCogenMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { + import c.universe._ + val wtt = weakTypeTag[T] + q"""_root_.magnolify.scalacheck.CogenDerivation.gen[$wtt]""" + } + +} + +trait AutoDerivations { + implicit def genArbitrary[T]: Arbitrary[T] = macro ScalaCheckMacros.genArbitraryMacro[T] + implicit def genCogen[T]: Cogen[T] = macro ScalaCheckMacros.genCogenMacro[T] +} diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala new file mode 100644 index 000000000..722898a0a --- /dev/null +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala @@ -0,0 +1,54 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.scalacheck + +import magnolia1.* +import org.scalacheck.{Arbitrary, Gen} + +import scala.deriving.Mirror + +object ArbitraryDerivation extends Derivation[Arbitrary]: + + private given Monadic[Gen] with + def point[A](value: A): Gen[A] = Gen.const(value) + def map[A, B](from: Gen[A])(fn: A => B): Gen[B] = from.map(fn) + def flatMap[A, B](from: Gen[A])(fn: A => Gen[B]): Gen[B] = from.flatMap(fn) + + def join[T](caseClass: CaseClass[Arbitrary, T]): Arbitrary[T] = Arbitrary { + caseClass.constructMonadic(_.typeclass.arbitrary) + } + + def split[T](sealedTrait: SealedTrait[Arbitrary, T]): Arbitrary[T] = Arbitrary { + Gen.lzy { + Gen.sized { size => + val subtypes = sealedTrait.subtypes + for { + i <- + if (size >= 0) { + // pick any subtype + Gen.choose(0, subtypes.size - 1) + } else { + // pick a fixed subtype to have a chance to stop recursion + Gen.const(subtypes.size + size) + } + subtypeGen <- Gen.resize(size - 1, sealedTrait.subtypes(i).typeclass.arbitrary) + } yield subtypeGen + } + } + } + + inline def gen[T](using Mirror.Of[T]): Arbitrary[T] = derivedMirror[T] diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/CogenDerivation.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/CogenDerivation.scala new file mode 100644 index 000000000..3cb8b226a --- /dev/null +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/CogenDerivation.scala @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.scalacheck + +import magnolia1.* +import org.scalacheck.Cogen + +import scala.deriving.Mirror + +object CogenDerivation extends Derivation[Cogen]: + + def join[T](caseClass: CaseClass[Cogen, T]): Cogen[T] = Cogen[T] { (seed, t) => + caseClass.params.foldLeft(seed) { (s, p) => + // inject index to distinguish cases like `(Some(false), None)` and `(None, Some(0))` + p.typeclass.perturb(Cogen.perturb(s, p.index), p.deref(t)) + } + } + + def split[T](sealedTrait: SealedTrait[Cogen, T]): Cogen[T] = Cogen[T] { (seed, t) => + sealedTrait.choose(t) { sub => + // inject index to distinguish case objects instances + sub.typeclass.perturb(Cogen.perturb(seed, sub.subtype.index), sub.cast(t)) + } + } + + inline def gen[T](using Mirror.Of[T]): Cogen[T] = derivedMirror[T] diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala new file mode 100644 index 000000000..d21dc6c83 --- /dev/null +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala @@ -0,0 +1,9 @@ +package magnolify.scalacheck + +import org.scalacheck.{Arbitrary, Cogen} + +import scala.deriving.Mirror +trait AutoDerivations: + + inline given genArbitrary[T](using Mirror.Of[T]): Arbitrary[T] = ArbitraryDerivation.derivedMirror[T] + inline given genCogen[T](using Mirror.Of[T]): Cogen[T] = CogenDerivation.derivedMirror[T] diff --git a/scalacheck/src/main/scala/magnolify/scalacheck/auto/package.scala b/scalacheck/src/main/scala/magnolify/scalacheck/auto/package.scala index e416350b1..fbf9a262e 100644 --- a/scalacheck/src/main/scala/magnolify/scalacheck/auto/package.scala +++ b/scalacheck/src/main/scala/magnolify/scalacheck/auto/package.scala @@ -16,23 +16,4 @@ package magnolify.scalacheck -import org.scalacheck._ - -import scala.reflect.macros._ - -package object auto { - def genArbitraryMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.scalacheck.semiauto.ArbitraryDerivation.apply[$wtt]""" - } - - def genCogenMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.scalacheck.semiauto.CogenDerivation.apply[$wtt]""" - } - - implicit def genArbitrary[T]: Arbitrary[T] = macro genArbitraryMacro[T] - implicit def genCogen[T]: Cogen[T] = macro genCogenMacro[T] -} +package object auto extends AutoDerivations diff --git a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/ArbitraryDerivation.scala b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/ArbitraryDerivation.scala deleted file mode 100644 index e6a882367..000000000 --- a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/ArbitraryDerivation.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package magnolify.scalacheck.semiauto - -import magnolia1._ -import org.scalacheck.rng.Seed -import org.scalacheck.{Arbitrary, Gen} - -object ArbitraryDerivation { - type Typeclass[T] = Arbitrary[T] - - def join[T: Fallback](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = Arbitrary { - Gen.lzy(Gen.sized { size => - if (size >= 0) { - Gen.resize(size - 1, caseClass.constructMonadic(_.typeclass.arbitrary)(monadicGen)) - } else { - implicitly[Fallback[T]].get - } - }) - } - - def split[T: Fallback](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = Arbitrary { - if (sealedTrait.typeName.full == classOf[Seed].getCanonicalName) { - // Prevent derivation of invalid seed via `Seed.apply(0, 0, 0, 0)` - // https://github.com/typelevel/scalacheck/pull/674 - Arbitrary.arbLong.arbitrary.map(Seed(_)).asInstanceOf[Gen[T]] - } else { - Gen.sized { size => - if (size > 0) { - Gen.resize( - size - 1, - Gen.oneOf(sealedTrait.subtypes.map(_.typeclass.arbitrary)).flatMap(identity) - ) - } else { - implicitly[Fallback[T]].get - } - } - } - } - - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] - - private val monadicGen: Monadic[Gen] = new Monadic[Gen] { - override def point[A](value: A): Gen[A] = Gen.const(value) - override def map[A, B](from: Gen[A])(fn: A => B): Gen[B] = from.map(fn) - override def flatMap[A, B](from: Gen[A])(fn: A => Gen[B]): Gen[B] = from.flatMap(fn) - } - - sealed trait Fallback[+T] extends Serializable { - def get: Gen[T] - } - - object Fallback { - - object NoFallback extends Fallback[Nothing] { - override def get: Gen[Nothing] = Gen.fail - } - - def apply[T](g: Gen[T]): Fallback[T] = new Fallback[T] { - override def get: Gen[T] = g - } - - def apply[T](v: T): Fallback[T] = Fallback[T](Gen.const(v)) - def apply[T](implicit arb: Arbitrary[T]): Fallback[T] = Fallback[T](arb.arbitrary) - - implicit def defaultFallback[T]: Fallback[T] = NoFallback - } -} diff --git a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala new file mode 100644 index 000000000..be5ec64e2 --- /dev/null +++ b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala @@ -0,0 +1,16 @@ +package magnolify.scalacheck + +import org.scalacheck.{Arbitrary, Cogen} + +package object semiauto { + + @deprecated("Use Arbitrary.gen[T] instead", "0.7.0") + val ArbitraryDerivation = magnolify.scalacheck.ArbitraryDerivation + @deprecated("Use Gogen.gen[T] instead", "0.7.0") + val CogenDerivation = magnolify.scalacheck.CogenDerivation + + implicit def genArbitrary(a: Arbitrary.type): magnolify.scalacheck.ArbitraryDerivation.type = + magnolify.scalacheck.ArbitraryDerivation + implicit def genCogen(c: Cogen.type): magnolify.scalacheck.CogenDerivation.type = + magnolify.scalacheck.CogenDerivation +} diff --git a/scalacheck/src/test/scala-3/magnolify/scalacheck/MoreCollectionsBuildable.scala b/scalacheck/src/test/scala-3/magnolify/scalacheck/MoreCollectionsBuildable.scala new file mode 100644 index 000000000..57404f0ba --- /dev/null +++ b/scalacheck/src/test/scala-3/magnolify/scalacheck/MoreCollectionsBuildable.scala @@ -0,0 +1,19 @@ +/* + * Copyright 2022 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.scalacheck + +object MoreCollectionsBuildable diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala index 59b896ed3..8cbe0e9b0 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala @@ -16,7 +16,6 @@ package magnolify.scalacheck -import magnolify.scalacheck.auto._ import magnolify.scalacheck.MoreCollectionsBuildable._ // extra scala 2.12 Buildable import magnolify.scalacheck.TestArbitrary.arbDuration import magnolify.scalacheck.TestArbitrary.arbUri @@ -29,14 +28,14 @@ import org.scalacheck.rng.Seed import scala.reflect._ -class ArbitraryDerivationSuite extends MagnolifySuite { +class ArbitraryDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { - private def test[T: Arbitrary: ClassTag]: Unit = test[T](None) - private def test[T: Arbitrary: ClassTag](suffix: String): Unit = test[T](Some(suffix)) + import TestArbitrary.arbSeed - private def test[T: ClassTag](suffix: Option[String])(implicit t: Arbitrary[T]): Unit = { - val g = ensureSerializable(t).arbitrary - val name = className[T] + (if (suffix == null) "" else "." + suffix) + private def test[T: ClassTag](implicit t: Arbitrary[T]): Unit = { + // TODO val g = ensureSerializable(t).arbitrary + val g = t.arbitrary + val name = className[T] val prms = Gen.Parameters.default // `forAll(Gen.listOfN(10, g))` fails for `Repeated` & `Collections` when size parameter <= 1 property(s"$name.uniqueness") { @@ -72,36 +71,13 @@ class ArbitraryDerivationSuite extends MagnolifySuite { test[Custom] - { - import magnolify.scalacheck.semiauto.ArbitraryDerivation.Fallback - implicit val f: Fallback[Node] = Fallback[Leaf] - test[Node] - } - - { - import magnolify.scalacheck.semiauto.ArbitraryDerivation.Fallback - implicit val f: Fallback[GNode[Int]] = Fallback(Gen.const(GLeaf(0))) - test[GNode[Int]]("Fallback(G: Gen[T])") - } - - { - import magnolify.scalacheck.semiauto.ArbitraryDerivation.Fallback - implicit val f: Fallback[GNode[Int]] = Fallback(GLeaf(0)) - test[GNode[Int]]("Fallback(v: T)") - } - - { - import magnolify.scalacheck.semiauto.ArbitraryDerivation.Fallback - implicit val f: Fallback[GNode[Int]] = Fallback[GLeaf[Int]] - test[GNode[Int]]("Fallback[T]") - } + // magnolia scala3 limitation: + // For a recursive structures it is required to assign the derived value to an implicit variable + implicit val arbNode: Arbitrary[Node] = genArbitrary + implicit val arbGNode: Arbitrary[GNode[Int]] = genArbitrary + test[Node] + test[GNode[Int]] test[Shape] test[Color] - - property("Seed") { - Prop.forAll { (seed: Seed) => - seed.next != seed - } - } } diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala index 8109c0a14..b619c2874 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala @@ -16,25 +16,33 @@ package magnolify.scalacheck -import magnolify.scalacheck.auto._ -import magnolify.test.ADT._ -import magnolify.test.Simple._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.test.* +import magnolify.test.ADT.* +import magnolify.test.Simple.* +import org.scalacheck.* import org.scalacheck.rng.Seed -import scala.reflect._ import java.net.URI +import scala.reflect.* -class CogenDerivationSuite extends MagnolifySuite { +class CogenDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + + import TestArbitrary.arbSeed private def test[T: ClassTag](implicit arb: Arbitrary[T], t: Cogen[T]): Unit = { - val co = ensureSerializable(t) + // TODO val co = ensureSerializable(t) + val co = t val name = className[T] implicit val arbList: Arbitrary[List[T]] = Arbitrary(Gen.listOfN(10, arb.arbitrary)) property(s"$name.uniqueness") { Prop.forAll { (seed: Seed, xs: List[T]) => - xs.map(co.perturb(seed, _)).toSet.size == xs.toSet.size + val coper = xs.map(co.perturb(seed, _)) + val result = coper.toSet.size == xs.toSet.size + if (!result) { + println("coper: " + coper) + println("origin: " + xs) + } + result } } property(s"$name.consistency") { @@ -44,7 +52,7 @@ class CogenDerivationSuite extends MagnolifySuite { } } - import magnolify.scalacheck.TestArbitrary._ + import magnolify.scalacheck.TestArbitrary.* implicit val cogenUri: Cogen[URI] = Cogen(_.hashCode().toLong) test[Numbers] @@ -56,6 +64,11 @@ class CogenDerivationSuite extends MagnolifySuite { test[Nested] test[Custom] + // magnolia scala3 limitation: + // For a recursive structures it is required to assign the derived value to an implicit variable + implicit val cogenNode: Cogen[Node] = genCogen + implicit val cogenGNode: Cogen[GNode[Int]] = genCogen + test[Node] test[GNode[Int]] test[Shape] diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala index 7b18cc1b5..1745711a0 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala @@ -18,18 +18,18 @@ package magnolify.scalacheck import magnolify.test.Simple._ import magnolify.test.ADT._ -import magnolify.scalacheck.auto._ import magnolify.test._ import org.scalacheck._ import scala.reflect._ -class FunctionDerivationSuite extends MagnolifySuite { +class FunctionDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { private def test[A: ClassTag, B: ClassTag](implicit t: Arbitrary[A => B], arbA: Arbitrary[A] ): Unit = { - val gf = ensureSerializable(t).arbitrary + // TODO val gf = ensureSerializable(t).arbitrary + val gf = t.arbitrary val ga = arbA.arbitrary val name = s"${className[A]}.${className[B]}" property(s"$name.consistency") { @@ -45,14 +45,7 @@ class FunctionDerivationSuite extends MagnolifySuite { } test[Numbers, Numbers] - - { - // Gen[A => B] depends on Gen[B] and may run out of size - import magnolify.scalacheck.semiauto.ArbitraryDerivation.Fallback - implicit val f: Fallback[Shape] = Fallback[Circle] - test[Shape, Shape] - test[Numbers, Shape] - } - + test[Shape, Shape] + test[Numbers, Shape] test[Shape, Numbers] } diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala index df59d2e07..498a54692 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala @@ -16,21 +16,20 @@ package magnolify.scalacheck -import magnolify.test.Simple._ -import org.scalacheck._ +import magnolify.test.Simple.* +import org.scalacheck.* object ScopeTest { - object Auto { - import magnolify.scalacheck.auto._ + object Auto extends magnolify.scalacheck.AutoDerivations { implicitly[Arbitrary[Numbers]] implicitly[Cogen[Numbers]] implicitly[Arbitrary[Numbers => Numbers]] } object Semi { - import magnolify.scalacheck.semiauto._ - implicit val arb: Arbitrary[Numbers] = ArbitraryDerivation[Numbers] - implicit val cogen: Cogen[Numbers] = CogenDerivation[Numbers] + import magnolify.scalacheck.semiauto.* + implicit val arb: Arbitrary[Numbers] = Arbitrary.gen[Numbers] + implicit val cogen: Cogen[Numbers] = Cogen.gen[Numbers] // T => T is not a case class, so ArbitraryDerivation.apply won't work implicitly[Arbitrary[Numbers => Numbers]] } diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala b/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala index c0d9de75e..513a1e71c 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/TestArbitrary.scala @@ -16,19 +16,25 @@ package magnolify.scalacheck -import magnolify.scalacheck.semiauto.ArbitraryDerivation +import magnolify.scalacheck.semiauto.* import magnolify.shared.UnsafeEnum -import magnolify.test.ADT._ +import magnolify.test.ADT.* import magnolify.test.JavaEnums -import magnolify.test.Simple._ -import org.joda.{time => joda} -import org.scalacheck._ +import magnolify.test.Simple.* +import org.joda.time as joda +import org.scalacheck.* +import org.scalacheck.rng.Seed import java.net.URI import java.nio.ByteBuffer -import java.time._ +import java.time.* object TestArbitrary { + // seed + implicit lazy val arbSeed: Arbitrary[Seed] = Arbitrary( + Arbitrary.arbLong.arbitrary.map(Seed.apply) + ) + // null implicit lazy val arbNull: Arbitrary[Null] = Arbitrary(Gen.const(null)) @@ -93,29 +99,29 @@ object TestArbitrary { } // ADT - implicit lazy val arbNode: Arbitrary[Node] = ArbitraryDerivation[Node] - implicit lazy val arbGNode: Arbitrary[GNode[Int]] = ArbitraryDerivation[GNode[Int]] - implicit lazy val arbShape: Arbitrary[Shape] = ArbitraryDerivation[Shape] - implicit lazy val arbColor: Arbitrary[Color] = ArbitraryDerivation[Color] - implicit lazy val arbPerson: Arbitrary[Person] = ArbitraryDerivation[Person] + implicit lazy val arbNode: Arbitrary[Node] = Arbitrary.gen[Node] + implicit lazy val arbGNode: Arbitrary[GNode[Int]] = Arbitrary.gen[GNode[Int]] + implicit lazy val arbShape: Arbitrary[Shape] = Arbitrary.gen[Shape] + implicit lazy val arbColor: Arbitrary[Color] = Arbitrary.gen[Color] + implicit lazy val arbPerson: Arbitrary[Person] = Arbitrary.gen[Person] // simple - implicit lazy val arbIntegers: Arbitrary[Integers] = ArbitraryDerivation[Integers] - implicit lazy val arbFloats: Arbitrary[Floats] = ArbitraryDerivation[Floats] - implicit lazy val arbNumbers: Arbitrary[Numbers] = ArbitraryDerivation[Numbers] - implicit lazy val arbRequired: Arbitrary[Required] = ArbitraryDerivation[Required] - implicit lazy val arbNullable: Arbitrary[Nullable] = ArbitraryDerivation[Nullable] - implicit lazy val arbRepeated: Arbitrary[Repeated] = ArbitraryDerivation[Repeated] - implicit lazy val arbNested: Arbitrary[Nested] = ArbitraryDerivation[Nested] - implicit lazy val arbCollections: Arbitrary[Collections] = ArbitraryDerivation[Collections] + implicit lazy val arbIntegers: Arbitrary[Integers] = Arbitrary.gen[Integers] + implicit lazy val arbFloats: Arbitrary[Floats] = Arbitrary.gen[Floats] + implicit lazy val arbNumbers: Arbitrary[Numbers] = Arbitrary.gen[Numbers] + implicit lazy val arbRequired: Arbitrary[Required] = Arbitrary.gen[Required] + implicit lazy val arbNullable: Arbitrary[Nullable] = Arbitrary.gen[Nullable] + implicit lazy val arbRepeated: Arbitrary[Repeated] = Arbitrary.gen[Repeated] + implicit lazy val arbNested: Arbitrary[Nested] = Arbitrary.gen[Nested] + implicit lazy val arbCollections: Arbitrary[Collections] = Arbitrary.gen[Collections] implicit lazy val arbMoreCollections: Arbitrary[MoreCollections] = - ArbitraryDerivation[MoreCollections] - implicit lazy val arbEnums: Arbitrary[Enums] = ArbitraryDerivation[Enums] - implicit lazy val arbUnsafeEnums: Arbitrary[UnsafeEnums] = ArbitraryDerivation[UnsafeEnums] - implicit lazy val arbCustom: Arbitrary[Custom] = ArbitraryDerivation[Custom] - implicit lazy val arbLowerCamel: Arbitrary[LowerCamel] = ArbitraryDerivation[LowerCamel] + Arbitrary.gen[MoreCollections] + implicit lazy val arbEnums: Arbitrary[Enums] = Arbitrary.gen[Enums] + implicit lazy val arbUnsafeEnums: Arbitrary[UnsafeEnums] = Arbitrary.gen[UnsafeEnums] + implicit lazy val arbCustom: Arbitrary[Custom] = Arbitrary.gen[Custom] + implicit lazy val arbLowerCamel: Arbitrary[LowerCamel] = Arbitrary.gen[LowerCamel] implicit lazy val arbLowerCamelInner: Arbitrary[LowerCamelInner] = - ArbitraryDerivation[LowerCamelInner] + Arbitrary.gen[LowerCamelInner] // other implicit lazy val arbUri: Arbitrary[URI] = Arbitrary(Gen.alphaNumStr.map(URI.create)) diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala index b32e59f8b..82ca6e678 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala @@ -16,10 +16,11 @@ package magnolify.scalacheck -import magnolify.scalacheck.semiauto.CogenDerivation -import magnolify.test.ADT._ +import magnolify.scalacheck.semiauto.* +import magnolify.shared.UnsafeEnum +import magnolify.test.ADT.* import magnolify.test.JavaEnums -import magnolify.test.Simple._ +import magnolify.test.Simple.* import org.scalacheck.Cogen import java.net.URI @@ -28,29 +29,30 @@ object TestCogen { // enum implicit lazy val coJavaEnum: Cogen[JavaEnums.Color] = Cogen(_.ordinal().toLong) implicit lazy val coScalaEnums: Cogen[ScalaEnums.Color.Type] = Cogen(_.id.toLong) + implicit def coUnsafeEnum[T: Cogen]: Cogen[UnsafeEnum[T]] = Cogen.gen[UnsafeEnum[T]] // ADT - implicit lazy val coNode: Cogen[Node] = CogenDerivation[Node] - implicit lazy val coGNode: Cogen[GNode[Int]] = CogenDerivation[GNode[Int]] - implicit lazy val coShape: Cogen[Shape] = CogenDerivation[Shape] - implicit lazy val coColor: Cogen[Color] = CogenDerivation[Color] - implicit lazy val coPerson: Cogen[Person] = CogenDerivation[Person] + implicit lazy val coNode: Cogen[Node] = Cogen.gen + implicit lazy val coGNode: Cogen[GNode[Int]] = Cogen.gen + implicit lazy val coShape: Cogen[Shape] = Cogen.gen + implicit lazy val coColor: Cogen[Color] = Cogen.gen + implicit lazy val coPerson: Cogen[Person] = Cogen.gen // simple - implicit lazy val coIntegers: Cogen[Integers] = CogenDerivation[Integers] - implicit lazy val coFloats: Cogen[Floats] = CogenDerivation[Floats] - implicit lazy val coNumbers: Cogen[Numbers] = CogenDerivation[Numbers] - implicit lazy val coRequired: Cogen[Required] = CogenDerivation[Required] - implicit lazy val coNullable: Cogen[Nullable] = CogenDerivation[Nullable] - implicit lazy val coRepeated: Cogen[Repeated] = CogenDerivation[Repeated] - implicit lazy val coNested: Cogen[Nested] = CogenDerivation[Nested] - implicit lazy val coCollections: Cogen[Collections] = CogenDerivation[Collections] - // implicit lazy val coMoreCollections: Cogen[MoreCollections] = CogenDerivation[MoreCollections] - implicit lazy val coEnums: Cogen[Enums] = CogenDerivation[Enums] - implicit lazy val coUnsafeEnums: Cogen[UnsafeEnums] = CogenDerivation[UnsafeEnums] - implicit lazy val coCustom: Cogen[Custom] = CogenDerivation[Custom] - implicit lazy val coLowerCamel: Cogen[LowerCamel] = CogenDerivation[LowerCamel] - implicit lazy val coLowerCamelInner: Cogen[LowerCamelInner] = CogenDerivation[LowerCamelInner] + implicit lazy val coIntegers: Cogen[Integers] = Cogen.gen[Integers] + implicit lazy val coFloats: Cogen[Floats] = Cogen.gen[Floats] + implicit lazy val coNumbers: Cogen[Numbers] = Cogen.gen[Numbers] + implicit lazy val coRequired: Cogen[Required] = Cogen.gen[Required] + implicit lazy val coNullable: Cogen[Nullable] = Cogen.gen[Nullable] + implicit lazy val coRepeated: Cogen[Repeated] = Cogen.gen[Repeated] + implicit lazy val coNested: Cogen[Nested] = Cogen.gen[Nested] + implicit lazy val coCollections: Cogen[Collections] = Cogen.gen[Collections] + // implicit lazy val coMoreCollections: Cogen[MoreCollections] = Cogen.gen[MoreCollections] + implicit lazy val coEnums: Cogen[Enums] = Cogen.gen[Enums] + implicit lazy val coUnsafeEnums: Cogen[UnsafeEnums] = Cogen.gen[UnsafeEnums] + implicit lazy val coCustom: Cogen[Custom] = Cogen.gen[Custom] + implicit lazy val coLowerCamel: Cogen[LowerCamel] = Cogen.gen[LowerCamel] + implicit lazy val coLowerCamelInner: Cogen[LowerCamelInner] = Cogen.gen[LowerCamelInner] // other implicit lazy val coUri: Cogen[URI] = Cogen(_.hashCode().toLong) diff --git a/shared/src/main/scala-2/magnolify/shared/EnumTypeDerivation.scala b/shared/src/main/scala-2/magnolify/shared/EnumTypeDerivation.scala index 249030ccf..f2ae647ee 100644 --- a/shared/src/main/scala-2/magnolify/shared/EnumTypeDerivation.scala +++ b/shared/src/main/scala-2/magnolify/shared/EnumTypeDerivation.scala @@ -16,7 +16,7 @@ package magnolify.shared -import magnolia1.{CaseClass, SealedTrait} +import magnolia1.{CaseClass, Magnolia, SealedTrait} import scala.annotation.implicitNotFound @@ -32,7 +32,7 @@ trait EnumTypeDerivation { implicit def genEnumValue[T]: EnumValue[T] = macro EnumTypeMacros.genEnumValueMacro[T] - def join[T: EnumValue](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T: EnumValue](caseClass: CaseClass[EnumType, T]): EnumType[T] = { val n = caseClass.typeName.short val ns = caseClass.typeName.owner EnumType.create( @@ -44,7 +44,7 @@ trait EnumTypeDerivation { ) } - def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = { + def split[T](sealedTrait: SealedTrait[EnumType, T]): EnumType[T] = { val n = sealedTrait.typeName.short val ns = sealedTrait.typeName.owner val subs = sealedTrait.subtypes.map(_.typeclass) @@ -60,4 +60,6 @@ trait EnumTypeDerivation { v => subs.find(_.name == v).get.from(v) ) } + + implicit def gen[T]: EnumType[T] = macro Magnolia.gen[T] } diff --git a/shared/src/main/scala-2/magnolify/shared/EnumTypeMacros.scala b/shared/src/main/scala-2/magnolify/shared/EnumTypeMacros.scala index 7a9f4f3bf..19646df78 100644 --- a/shared/src/main/scala-2/magnolify/shared/EnumTypeMacros.scala +++ b/shared/src/main/scala-2/magnolify/shared/EnumTypeMacros.scala @@ -16,7 +16,6 @@ package magnolify.shared -import magnolia1.Magnolia import scala.reflect.macros.whitebox object EnumTypeMacros { @@ -51,11 +50,7 @@ object EnumTypeMacros { } } -trait EnumTypeCompanionMacros extends EnumTypeCompanionLowPrioMacros { +trait EnumTypeCompanionMacros extends EnumTypeDerivation { implicit def scalaEnumType[T <: Enumeration#Value: AnnotationType]: EnumType[T] = macro EnumTypeMacros.scalaEnumTypeMacro[T] } - -trait EnumTypeCompanionLowPrioMacros extends EnumTypeDerivation { - implicit def gen[T]: EnumType[T] = macro Magnolia.gen[T] -} diff --git a/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala b/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala index 784ff722d..18fc199b8 100644 --- a/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala +++ b/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala @@ -75,3 +75,5 @@ trait EnumTypeDerivation extends CommonDerivation[EnumType] with SealedTraitDeri v => subs.find(_.name == v).get.from(v) ) end split + + inline given gen[T](using Mirror.Of[T]): EnumType[T] = derivedMirror[T] diff --git a/shared/src/main/scala-3/magnolify/shared/EnumTypeMacros.scala b/shared/src/main/scala-3/magnolify/shared/EnumTypeMacros.scala index ffbf59ecd..fde9a36be 100644 --- a/shared/src/main/scala-3/magnolify/shared/EnumTypeMacros.scala +++ b/shared/src/main/scala-3/magnolify/shared/EnumTypeMacros.scala @@ -17,7 +17,6 @@ package magnolify.shared import scala.quoted.* -import scala.deriving.Mirror object EnumTypeMacros: def scalaEnumTypeMacro[T: Type](annotations: Expr[AnnotationType[T]])(using @@ -43,5 +42,4 @@ trait EnumTypeCompanionMacros0 extends EnumTypeCompanionMacros1: ): EnumType[T] = ${ EnumTypeMacros.scalaEnumTypeMacro[T]('annotations) } -trait EnumTypeCompanionMacros1 extends EnumTypeDerivation: - inline implicit def gen[T](using Mirror.Of[T]): EnumType[T] = derivedMirror[T] +trait EnumTypeCompanionMacros1 extends EnumTypeDerivation From 2370500a57e5b1782596cda6ad294237acdb4ed2 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 8 Nov 2023 18:54:58 +0100 Subject: [PATCH 02/24] Keep type param --- .../test/scala/magnolify/scalacheck/TestCogen.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala index 82ca6e678..61da28e17 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala @@ -32,11 +32,11 @@ object TestCogen { implicit def coUnsafeEnum[T: Cogen]: Cogen[UnsafeEnum[T]] = Cogen.gen[UnsafeEnum[T]] // ADT - implicit lazy val coNode: Cogen[Node] = Cogen.gen - implicit lazy val coGNode: Cogen[GNode[Int]] = Cogen.gen - implicit lazy val coShape: Cogen[Shape] = Cogen.gen - implicit lazy val coColor: Cogen[Color] = Cogen.gen - implicit lazy val coPerson: Cogen[Person] = Cogen.gen + implicit lazy val coNode: Cogen[Node] = Cogen.gen[Node] + implicit lazy val coGNode: Cogen[GNode[Int]] = Cogen.gen[GNode[Int]] + implicit lazy val coShape: Cogen[Shape] = Cogen.gen[Shape] + implicit lazy val coColor: Cogen[Color] = Cogen.gen[Color] + implicit lazy val coPerson: Cogen[Person] = Cogen.gen[Person] // simple implicit lazy val coIntegers: Cogen[Integers] = Cogen.gen[Integers] From f85ac196f277fb3e3d8c294cd64bb31e4c8aa37b Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Thu, 9 Nov 2023 15:19:02 +0100 Subject: [PATCH 03/24] Add missing headers --- .../magnolify/scalacheck/ScalacheckMacros.scala | 16 ++++++++++++++++ .../magnolify/scalacheck/semiauto/package.scala | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala index 3e503f5bc..5e97d5417 100644 --- a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package magnolify.scalacheck import org.scalacheck.{Arbitrary, Cogen} diff --git a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala index be5ec64e2..49968882c 100644 --- a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala +++ b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package magnolify.scalacheck import org.scalacheck.{Arbitrary, Cogen} From 6f0c832835b7eb290efb619a89bc5aa3b87107c3 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Mon, 13 Nov 2023 14:58:00 +0100 Subject: [PATCH 04/24] Prefer explicit imports instead of trait mixin --- .../magnolify/scalacheck/ArbitraryDerivationSuite.scala | 4 ++-- .../scala/magnolify/scalacheck/CogenDerivationSuite.scala | 4 ++-- .../scala/magnolify/scalacheck/FunctionDerivationSuite.scala | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala index 8cbe0e9b0..692fafafa 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala @@ -28,9 +28,9 @@ import org.scalacheck.rng.Seed import scala.reflect._ -class ArbitraryDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { - +class ArbitraryDerivationSuite extends MagnolifySuite { import TestArbitrary.arbSeed + import magnolify.scalacheck.auto.genArbitrary private def test[T: ClassTag](implicit t: Arbitrary[T]): Unit = { // TODO val g = ensureSerializable(t).arbitrary diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala index b619c2874..4c3362d0b 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala @@ -25,9 +25,9 @@ import org.scalacheck.rng.Seed import java.net.URI import scala.reflect.* -class CogenDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { - +class CogenDerivationSuite extends MagnolifySuite { import TestArbitrary.arbSeed + import magnolify.scalacheck.auto.genCogen private def test[T: ClassTag](implicit arb: Arbitrary[T], t: Cogen[T]): Unit = { // TODO val co = ensureSerializable(t) diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala index 1745711a0..6db978569 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala @@ -23,7 +23,10 @@ import org.scalacheck._ import scala.reflect._ -class FunctionDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class FunctionDerivationSuite extends MagnolifySuite { + import magnolify.scalacheck.auto.genCogen + import magnolify.scalacheck.auto.genArbitrary + private def test[A: ClassTag, B: ClassTag](implicit t: Arbitrary[A => B], arbA: Arbitrary[A] From b2881d4a90f0270d5e00078d407888f3dfa5fef8 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 3 Jan 2024 11:56:10 +0100 Subject: [PATCH 05/24] Revert to implicit in shared --- .../src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala b/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala index 18fc199b8..eccf6ba7a 100644 --- a/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala +++ b/shared/src/main/scala-3/magnolify/shared/EnumTypeDerivation.scala @@ -76,4 +76,4 @@ trait EnumTypeDerivation extends CommonDerivation[EnumType] with SealedTraitDeri ) end split - inline given gen[T](using Mirror.Of[T]): EnumType[T] = derivedMirror[T] + inline implicit def gen[T](using Mirror.Of[T]): EnumType[T] = derivedMirror[T] From 0cc8b047243e9e93ce0ed4413cb4975885495753 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 3 Jan 2024 12:01:15 +0100 Subject: [PATCH 06/24] Use implicit instead of given --- .../scala-3/magnolify/scalacheck/ScalacheckMacros.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala index d21dc6c83..14aa04286 100644 --- a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala @@ -3,7 +3,9 @@ package magnolify.scalacheck import org.scalacheck.{Arbitrary, Cogen} import scala.deriving.Mirror -trait AutoDerivations: - inline given genArbitrary[T](using Mirror.Of[T]): Arbitrary[T] = ArbitraryDerivation.derivedMirror[T] - inline given genCogen[T](using Mirror.Of[T]): Cogen[T] = CogenDerivation.derivedMirror[T] +trait AutoDerivations: + inline implicit def genArbitrary[T](using Mirror.Of[T]): Arbitrary[T] = + ArbitraryDerivation.derivedMirror[T] + inline implicit def genCogen[T](using Mirror.Of[T]): Cogen[T] = + CogenDerivation.derivedMirror[T] From 3b6ee33c9e4c914c75f339d1207e5c2b6e52382d Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 3 Jan 2024 12:16:31 +0100 Subject: [PATCH 07/24] Add missing header --- .../magnolify/scalacheck/ScalacheckMacros.scala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala index 14aa04286..789fe7ca8 100644 --- a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2024 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package magnolify.scalacheck import org.scalacheck.{Arbitrary, Cogen} From 0ae6c95a4bccb70b4902d0440bc3efb774241f23 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 3 Jan 2024 17:48:40 +0100 Subject: [PATCH 08/24] Fix scala3 warning --- build.sbt | 4 +++- .../src/test/scala/magnolify/scalacheck/TestCogen.scala | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index e42c30350..e70e0c9ab 100644 --- a/build.sbt +++ b/build.sbt @@ -268,7 +268,9 @@ val commonSettings = Seq( "-Yretain-trees", // tolerate some nested macro expansion "-Xmax-inlines", - "64" + "64", + // silence warnings. dotty doesn't have unused-imports category nor origin support yet + "-Wconf:msg=unused import:s" ) case Some((2, 13)) => Seq( diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala index 61da28e17..418f21e7f 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/TestCogen.scala @@ -22,6 +22,7 @@ import magnolify.test.ADT.* import magnolify.test.JavaEnums import magnolify.test.Simple.* import org.scalacheck.Cogen +import org.scalacheck.rng.Seed import java.net.URI @@ -29,7 +30,13 @@ object TestCogen { // enum implicit lazy val coJavaEnum: Cogen[JavaEnums.Color] = Cogen(_.ordinal().toLong) implicit lazy val coScalaEnums: Cogen[ScalaEnums.Color.Type] = Cogen(_.id.toLong) - implicit def coUnsafeEnum[T: Cogen]: Cogen[UnsafeEnum[T]] = Cogen.gen[UnsafeEnum[T]] + implicit def coUnsafeEnum[T: Cogen]: Cogen[UnsafeEnum[T]] = + Cogen { (seed: Seed, value: UnsafeEnum[T]) => + value match { + case UnsafeEnum.Known(v) => Cogen[T].perturb(seed, v) + case UnsafeEnum.Unknown(v) => Cogen[String].perturb(seed, v) + } + } // ADT implicit lazy val coNode: Cogen[Node] = Cogen.gen[Node] From ca19751767d7714dede52568c197f864d2fafd05 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Fri, 5 Jan 2024 09:46:07 +0100 Subject: [PATCH 09/24] Remove trace --- .../scala/magnolify/scalacheck/CogenDerivationSuite.scala | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala index 4c3362d0b..e491eae68 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala @@ -36,13 +36,7 @@ class CogenDerivationSuite extends MagnolifySuite { implicit val arbList: Arbitrary[List[T]] = Arbitrary(Gen.listOfN(10, arb.arbitrary)) property(s"$name.uniqueness") { Prop.forAll { (seed: Seed, xs: List[T]) => - val coper = xs.map(co.perturb(seed, _)) - val result = coper.toSet.size == xs.toSet.size - if (!result) { - println("coper: " + coper) - println("origin: " + xs) - } - result + xs.map(co.perturb(seed, _)).toSet.size == xs.toSet.size } } property(s"$name.consistency") { From 27a00dfda634939c08423d5fda78d77239282e97 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Tue, 9 Jan 2024 16:43:05 +0100 Subject: [PATCH 10/24] Change year in header --- .../main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala | 2 +- .../main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala index 9ef51531f..06d61566b 100644 --- a/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala @@ -1,5 +1,5 @@ /* - * Copyright 2019 Spotify AB + * Copyright 2024 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala index 722898a0a..f64ae6dc6 100644 --- a/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala @@ -1,5 +1,5 @@ /* - * Copyright 2023 Spotify AB + * Copyright 2024 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 8e79b3212d62b46b4a535fd4263615e1e676db77 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Tue, 9 Jan 2024 16:55:39 +0100 Subject: [PATCH 11/24] Update doc --- docs/scalacheck.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/scalacheck.md b/docs/scalacheck.md index 2542cf3e2..aae5826bf 100644 --- a/docs/scalacheck.md +++ b/docs/scalacheck.md @@ -25,6 +25,6 @@ import org.scalacheck._ case class Inner(int: Int, str: String) case class Outer(inner: Inner) -val arb: Arbitrary[Outer] = ArbitraryDerivation[Outer] -val cogen: Cogen[Outer] = CogenDerivation[Outer] +val arb: Arbitrary[Outer] = Arbitrary.gen[Outer] +val cogen: Cogen[Outer] = Cogen.gen[Outer] ``` From dcadec99dcf4ea0ee565d023cccee9f09148d6aa Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 22 May 2024 14:04:16 +0200 Subject: [PATCH 12/24] Simplify arbitrary derivation --- .../main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala | 2 +- .../main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala index 06d61566b..9ff13415e 100644 --- a/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ArbitraryDerivation.scala @@ -45,7 +45,7 @@ object ArbitraryDerivation { // pick a fixed subtype to have a chance to stop recursion Gen.const(subtypes.size + size) } - subtypeGen <- Gen.resize(size - 1, sealedTrait.subtypes(i).typeclass.arbitrary) + subtypeGen <- Gen.resize(size - 1, subtypes(i).typeclass.arbitrary) } yield subtypeGen } } diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala index f64ae6dc6..0a32e7262 100644 --- a/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ArbitraryDerivation.scala @@ -45,7 +45,7 @@ object ArbitraryDerivation extends Derivation[Arbitrary]: // pick a fixed subtype to have a chance to stop recursion Gen.const(subtypes.size + size) } - subtypeGen <- Gen.resize(size - 1, sealedTrait.subtypes(i).typeclass.arbitrary) + subtypeGen <- Gen.resize(size - 1, subtypes(i).typeclass.arbitrary) } yield subtypeGen } } From 35966e6916a09fc2ad4f3cff82573ebb6d4fa878 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 22 May 2024 14:17:28 +0200 Subject: [PATCH 13/24] Update to next minor version --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index e70e0c9ab..35c986bf1 100644 --- a/build.sbt +++ b/build.sbt @@ -46,7 +46,7 @@ val tensorflowMetadataVersion = "1.10.0" val tensorflowVersion = "0.5.0" // project -ThisBuild / tlBaseVersion := "0.7" +ThisBuild / tlBaseVersion := "0.8" ThisBuild / tlSonatypeUseLegacyHost := true ThisBuild / organization := "com.spotify" ThisBuild / organizationName := "Spotify AB" From 45bcb1c873d19612d3ce244e460159f2c2186ab9 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 22 May 2024 14:29:04 +0200 Subject: [PATCH 14/24] Use import instead of mixin trait --- scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala index 498a54692..8687371c0 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ScopeTest.scala @@ -20,7 +20,8 @@ import magnolify.test.Simple.* import org.scalacheck.* object ScopeTest { - object Auto extends magnolify.scalacheck.AutoDerivations { + object Auto { + import magnolify.scalacheck.auto.* implicitly[Arbitrary[Numbers]] implicitly[Cogen[Numbers]] implicitly[Arbitrary[Numbers => Numbers]] From 0125b325feb345f0dba9cb9fd76075e62d74d4e3 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Mon, 27 May 2024 10:22:05 +0200 Subject: [PATCH 15/24] Avoid implicit name conflict --- .../scala-2/magnolify/scalacheck/ScalacheckMacros.scala | 9 +++++---- .../scala-3/magnolify/scalacheck/ScalacheckMacros.scala | 4 ++-- .../scala/magnolify/scalacheck/semiauto/package.scala | 6 ++++-- .../magnolify/scalacheck/ArbitraryDerivationSuite.scala | 7 ++++--- .../magnolify/scalacheck/CogenDerivationSuite.scala | 7 ++++--- .../magnolify/scalacheck/FunctionDerivationSuite.scala | 3 +-- 6 files changed, 20 insertions(+), 16 deletions(-) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala index 5e97d5417..bfcb89516 100644 --- a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala @@ -20,13 +20,13 @@ import org.scalacheck.{Arbitrary, Cogen} import scala.reflect.macros.* object ScalaCheckMacros { - def genArbitraryMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { + def autoDerivationArbitrary[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { import c.universe._ val wtt = weakTypeTag[T] q"""_root_.magnolify.scalacheck.ArbitraryDerivation.gen[$wtt]""" } - def genCogenMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { + def autoDerivationCogen[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { import c.universe._ val wtt = weakTypeTag[T] q"""_root_.magnolify.scalacheck.CogenDerivation.gen[$wtt]""" @@ -35,6 +35,7 @@ object ScalaCheckMacros { } trait AutoDerivations { - implicit def genArbitrary[T]: Arbitrary[T] = macro ScalaCheckMacros.genArbitraryMacro[T] - implicit def genCogen[T]: Cogen[T] = macro ScalaCheckMacros.genCogenMacro[T] + implicit def autoDerivationArbitrary[T]: Arbitrary[T] = + macro ScalaCheckMacros.autoDerivationArbitrary[T] + implicit def autoDerivationCogen[T]: Cogen[T] = macro ScalaCheckMacros.autoDerivationCogen[T] } diff --git a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala index 789fe7ca8..d699de7da 100644 --- a/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-3/magnolify/scalacheck/ScalacheckMacros.scala @@ -21,7 +21,7 @@ import org.scalacheck.{Arbitrary, Cogen} import scala.deriving.Mirror trait AutoDerivations: - inline implicit def genArbitrary[T](using Mirror.Of[T]): Arbitrary[T] = + inline implicit def autoDerivationArbitrary[T](using Mirror.Of[T]): Arbitrary[T] = ArbitraryDerivation.derivedMirror[T] - inline implicit def genCogen[T](using Mirror.Of[T]): Cogen[T] = + inline implicit def autoDerivationCogen[T](using Mirror.Of[T]): Cogen[T] = CogenDerivation.derivedMirror[T] diff --git a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala index 49968882c..50cbf3028 100644 --- a/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala +++ b/scalacheck/src/main/scala/magnolify/scalacheck/semiauto/package.scala @@ -25,8 +25,10 @@ package object semiauto { @deprecated("Use Gogen.gen[T] instead", "0.7.0") val CogenDerivation = magnolify.scalacheck.CogenDerivation - implicit def genArbitrary(a: Arbitrary.type): magnolify.scalacheck.ArbitraryDerivation.type = + implicit def semiautoDerivationArbitrary( + a: Arbitrary.type + ): magnolify.scalacheck.ArbitraryDerivation.type = magnolify.scalacheck.ArbitraryDerivation - implicit def genCogen(c: Cogen.type): magnolify.scalacheck.CogenDerivation.type = + implicit def semiautoDerivationCogen(c: Cogen.type): magnolify.scalacheck.CogenDerivation.type = magnolify.scalacheck.CogenDerivation } diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala index 692fafafa..f2ebbb9ba 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/ArbitraryDerivationSuite.scala @@ -30,7 +30,7 @@ import scala.reflect._ class ArbitraryDerivationSuite extends MagnolifySuite { import TestArbitrary.arbSeed - import magnolify.scalacheck.auto.genArbitrary + import magnolify.scalacheck.auto.autoDerivationArbitrary private def test[T: ClassTag](implicit t: Arbitrary[T]): Unit = { // TODO val g = ensureSerializable(t).arbitrary @@ -73,8 +73,9 @@ class ArbitraryDerivationSuite extends MagnolifySuite { // magnolia scala3 limitation: // For a recursive structures it is required to assign the derived value to an implicit variable - implicit val arbNode: Arbitrary[Node] = genArbitrary - implicit val arbGNode: Arbitrary[GNode[Int]] = genArbitrary + import magnolify.scalacheck.semiauto.semiautoDerivationArbitrary + implicit val arbNode: Arbitrary[Node] = Arbitrary.gen + implicit val arbGNode: Arbitrary[GNode[Int]] = Arbitrary.gen test[Node] test[GNode[Int]] diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala index e491eae68..73858da15 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/CogenDerivationSuite.scala @@ -27,7 +27,7 @@ import scala.reflect.* class CogenDerivationSuite extends MagnolifySuite { import TestArbitrary.arbSeed - import magnolify.scalacheck.auto.genCogen + import magnolify.scalacheck.auto.autoDerivationCogen private def test[T: ClassTag](implicit arb: Arbitrary[T], t: Cogen[T]): Unit = { // TODO val co = ensureSerializable(t) @@ -60,8 +60,9 @@ class CogenDerivationSuite extends MagnolifySuite { // magnolia scala3 limitation: // For a recursive structures it is required to assign the derived value to an implicit variable - implicit val cogenNode: Cogen[Node] = genCogen - implicit val cogenGNode: Cogen[GNode[Int]] = genCogen + import magnolify.scalacheck.semiauto.semiautoDerivationCogen + implicit val cogenNode: Cogen[Node] = Cogen.gen + implicit val cogenGNode: Cogen[GNode[Int]] = Cogen.gen test[Node] test[GNode[Int]] diff --git a/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala index 6db978569..63cce1116 100644 --- a/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala +++ b/scalacheck/src/test/scala/magnolify/scalacheck/FunctionDerivationSuite.scala @@ -24,8 +24,7 @@ import org.scalacheck._ import scala.reflect._ class FunctionDerivationSuite extends MagnolifySuite { - import magnolify.scalacheck.auto.genCogen - import magnolify.scalacheck.auto.genArbitrary + import magnolify.scalacheck.auto._ private def test[A: ClassTag, B: ClassTag](implicit t: Arbitrary[A => B], From 450d598881889354dbd37c16976015be97cb32df Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Fri, 31 May 2024 14:38:15 +0200 Subject: [PATCH 16/24] Streamline macro naming --- .../scala-2/magnolify/scalacheck/ScalacheckMacros.scala | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala index bfcb89516..265c4a3f0 100644 --- a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala @@ -20,13 +20,13 @@ import org.scalacheck.{Arbitrary, Cogen} import scala.reflect.macros.* object ScalaCheckMacros { - def autoDerivationArbitrary[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { + def autoDerivationArbitraryMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { import c.universe._ val wtt = weakTypeTag[T] q"""_root_.magnolify.scalacheck.ArbitraryDerivation.gen[$wtt]""" } - def autoDerivationCogen[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { + def autoDerivationCogenMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { import c.universe._ val wtt = weakTypeTag[T] q"""_root_.magnolify.scalacheck.CogenDerivation.gen[$wtt]""" @@ -36,6 +36,7 @@ object ScalaCheckMacros { trait AutoDerivations { implicit def autoDerivationArbitrary[T]: Arbitrary[T] = - macro ScalaCheckMacros.autoDerivationArbitrary[T] - implicit def autoDerivationCogen[T]: Cogen[T] = macro ScalaCheckMacros.autoDerivationCogen[T] + macro ScalaCheckMacros.autoDerivationArbitraryMacro[T] + implicit def autoDerivationCogen[T]: Cogen[T] = + macro ScalaCheckMacros.autoDerivationCogenMacro[T] } From 8690d6e8e61e692c5e4953bfbd6794934bdd1378 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Thu, 9 Nov 2023 14:45:33 +0100 Subject: [PATCH 17/24] Cross-build cats module on scala3 --- .github/workflows/ci.yml | 2 +- build.sbt | 5 +- .../magnolify/cats}/BandDerivation.scala | 15 +- .../scala-2/magnolify/cats/CatsMacros.scala | 150 ++++++++++++++++++ .../cats}/CommutativeGroupDerivation.scala | 16 +- .../cats}/CommutativeMonoidDerivation.scala | 16 +- .../CommutativeSemigroupDerivation.scala | 17 +- .../magnolify/cats}/EqDerivation.scala | 13 +- .../magnolify/cats}/GroupDerivation.scala | 15 +- .../magnolify/cats}/HashDerivation.scala | 13 +- .../magnolify/cats}/MonoidDerivation.scala | 15 +- .../magnolify/cats}/SemigroupDerivation.scala | 15 +- .../magnolify/cats}/ShowDerivation.scala | 13 +- .../magnolify/cats/BandDerivation.scala | 37 +++++ .../scala-3/magnolify/cats/CatsMacros.scala | 61 +++++++ .../cats/CommutativeGroupDerivation.scala | 45 ++++++ .../cats/CommutativeMonoidDerivation.scala | 41 +++++ .../cats/CommutativeSemigroupDerivation.scala | 37 +++++ .../scala-3/magnolify/cats/EqDerivation.scala | 48 ++++++ .../magnolify/cats/GroupDerivation.scala | 70 ++++++++ .../magnolify/cats/HashDerivation.scala | 53 +++++++ .../magnolify/cats/MonoidDerivation.scala | 82 ++++++++++ .../magnolify/cats/SemigroupDerivation.scala | 81 ++++++++++ .../magnolify/cats/ShowDerivation.scala | 34 ++++ .../scala/magnolify/cats/CatsMacros.scala | 93 ----------- .../scala/magnolify/cats/auto/package.scala | 57 +------ .../magnolify/cats/semiauto/package.scala | 68 ++++++++ .../magnolify/cats/BandDerivationSuite.scala | 25 +-- .../CommutativeGroupDerivationSuite.scala | 26 +-- .../CommutativeMonoidDerivationSuite.scala | 26 +-- .../CommutativeSemigroupDerivationSuite.scala | 26 +-- .../magnolify/cats/EqDerivationSuite.scala | 11 +- .../magnolify/cats/GroupDerivationSuite.scala | 24 +-- .../magnolify/cats/HashDerivationSuite.scala | 13 +- .../cats/MonoidDerivationSuite.scala | 30 ++-- .../scala/magnolify/cats/PrioritySuite.scala | 47 +++--- .../test/scala/magnolify/cats/ScopeTest.scala | 31 ++-- .../cats/SemigroupDerivationSuite.scala | 30 ++-- .../magnolify/cats/ShowDerivationSuite.scala | 35 ++-- .../test/scala/magnolify/cats/TestEq.scala | 53 ++++--- .../scala/magnolify/jmh/MagnolifyBench.scala | 11 +- .../scalacheck/ScalacheckMacros.scala | 1 + 42 files changed, 1114 insertions(+), 387 deletions(-) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/BandDerivation.scala (77%) create mode 100644 cats/src/main/scala-2/magnolify/cats/CatsMacros.scala rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/CommutativeGroupDerivation.scala (80%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/CommutativeMonoidDerivation.scala (77%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/CommutativeSemigroupDerivation.scala (74%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/EqDerivation.scala (80%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/GroupDerivation.scala (87%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/HashDerivation.scala (83%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/MonoidDerivation.scala (89%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/SemigroupDerivation.scala (88%) rename cats/src/main/{scala/magnolify/cats/semiauto => scala-2/magnolify/cats}/ShowDerivation.scala (74%) create mode 100644 cats/src/main/scala-3/magnolify/cats/BandDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/CatsMacros.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/CommutativeGroupDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/CommutativeMonoidDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/CommutativeSemigroupDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/EqDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/GroupDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/HashDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/MonoidDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/SemigroupDerivation.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/ShowDerivation.scala delete mode 100644 cats/src/main/scala/magnolify/cats/CatsMacros.scala create mode 100644 cats/src/main/scala/magnolify/cats/semiauto/package.scala diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0eb1171ed..50d09e80f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,7 +83,7 @@ jobs: - name: Test if: matrix.scala == '3' - run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' shared/test test/test scalacheck/test + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' shared/test test/test scalacheck/test cats/test - name: Check binary compatibility if: '!(matrix.scala == ''3'')' diff --git a/build.sbt b/build.sbt index 35c986bf1..2734c3252 100644 --- a/build.sbt +++ b/build.sbt @@ -111,7 +111,8 @@ val scalaDefault = scala213 val scala3Projects = List( "shared", "test", - "scalacheck" + "scalacheck", + "cats" ) // github actions @@ -391,9 +392,9 @@ lazy val cats = project commonSettings, moduleName := "magnolify-cats", description := "Magnolia add-on for Cats", + crossScalaVersions := Seq(scala3, scala213, scala212), libraryDependencies ++= Seq( "org.typelevel" %% "cats-core" % catsVersion % Provided, - "com.twitter" %% "algebird-core" % algebirdVersion % Test, "org.typelevel" %% "cats-laws" % catsVersion % Test ) ) diff --git a/cats/src/main/scala/magnolify/cats/semiauto/BandDerivation.scala b/cats/src/main/scala-2/magnolify/cats/BandDerivation.scala similarity index 77% rename from cats/src/main/scala/magnolify/cats/semiauto/BandDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/BandDerivation.scala index d46d470c3..d5a9be061 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/BandDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/BandDerivation.scala @@ -14,18 +14,18 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.kernel.Band -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound -import scala.collection.compat._ +import scala.collection.compat.* object BandDerivation { type Typeclass[T] = Band[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[Band, T]): Band[T] = { val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = SemigroupMethods.combineN(caseClass) val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) @@ -39,7 +39,10 @@ object BandDerivation { @implicitNotFound("Cannot derive Band for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable](sealedTrait: SealedTrait[Band, T]): Band[T] = ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Band[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Band[T] = macro Magnolia.gen[T] } diff --git a/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala b/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala new file mode 100644 index 000000000..078bc2da3 --- /dev/null +++ b/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala @@ -0,0 +1,150 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Show +import cats.kernel.* + +import scala.annotation.nowarn +import scala.reflect.macros.* + +private object CatsMacros { + + @nowarn("msg=parameter lp in method genShowMacro is never used") + def genShowMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.ShowDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genEqMacro is never used") + def genEqMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.EqDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genHashMacro is never used") + def genHashMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.HashDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genSemigroupMacro is never used") + def genSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.SemigroupDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genMonoidMacro is never used") + def genMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.MonoidDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genCommutativeSemigroupMacro is never used") + def genCommutativeSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.CommutativeSemigroupDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genCommutativeMonoidMacro is never used") + def genCommutativeMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.CommutativeMonoidDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genGroupMacro is never used") + def genGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.GroupDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genCommutativeGroupMacro is never used") + def genCommutativeGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.CommutativeGroupDerivation.gen[$wtt]""" + } + + @nowarn("msg=parameter lp in method genBandMacro is never used") + def genBandMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + import c.universe.* + val wtt = weakTypeTag[T] + q"""_root_.magnolify.cats.BandDerivation.gen[$wtt]""" + } +} + +// set implicit priority to avoid conflicts +// see: https://typelevel.org/cats/guidelines.html#implicit-instance-priority +// use shapeless.LowPriority so the +// provided cats type classes are always preferred +// triggers derivation as last resort +trait AutoDerivation extends LowPriority0Implicits + +trait LowPriority0Implicits extends LowPriority1Implicits { + implicit def genShow[T](implicit lp: shapeless.LowPriority): Show[T] = + macro CatsMacros.genShowMacro[T] + // CommutativeGroup <: Group | CommutativeMonoid + implicit def genCommutativeGroup[T](implicit lp: shapeless.LowPriority): CommutativeGroup[T] = + macro CatsMacros.genCommutativeGroupMacro[T] + // Hash <: Eq + implicit def genHash[T](implicit lp: shapeless.LowPriority): Hash[T] = + macro CatsMacros.genHashMacro[T] +} + +trait LowPriority1Implicits extends LowPriority2Implicits { + implicit def genEq[T](implicit lp: shapeless.LowPriority): Eq[T] = + macro CatsMacros.genEqMacro[T] + // Group <: Monoid + implicit def genGroup[T](implicit lp: shapeless.LowPriority): Group[T] = + macro CatsMacros.genGroupMacro[T] +} + +trait LowPriority2Implicits extends LowPriority3Implicits { + // CommutativeMonoid <: Monoid | CommutativeSemigroup + implicit def genCommutativeMonoid[T](implicit lp: shapeless.LowPriority): CommutativeMonoid[T] = + macro CatsMacros.genCommutativeMonoidMacro[T] +} + +trait LowPriority3Implicits extends LowPriority4Implicits { + // CommutativeSemigroup <: Semigroup + implicit def genCommutativeSemigroup[T](implicit + lp: shapeless.LowPriority + ): CommutativeSemigroup[T] = + macro CatsMacros.genCommutativeSemigroupMacro[T] + // Monoid <: Semigroup + implicit def genMonoid[T](implicit lp: shapeless.LowPriority): Monoid[T] = + macro CatsMacros.genMonoidMacro[T] +} + +trait LowPriority4Implicits extends LowPriority5Implicits { + // Band <: Semigroup + implicit def genBand[T](implicit lp: shapeless.LowPriority): Band[T] = + macro CatsMacros.genBandMacro[T] +} + +trait LowPriority5Implicits { + implicit def genSemigroup[T](implicit lp: shapeless.LowPriority): Semigroup[T] = + macro CatsMacros.genSemigroupMacro[T] +} diff --git a/cats/src/main/scala/magnolify/cats/semiauto/CommutativeGroupDerivation.scala b/cats/src/main/scala-2/magnolify/cats/CommutativeGroupDerivation.scala similarity index 80% rename from cats/src/main/scala/magnolify/cats/semiauto/CommutativeGroupDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/CommutativeGroupDerivation.scala index 48b467938..e8496a7f3 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/CommutativeGroupDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/CommutativeGroupDerivation.scala @@ -14,18 +14,18 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.kernel.CommutativeGroup -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound -import scala.collection.compat._ +import scala.collection.compat.* object CommutativeGroupDerivation { type Typeclass[T] = CommutativeGroup[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[CommutativeGroup, T]): CommutativeGroup[T] = { val emptyImpl = MonoidMethods.empty(caseClass) val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = GroupMethods.combineN(caseClass) @@ -47,7 +47,11 @@ object CommutativeGroupDerivation { @implicitNotFound("Cannot derive CommutativeGroup for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable](sealedTrait: SealedTrait[CommutativeGroup, T]): CommutativeGroup[T] = + ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: CommutativeGroup[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: CommutativeGroup[T] = macro Magnolia.gen[T] } diff --git a/cats/src/main/scala/magnolify/cats/semiauto/CommutativeMonoidDerivation.scala b/cats/src/main/scala-2/magnolify/cats/CommutativeMonoidDerivation.scala similarity index 77% rename from cats/src/main/scala/magnolify/cats/semiauto/CommutativeMonoidDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/CommutativeMonoidDerivation.scala index d568f26da..9cc0a2bec 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/CommutativeMonoidDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/CommutativeMonoidDerivation.scala @@ -14,18 +14,18 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.kernel.CommutativeMonoid -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound -import scala.collection.compat._ +import scala.collection.compat.* object CommutativeMonoidDerivation { type Typeclass[T] = CommutativeMonoid[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[CommutativeMonoid, T]): CommutativeMonoid[T] = { val emptyImpl = MonoidMethods.empty(caseClass) val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = MonoidMethods.combineN(caseClass) @@ -43,7 +43,11 @@ object CommutativeMonoidDerivation { @implicitNotFound("Cannot derive CommutativeMonoid for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable](sealedTrait: SealedTrait[CommutativeMonoid, T]): CommutativeMonoid[T] = + ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: CommutativeMonoid[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: CommutativeMonoid[T] = macro Magnolia.gen[T] } diff --git a/cats/src/main/scala/magnolify/cats/semiauto/CommutativeSemigroupDerivation.scala b/cats/src/main/scala-2/magnolify/cats/CommutativeSemigroupDerivation.scala similarity index 74% rename from cats/src/main/scala/magnolify/cats/semiauto/CommutativeSemigroupDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/CommutativeSemigroupDerivation.scala index 93fe80e1a..30ea2f69c 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/CommutativeSemigroupDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/CommutativeSemigroupDerivation.scala @@ -14,18 +14,18 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.kernel.CommutativeSemigroup -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound -import scala.collection.compat._ +import scala.collection.compat.* object CommutativeSemigroupDerivation { type Typeclass[T] = CommutativeSemigroup[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[CommutativeSemigroup, T]): CommutativeSemigroup[T] = { val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = SemigroupMethods.combineN(caseClass) val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) @@ -39,7 +39,12 @@ object CommutativeSemigroupDerivation { @implicitNotFound("Cannot derive CommutativeSemigroup for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable]( + sealedTrait: SealedTrait[CommutativeSemigroup, T] + ): CommutativeSemigroup[T] = ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: CommutativeSemigroup[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: CommutativeSemigroup[T] = macro Magnolia.gen[T] } diff --git a/cats/src/main/scala/magnolify/cats/semiauto/EqDerivation.scala b/cats/src/main/scala-2/magnolify/cats/EqDerivation.scala similarity index 80% rename from cats/src/main/scala/magnolify/cats/semiauto/EqDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/EqDerivation.scala index 47624c7fd..7ee505e7f 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/EqDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/EqDerivation.scala @@ -14,21 +14,24 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.Eq -import magnolia1._ +import magnolia1.* object EqDerivation { type Typeclass[T] = Eq[T] - def join[T](caseClass: ReadOnlyCaseClass[Typeclass, T]): Typeclass[T] = + def join[T](caseClass: ReadOnlyCaseClass[Eq, T]): Eq[T] = Eq.instance(EqMethods.join(caseClass)) - def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = + def split[T](sealedTrait: SealedTrait[Eq, T]): Eq[T] = Eq.instance(EqMethods.split(sealedTrait)) - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Eq[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Eq[T] = macro Magnolia.gen[T] } private object EqMethods { diff --git a/cats/src/main/scala/magnolify/cats/semiauto/GroupDerivation.scala b/cats/src/main/scala-2/magnolify/cats/GroupDerivation.scala similarity index 87% rename from cats/src/main/scala/magnolify/cats/semiauto/GroupDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/GroupDerivation.scala index ba0ad094a..136df6001 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/GroupDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/GroupDerivation.scala @@ -14,18 +14,18 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.Group -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound -import scala.collection.compat._ +import scala.collection.compat.* object GroupDerivation { type Typeclass[T] = Group[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[Group, T]): Group[T] = { val emptyImpl = MonoidMethods.empty(caseClass) val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = GroupMethods.combineN(caseClass) @@ -47,9 +47,12 @@ object GroupDerivation { @implicitNotFound("Cannot derive Group for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable](sealedTrait: SealedTrait[Group, T]): Group[T] = ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Group[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Group[T] = macro Magnolia.gen[T] } private object GroupMethods { diff --git a/cats/src/main/scala/magnolify/cats/semiauto/HashDerivation.scala b/cats/src/main/scala-2/magnolify/cats/HashDerivation.scala similarity index 83% rename from cats/src/main/scala/magnolify/cats/semiauto/HashDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/HashDerivation.scala index 001388000..4c4952f44 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/HashDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/HashDerivation.scala @@ -14,10 +14,10 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.Hash -import magnolia1._ +import magnolia1.* import magnolify.shims.MurmurHash3Compat import scala.util.hashing.MurmurHash3 @@ -25,7 +25,7 @@ import scala.util.hashing.MurmurHash3 object HashDerivation { type Typeclass[T] = Hash[T] - def join[T](caseClass: ReadOnlyCaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: ReadOnlyCaseClass[Hash, T]): Hash[T] = { val eqvImpl = EqMethods.join(caseClass) new Hash[T] { @@ -44,7 +44,7 @@ object HashDerivation { } } - def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = { + def split[T](sealedTrait: SealedTrait[Hash, T]): Hash[T] = { val eqvImpl = EqMethods.split(sealedTrait) new Hash[T] { @@ -56,5 +56,8 @@ object HashDerivation { } } - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Hash[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Hash[T] = macro Magnolia.gen[T] } diff --git a/cats/src/main/scala/magnolify/cats/semiauto/MonoidDerivation.scala b/cats/src/main/scala-2/magnolify/cats/MonoidDerivation.scala similarity index 89% rename from cats/src/main/scala/magnolify/cats/semiauto/MonoidDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/MonoidDerivation.scala index 529190d1e..dbc2958ec 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/MonoidDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/MonoidDerivation.scala @@ -14,19 +14,19 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.Monoid -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound +import scala.collection.compat.* import scala.collection.compat.immutable.ArraySeq -import scala.collection.compat._ object MonoidDerivation { type Typeclass[T] = Monoid[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[Monoid, T]): Monoid[T] = { val emptyImpl = MonoidMethods.empty(caseClass) val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = MonoidMethods.combineN(caseClass) @@ -44,9 +44,12 @@ object MonoidDerivation { @implicitNotFound("Cannot derive Monoid for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable](sealedTrait: SealedTrait[Monoid, T]): Monoid[T] = ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Monoid[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Monoid[T] = macro Magnolia.gen[T] } private object MonoidMethods { diff --git a/cats/src/main/scala/magnolify/cats/semiauto/SemigroupDerivation.scala b/cats/src/main/scala-2/magnolify/cats/SemigroupDerivation.scala similarity index 88% rename from cats/src/main/scala/magnolify/cats/semiauto/SemigroupDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/SemigroupDerivation.scala index 92647a3db..2ff4232f5 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/SemigroupDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/SemigroupDerivation.scala @@ -14,19 +14,19 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.Semigroup -import magnolia1._ +import magnolia1.* import scala.annotation.implicitNotFound +import scala.collection.compat.* import scala.collection.compat.immutable.ArraySeq -import scala.collection.compat._ object SemigroupDerivation { type Typeclass[T] = Semigroup[T] - def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = { + def join[T](caseClass: CaseClass[Semigroup, T]): Semigroup[T] = { val combineImpl = SemigroupMethods.combine(caseClass) val combineNImpl = SemigroupMethods.combineN(caseClass) val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) @@ -40,9 +40,12 @@ object SemigroupDerivation { @implicitNotFound("Cannot derive Semigroup for sealed trait") private sealed trait Dispatchable[T] - def split[T: Dispatchable](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = ??? + def split[T: Dispatchable](sealedTrait: SealedTrait[Semigroup, T]): Semigroup[T] = ??? - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Semigroup[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Semigroup[T] = macro Magnolia.gen[T] } private object SemigroupMethods { diff --git a/cats/src/main/scala/magnolify/cats/semiauto/ShowDerivation.scala b/cats/src/main/scala-2/magnolify/cats/ShowDerivation.scala similarity index 74% rename from cats/src/main/scala/magnolify/cats/semiauto/ShowDerivation.scala rename to cats/src/main/scala-2/magnolify/cats/ShowDerivation.scala index b2b4eed91..a85d6c763 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/ShowDerivation.scala +++ b/cats/src/main/scala-2/magnolify/cats/ShowDerivation.scala @@ -14,24 +14,27 @@ * limitations under the License. */ -package magnolify.cats.semiauto +package magnolify.cats import cats.Show -import magnolia1._ +import magnolia1.* object ShowDerivation { type Typeclass[T] = Show[T] - def join[T](caseClass: ReadOnlyCaseClass[Typeclass, T]): Typeclass[T] = new Show[T] { + def join[T](caseClass: ReadOnlyCaseClass[Show, T]): Show[T] = new Show[T] { override def show(x: T): String = caseClass.parameters .map(p => s"${p.label} = ${p.typeclass.show(p.dereference(x))}") .mkString(s"${caseClass.typeName.full} {", ", ", "}") } - def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = new Show[T] { + def split[T](sealedTrait: SealedTrait[Show, T]): Show[T] = new Show[T] { override def show(x: T): String = sealedTrait.split(x)(sub => sub.typeclass.show(sub.cast(x))) } - implicit def apply[T]: Typeclass[T] = macro Magnolia.gen[T] + implicit def gen[T]: Show[T] = macro Magnolia.gen[T] + + @deprecated("Use gen instead", "0.7.0") + def apply[T]: Show[T] = macro Magnolia.gen[T] } diff --git a/cats/src/main/scala-3/magnolify/cats/BandDerivation.scala b/cats/src/main/scala-3/magnolify/cats/BandDerivation.scala new file mode 100644 index 000000000..023c449aa --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/BandDerivation.scala @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.kernel.Band +import magnolia1.* + +import scala.collection.compat.* + +import scala.deriving.Mirror + +object BandDerivation extends ProductDerivation[Band]: + def join[T](caseClass: CaseClass[Band, T]): Band[T] = + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = SemigroupMethods.combineN(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + + new Band[T]: + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + + inline def gen[T](using Mirror.Of[T]): Band[T] = derivedMirror[T] diff --git a/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala b/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala new file mode 100644 index 000000000..ff3cab4b7 --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Show +import cats.kernel.* + +import scala.deriving.Mirror + +// set implicit priority to avoid conflicts +// see: https://typelevel.org/cats/guidelines.html#implicit-instance-priority +// use shapeless.LowPriority so the +// provided cats type classes are always preferred +// triggers derivation as last resort +trait AutoDerivation extends LowPriority0Implicits + +trait LowPriority0Implicits extends LowPriority1Implicits: + inline given genShow[T](using Mirror.Of[T]): Show[T] = ShowDerivation.gen[T] + // CommutativeGroup <: Group | CommutativeMonoid + inline given genCommutativeGroup[T](using Mirror.Of[T]): CommutativeGroup[T] = + CommutativeGroupDerivation.gen[T] + // Hash <: Eq + inline given genHash[T](using Mirror.Of[T]): Hash[T] = HashDerivation.gen[T] + +trait LowPriority1Implicits extends LowPriority2Implicits: + inline given genEq[T](using Mirror.Of[T]): Eq[T] = EqDerivation.gen[T] + // Group <: Monoid + inline given genGroup[T](using Mirror.Of[T]): Group[T] = GroupDerivation.gen[T] + +trait LowPriority2Implicits extends LowPriority3Implicits: + // CommutativeMonoid <: Monoid | CommutativeSemigroup + inline given genCommutativeMonoid[T](using Mirror.Of[T]): CommutativeMonoid[T] = + CommutativeMonoidDerivation.gen[T] + +trait LowPriority3Implicits extends LowPriority4Implicits: + // CommutativeSemigroup <: Semigroup + inline given genCommutativeSemigroup[T](using Mirror.Of[T]): CommutativeSemigroup[T] = + CommutativeSemigroupDerivation.gen[T] + // Monoid <: Semigroup + inline given genMonoid[T](using Mirror.Of[T]): Monoid[T] = MonoidDerivation.gen[T] + +trait LowPriority4Implicits extends LowPriority5Implicits: + // Band <: Semigroup + inline given genBand[T](using Mirror.Of[T]): Band[T] = BandDerivation.gen[T] + +trait LowPriority5Implicits: + inline given genSemigroup[T](using Mirror.Of[T]): Semigroup[T] = SemigroupDerivation.gen[T] diff --git a/cats/src/main/scala-3/magnolify/cats/CommutativeGroupDerivation.scala b/cats/src/main/scala-3/magnolify/cats/CommutativeGroupDerivation.scala new file mode 100644 index 000000000..6bb3552aa --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/CommutativeGroupDerivation.scala @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.kernel.CommutativeGroup +import magnolia1.* + +import scala.deriving.Mirror + +object CommutativeGroupDerivation extends ProductDerivation[CommutativeGroup]: + + def join[T](caseClass: CaseClass[CommutativeGroup, T]): CommutativeGroup[T] = + val emptyImpl = MonoidMethods.empty(caseClass) + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = GroupMethods.combineN(caseClass) + val combineAllImpl = MonoidMethods.combineAll(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + val inverseImpl = GroupMethods.inverse(caseClass) + val removeImpl = GroupMethods.remove(caseClass) + + new CommutativeGroup[T]: + override def empty: T = emptyImpl() + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAll(as: IterableOnce[T]): T = combineAllImpl(as) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + override def inverse(a: T): T = inverseImpl(a) + override def remove(a: T, b: T): T = removeImpl(a, b) + end join + + inline def gen[T](using Mirror.Of[T]): CommutativeGroup[T] = derivedMirror[T] diff --git a/cats/src/main/scala-3/magnolify/cats/CommutativeMonoidDerivation.scala b/cats/src/main/scala-3/magnolify/cats/CommutativeMonoidDerivation.scala new file mode 100644 index 000000000..60512b5ad --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/CommutativeMonoidDerivation.scala @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.kernel.CommutativeMonoid +import magnolia1.* + +import scala.deriving.Mirror + +object CommutativeMonoidDerivation extends ProductDerivation[CommutativeMonoid]: + + def join[T](caseClass: CaseClass[CommutativeMonoid, T]): CommutativeMonoid[T] = + val emptyImpl = MonoidMethods.empty(caseClass) + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = MonoidMethods.combineN(caseClass) + val combineAllImpl = MonoidMethods.combineAll(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + + new CommutativeMonoid[T]: + override def empty: T = emptyImpl() + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAll(as: IterableOnce[T]): T = combineAllImpl(as) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + end join + + inline def gen[T](using Mirror.Of[T]): CommutativeMonoid[T] = derivedMirror[T] diff --git a/cats/src/main/scala-3/magnolify/cats/CommutativeSemigroupDerivation.scala b/cats/src/main/scala-3/magnolify/cats/CommutativeSemigroupDerivation.scala new file mode 100644 index 000000000..a4101f9ec --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/CommutativeSemigroupDerivation.scala @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.kernel.CommutativeSemigroup +import magnolia1.* + +import scala.deriving.Mirror + +object CommutativeSemigroupDerivation extends ProductDerivation[CommutativeSemigroup]: + + def join[T](caseClass: CaseClass[CommutativeSemigroup, T]): CommutativeSemigroup[T] = + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = SemigroupMethods.combineN(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + + new CommutativeSemigroup[T]: + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + end join + + inline def gen[T](using Mirror.Of[T]): CommutativeSemigroup[T] = derivedMirror[T] diff --git a/cats/src/main/scala-3/magnolify/cats/EqDerivation.scala b/cats/src/main/scala-3/magnolify/cats/EqDerivation.scala new file mode 100644 index 000000000..b3381c773 --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/EqDerivation.scala @@ -0,0 +1,48 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Eq +import magnolia1.* + +import scala.deriving.Mirror + +object EqDerivation extends Derivation[Eq]: + + def join[T](caseClass: CaseClass[Eq, T]): Eq[T] = + Eq.instance(EqMethods.join(caseClass)) + + def split[T](sealedTrait: SealedTrait[Eq, T]): Eq[T] = + Eq.instance(EqMethods.split(sealedTrait)) + + inline def gen[T](using Mirror.Of[T]): Eq[T] = derivedMirror[T] +end EqDerivation + +private object EqMethods: + + def join[T, Typeclass[T] <: Eq[T]]( + caseClass: CaseClass[Typeclass, T] + ): (T, T) => Boolean = + (x, y) => caseClass.params.forall(p => p.typeclass.eqv(p.deref(x), p.deref(y))) + + def split[T, Typeclass[T] <: Eq[T]]( + sealedTrait: SealedTrait[Typeclass, T] + ): (T, T) => Boolean = + (x, y) => + sealedTrait.choose(x) { sub => + sub.cast.isDefinedAt(y) && sub.typeclass.eqv(sub.value, sub.cast(y)) + } diff --git a/cats/src/main/scala-3/magnolify/cats/GroupDerivation.scala b/cats/src/main/scala-3/magnolify/cats/GroupDerivation.scala new file mode 100644 index 000000000..c30281397 --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/GroupDerivation.scala @@ -0,0 +1,70 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Group +import magnolia1.* + +import scala.deriving.Mirror + +object GroupDerivation extends ProductDerivation[Group]: + + def join[T](caseClass: CaseClass[Group, T]): Group[T] = + val emptyImpl = MonoidMethods.empty(caseClass) + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = GroupMethods.combineN(caseClass) + val combineAllImpl = MonoidMethods.combineAll(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + val inverseImpl = GroupMethods.inverse(caseClass) + val removeImpl = GroupMethods.remove(caseClass) + + new Group[T]: + override def empty: T = emptyImpl() + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAll(as: IterableOnce[T]): T = combineAllImpl(as) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + override def inverse(a: T): T = inverseImpl(a) + override def remove(a: T, b: T): T = removeImpl(a, b) + end join + + inline def gen[T](using Mirror.Of[T]): Group[T] = derivedMirror[T] +end GroupDerivation + +private object GroupMethods: + def combineN[T, Typeclass[T] <: Group[T]](caseClass: CaseClass[Typeclass, T]): (T, Int) => T = { + val emptyImpl = MonoidMethods.empty(caseClass) + val combineImpl = SemigroupMethods.combine(caseClass) + val f = SemigroupMethods.combineNBase(caseClass) + val inverseImpl = inverse(caseClass) + (a: T, n: Int) => + if (n > 0) { + f(a, n) + } else if (n == 0) { + emptyImpl() + } else if (n == Int.MinValue) { + f(inverseImpl(combineImpl(a, a)), 1073741824) + } else { + f(inverseImpl(a), -n) + } + } + + def inverse[T, Typeclass[T] <: Group[T]](caseClass: CaseClass[Typeclass, T]): T => T = + a => caseClass.construct(p => p.typeclass.inverse(p.deref(a))) + + def remove[T, Typeclass[T] <: Group[T]](caseClass: CaseClass[Typeclass, T]): (T, T) => T = + (a, b) => caseClass.construct(p => p.typeclass.remove(p.deref(a), p.deref(b))) diff --git a/cats/src/main/scala-3/magnolify/cats/HashDerivation.scala b/cats/src/main/scala-3/magnolify/cats/HashDerivation.scala new file mode 100644 index 000000000..9afb31309 --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/HashDerivation.scala @@ -0,0 +1,53 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Hash +import magnolia1.* +import magnolify.shims.MurmurHash3Compat +import scala.util.hashing.MurmurHash3 +import scala.deriving.Mirror + +object HashDerivation extends Derivation[Hash]: + + def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = + val eqvImpl = EqMethods.join(caseClass) + + new Hash[T]: + override def hash(x: T): Int = + if (caseClass.params.isEmpty) { + caseClass.typeInfo.short.hashCode + } else { + val seed = MurmurHash3Compat.seed(caseClass.typeInfo.short.hashCode) + val h = caseClass.params + .map(p => p.typeclass.hash(p.deref(x))) + .foldLeft(seed)(MurmurHash3.mix) + MurmurHash3.finalizeHash(h, caseClass.params.size) + } + + override def eqv(x: T, y: T): Boolean = eqvImpl(x, y) + end join + + def split[T](sealedTrait: SealedTrait[Typeclass, T]): Typeclass[T] = + val eqvImpl = EqMethods.split(sealedTrait) + + new Hash[T]: + override def hash(x: T): Int = sealedTrait.choose(x)(sub => sub.typeclass.hash(sub.value)) + override def eqv(x: T, y: T): Boolean = eqvImpl(x, y) + end split + + inline def gen[T](using Mirror.Of[T]): Hash[T] = derivedMirror[T] diff --git a/cats/src/main/scala-3/magnolify/cats/MonoidDerivation.scala b/cats/src/main/scala-3/magnolify/cats/MonoidDerivation.scala new file mode 100644 index 000000000..203abfbdc --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/MonoidDerivation.scala @@ -0,0 +1,82 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Monoid +import magnolia1.* + +import scala.collection.immutable.ArraySeq.unsafeWrapArray +import scala.deriving.Mirror + +object MonoidDerivation extends ProductDerivation[Monoid]: + + def join[T](caseClass: CaseClass[Monoid, T]): Monoid[T] = + val emptyImpl = MonoidMethods.empty(caseClass) + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = MonoidMethods.combineN(caseClass) + val combineAllImpl = MonoidMethods.combineAll(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + + new Monoid[T]: + override def empty: T = emptyImpl() + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAll(as: IterableOnce[T]): T = combineAllImpl(as) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + end join + + inline def gen[T](using Mirror.Of[T]): Monoid[T] = derivedMirror[T] +end MonoidDerivation + +private object MonoidMethods: + def empty[T, Typeclass[T] <: Monoid[T]](caseClass: CaseClass[Typeclass, T]): () => T = + new Function0[T] with Serializable: + @transient private lazy val value = caseClass.construct(_.typeclass.empty) + override def apply(): T = value + + def combineN[T, Typeclass[T] <: Monoid[T]](caseClass: CaseClass[Typeclass, T]): (T, Int) => T = { + val emptyImpl = empty(caseClass) + val f = SemigroupMethods.combineNBase(caseClass) + (a: T, n: Int) => + if (n < 0) { + throw new IllegalArgumentException("Repeated combining for monoids must have n >= 0") + } else if (n == 0) { + emptyImpl() + } else { + f(a, n) + } + } + + def combineAll[T, Typeclass[T] <: Monoid[T]]( + caseClass: CaseClass[Typeclass, T] + ): IterableOnce[T] => T = { + val combineImpl = SemigroupMethods.combine(caseClass) + val emptyImpl = MonoidMethods.empty(caseClass) + { + case it: Iterable[T] if it.nonEmpty => + // input is re-iterable and non-empty, combineAll on each field + val result = Array.fill[Any](caseClass.params.length)(null) + var i = 0 + while (i < caseClass.params.length) { + val p = caseClass.params(i) + result(i) = p.typeclass.combineAll(it.iterator.map(p.deref)) + i += 1 + } + caseClass.rawConstruct(unsafeWrapArray(result)) + case xs => xs.iterator.foldLeft(emptyImpl())(combineImpl) + } + } diff --git a/cats/src/main/scala-3/magnolify/cats/SemigroupDerivation.scala b/cats/src/main/scala-3/magnolify/cats/SemigroupDerivation.scala new file mode 100644 index 000000000..09bf15a94 --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/SemigroupDerivation.scala @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Semigroup +import magnolia1.* + +import scala.collection.immutable.ArraySeq.unsafeWrapArray +import scala.deriving.Mirror + +object SemigroupDerivation extends ProductDerivation[Semigroup]: + + def join[T](caseClass: CaseClass[Typeclass, T]): Typeclass[T] = + val combineImpl = SemigroupMethods.combine(caseClass) + val combineNImpl = SemigroupMethods.combineN(caseClass) + val combineAllOptionImpl = SemigroupMethods.combineAllOption(caseClass) + + new Semigroup[T]: + override def combine(x: T, y: T): T = combineImpl(x, y) + override def combineN(a: T, n: Int): T = combineNImpl(a, n) + override def combineAllOption(as: IterableOnce[T]): Option[T] = combineAllOptionImpl(as) + end join + + inline def gen[T](using Mirror.Of[T]): Semigroup[T] = derivedMirror[T] +end SemigroupDerivation + +private object SemigroupMethods: + + def combine[T, Typeclass[T] <: Semigroup[T]](caseClass: CaseClass[Typeclass, T]): (T, T) => T = + (x, y) => caseClass.construct(p => p.typeclass.combine(p.deref(x), p.deref(y))) + + def combineNBase[T, Typeclass[T] <: Semigroup[T]]( + caseClass: CaseClass[Typeclass, T] + ): (T, Int) => T = + (a: T, n: Int) => caseClass.construct(p => p.typeclass.combineN(p.deref(a), n)) + + def combineN[T, Typeclass[T] <: Semigroup[T]]( + caseClass: CaseClass[Typeclass, T] + ): (T, Int) => T = { + val f = combineNBase(caseClass) + (a: T, n: Int) => + if (n <= 0) { + throw new IllegalArgumentException("Repeated combining for semigroups must have n > 0") + } else { + f(a, n) + } + } + + def combineAllOption[T, Typeclass[T] <: Semigroup[T]]( + caseClass: CaseClass[Typeclass, T] + ): IterableOnce[T] => Option[T] = { + val combineImpl = combine(caseClass) + { + case it: Iterable[T] if it.nonEmpty => + // input is re-iterable and non-empty, combineAllOption on each field + val result = Array.fill[Any](caseClass.params.length)(null) + var i = 0 + while (i < caseClass.params.length) { + val p = caseClass.params(i) + result(i) = p.typeclass.combineAllOption(it.iterator.map(p.deref)).get + i += 1 + } + Some(caseClass.rawConstruct(unsafeWrapArray(result))) + case xs => + xs.iterator.reduceOption(combineImpl) + } + } diff --git a/cats/src/main/scala-3/magnolify/cats/ShowDerivation.scala b/cats/src/main/scala-3/magnolify/cats/ShowDerivation.scala new file mode 100644 index 000000000..b44074192 --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/ShowDerivation.scala @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Show +import magnolia1.* + +import scala.deriving.Mirror + +object ShowDerivation extends Derivation[Show]: + + def join[T](caseClass: CaseClass[Show, T]): Show[T] = new Show[T]: + override def show(x: T): String = caseClass.params + .map(p => s"${p.label} = ${p.typeclass.show(p.deref(x))}") + .mkString(s"${caseClass.typeInfo.full} {", ", ", "}") + + def split[T](sealedTrait: SealedTrait[Show, T]): Show[T] = new Show[T]: + override def show(x: T): String = sealedTrait.choose(x)(sub => sub.typeclass.show(sub.value)) + + inline def gen[T](using Mirror.Of[T]): Show[T] = derivedMirror[T] diff --git a/cats/src/main/scala/magnolify/cats/CatsMacros.scala b/cats/src/main/scala/magnolify/cats/CatsMacros.scala deleted file mode 100644 index a7afec64b..000000000 --- a/cats/src/main/scala/magnolify/cats/CatsMacros.scala +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2019 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package magnolify.cats - -import scala.reflect.macros._ -import scala.annotation.nowarn - -private object CatsMacros { - - @nowarn("msg=parameter lp in method genShowMacro is never used") - def genShowMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.ShowDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genEqMacro is never used") - def genEqMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.EqDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genHashMacro is never used") - def genHashMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.HashDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genSemigroupMacro is never used") - def genSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.SemigroupDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genMonoidMacro is never used") - def genMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.MonoidDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genCommutativeSemigroupMacro is never used") - def genCommutativeSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.CommutativeSemigroupDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genCommutativeMonoidMacro is never used") - def genCommutativeMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.CommutativeMonoidDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genGroupMacro is never used") - def genGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.GroupDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genCommutativeGroupMacro is never used") - def genCommutativeGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.CommutativeGroupDerivation.apply[$wtt]""" - } - - @nowarn("msg=parameter lp in method genBandMacro is never used") - def genBandMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { - import c.universe._ - val wtt = weakTypeTag[T] - q"""_root_.magnolify.cats.semiauto.BandDerivation.apply[$wtt]""" - } -} diff --git a/cats/src/main/scala/magnolify/cats/auto/package.scala b/cats/src/main/scala/magnolify/cats/auto/package.scala index 904de08dc..34ed249a0 100644 --- a/cats/src/main/scala/magnolify/cats/auto/package.scala +++ b/cats/src/main/scala/magnolify/cats/auto/package.scala @@ -16,59 +16,4 @@ package magnolify.cats -import cats._ -import cats.kernel.{Band, CommutativeGroup, CommutativeMonoid, CommutativeSemigroup} - -// set implicit priority to avoid conflicts -// see: https://typelevel.org/cats/guidelines.html#implicit-instance-priority -// use shapeless.LowPriority so the -// provided cats type classes are always preferred -// triggers derivation as last resort -package object auto extends LowPriority0Implicits - -trait LowPriority0Implicits extends LowPriority2Implicits { - implicit def genShow[T](implicit lp: shapeless.LowPriority): Show[T] = - macro CatsMacros.genShowMacro[T] - // CommutativeGroup <: Group | CommutativeMonoid - implicit def genCommutativeGroup[T](implicit lp: shapeless.LowPriority): CommutativeGroup[T] = - macro CatsMacros.genCommutativeGroupMacro[T] - // Hash <: Eq - implicit def genHash[T](implicit lp: shapeless.LowPriority): Hash[T] = - macro CatsMacros.genHashMacro[T] -} - -trait LowPriority2Implicits extends LowPriority3Implicits { - implicit def genEq[T](implicit lp: shapeless.LowPriority): Eq[T] = - macro CatsMacros.genEqMacro[T] - // Group <: Monoid - implicit def genGroup[T](implicit lp: shapeless.LowPriority): Group[T] = - macro CatsMacros.genGroupMacro[T] -} - -trait LowPriority3Implicits extends LowPriority4Implicits { - // CommutativeMonoid <: Monoid | CommutativeSemigroup - implicit def genCommutativeMonoid[T](implicit lp: shapeless.LowPriority): CommutativeMonoid[T] = - macro CatsMacros.genCommutativeMonoidMacro[T] -} - -trait LowPriority4Implicits extends LowPriority5Implicits { - // CommutativeSemigroup <: Semigroup - implicit def genCommutativeSemigroup[T](implicit - lp: shapeless.LowPriority - ): CommutativeSemigroup[T] = - macro CatsMacros.genCommutativeSemigroupMacro[T] - // Monoid <: Semigroup - implicit def genMonoid[T](implicit lp: shapeless.LowPriority): Monoid[T] = - macro CatsMacros.genMonoidMacro[T] -} - -trait LowPriority5Implicits extends LowPriority6Implicits { - // Band <: Semigroup - implicit def genBand[T](implicit lp: shapeless.LowPriority): Band[T] = - macro CatsMacros.genBandMacro[T] -} - -trait LowPriority6Implicits { - implicit def genSemigroup[T](implicit lp: shapeless.LowPriority): Semigroup[T] = - macro CatsMacros.genSemigroupMacro[T] -} +package object auto extends AutoDerivation diff --git a/cats/src/main/scala/magnolify/cats/semiauto/package.scala b/cats/src/main/scala/magnolify/cats/semiauto/package.scala new file mode 100644 index 000000000..888f346d0 --- /dev/null +++ b/cats/src/main/scala/magnolify/cats/semiauto/package.scala @@ -0,0 +1,68 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Show +import cats.kernel.* + +package object semiauto { + + @deprecated("Use Band.gen[T] instead", "0.7.0") + val BandDerivation = magnolify.cats.BandDerivation + @deprecated("Use CommutativeGroup.gen[T] instead", "0.7.0") + val CommutativeGroupDerivation = magnolify.cats.CommutativeGroupDerivation + @deprecated("Use CommutativeMonoid.gen[T] instead", "0.7.0") + val CommutativeMonoidDerivation = magnolify.cats.CommutativeMonoidDerivation + @deprecated("Use CommutativeSemigroup.gen[T] instead", "0.7.0") + val CommutativeSemigroupDerivation = magnolify.cats.CommutativeSemigroupDerivation + @deprecated("Use Eq.gen[T] instead", "0.7.0") + val EqDerivation = magnolify.cats.EqDerivation + @deprecated("Use Group.gen[T] instead", "0.7.0") + val GroupDerivation = magnolify.cats.GroupDerivation + @deprecated("Use Hash.gen[T] instead", "0.7.0") + val HashDerivation = magnolify.cats.HashDerivation + @deprecated("Use Semigroup.gen[T] instead", "0.7.0") + val SemigroupDerivation = magnolify.cats.SemigroupDerivation + @deprecated("Use Show.gen[T] instead", "0.7.0") + val ShowDerivation = magnolify.cats.ShowDerivation + implicit def genBand(b: Band.type): magnolify.cats.BandDerivation.type = + magnolify.cats.BandDerivation + implicit def genCommutativeGroup( + cg: CommutativeGroup.type + ): magnolify.cats.CommutativeGroupDerivation.type = + magnolify.cats.CommutativeGroupDerivation + implicit def genCommutativeMonoid( + cm: CommutativeMonoid.type + ): magnolify.cats.CommutativeMonoidDerivation.type = + magnolify.cats.CommutativeMonoidDerivation + implicit def genCommutativeSemigroup( + cm: CommutativeSemigroup.type + ): magnolify.cats.CommutativeSemigroupDerivation.type = + magnolify.cats.CommutativeSemigroupDerivation + implicit def genEq(eq: Eq.type): magnolify.cats.EqDerivation.type = + magnolify.cats.EqDerivation + implicit def genGroup(g: Group.type): magnolify.cats.GroupDerivation.type = + magnolify.cats.GroupDerivation + implicit def genHash(h: Hash.type): magnolify.cats.HashDerivation.type = + magnolify.cats.HashDerivation + implicit def genMonoid(m: Monoid.type): magnolify.cats.MonoidDerivation.type = + magnolify.cats.MonoidDerivation + implicit def genSemigroup(sg: Semigroup.type): magnolify.cats.SemigroupDerivation.type = + magnolify.cats.SemigroupDerivation + implicit def genShow(sg: Show.type): magnolify.cats.ShowDerivation.type = + magnolify.cats.ShowDerivation +} diff --git a/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala index ba7b7a7e6..b3dce2a59 100644 --- a/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala @@ -16,28 +16,29 @@ package magnolify.cats -import cats._ +import cats.* import cats.kernel.Band -import cats.kernel.laws.discipline._ +import cats.kernel.laws.discipline.* import magnolify.cats.Types.MiniSet -import magnolify.cats.auto.genBand -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.semiauto.* +import magnolify.test.* +import org.scalacheck.* -import scala.reflect._ +import scala.reflect.* -class BandDerivationSuite extends MagnolifySuite { - import BandDerivationSuite._ +class BandDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + import BandDerivationSuite.* + import magnolify.cats.auto.genBand private def test[T: Arbitrary: ClassTag: Eq: Band]: Unit = { - val band = ensureSerializable(implicitly[Band[T]]) + // TODO val band = ensureSerializable(implicitly[Band[T]]) + val band = Band[T] include(BandTests[T](band).band.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val bMiniSet: Band[MiniSet] = Band.instance((x, y) => MiniSet(x.s ++ y.s)) + test[Record] } diff --git a/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala index 157f70c0b..eab8ad3f0 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala @@ -16,27 +16,29 @@ package magnolify.cats -import cats._ +import cats.* import cats.kernel.CommutativeGroup -import cats.kernel.laws.discipline._ +import cats.kernel.laws.discipline.* import magnolify.cats.Types.MiniInt -import magnolify.cats.auto.genCommutativeGroup -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.semiauto.* +import magnolify.test.* +import org.scalacheck.* -import scala.reflect._ +import scala.reflect.* -class CommutativeGroupDerivationSuite extends MagnolifySuite { - import CommutativeGroupDerivationSuite._ +class CommutativeGroupDerivationSuite + extends MagnolifySuite + with magnolify.scalacheck.AutoDerivations { + import CommutativeGroupDerivationSuite.* + import magnolify.cats.auto.genCommutativeGroup private def test[T: Arbitrary: ClassTag: Eq: CommutativeGroup]: Unit = { - val cg = ensureSerializable(implicitly[CommutativeGroup[T]]) + // TODO val cg = ensureSerializable(implicitly[CommutativeGroup[T]]) + val cg = CommutativeGroup[T] include(CommutativeGroupTests[T](cg).commutativeGroup.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val cgMiniInt: CommutativeGroup[MiniInt] = new CommutativeGroup[MiniInt] { override def empty: MiniInt = MiniInt(0) override def combine(x: MiniInt, y: MiniInt): MiniInt = MiniInt(x.i + y.i) diff --git a/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala index b2a1a9d16..ed38f8463 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala @@ -16,27 +16,29 @@ package magnolify.cats -import cats._ +import cats.* import cats.kernel.CommutativeMonoid -import cats.kernel.laws.discipline._ +import cats.kernel.laws.discipline.* import magnolify.cats.Types.MiniInt -import magnolify.cats.auto.genCommutativeMonoid -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.semiauto.* +import magnolify.test.* +import org.scalacheck.* -import scala.reflect._ +import scala.reflect.* -class CommutativeMonoidDerivationSuite extends MagnolifySuite { - import CommutativeMonoidDerivationSuite._ +class CommutativeMonoidDerivationSuite + extends MagnolifySuite + with magnolify.scalacheck.AutoDerivations { + import CommutativeMonoidDerivationSuite.* + import magnolify.cats.auto.genCommutativeMonoid private def test[T: Arbitrary: ClassTag: Eq: CommutativeMonoid]: Unit = { - val cm = ensureSerializable(implicitly[CommutativeMonoid[T]]) + // TODO val cm = ensureSerializable(implicitly[CommutativeMonoid[T]]) + val cm = CommutativeMonoid[T] include(CommutativeMonoidTests[T](cm).commutativeMonoid.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val cmMiniInt: CommutativeMonoid[MiniInt] = CommutativeMonoid.instance(MiniInt(0), (x, y) => MiniInt(x.i + y.i)) diff --git a/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala index a256874cc..d72910b17 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala @@ -16,27 +16,29 @@ package magnolify.cats -import cats._ +import cats.* import cats.kernel.CommutativeSemigroup -import cats.kernel.laws.discipline._ +import cats.kernel.laws.discipline.* import magnolify.cats.Types.MiniInt -import magnolify.cats.auto.genCommutativeSemigroup -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.semiauto.* +import magnolify.test.* +import org.scalacheck.* -import scala.reflect._ +import scala.reflect.* -class CommutativeSemigroupDerivationSuite extends MagnolifySuite { - import CommutativeSemigroupDerivationSuite._ +class CommutativeSemigroupDerivationSuite + extends MagnolifySuite + with magnolify.scalacheck.AutoDerivations { + import CommutativeSemigroupDerivationSuite.* + import magnolify.cats.auto.genCommutativeSemigroup private def test[T: Arbitrary: ClassTag: Eq: CommutativeSemigroup]: Unit = { - val csg = ensureSerializable(implicitly[CommutativeSemigroup[T]]) + // TODO val csg = ensureSerializable(implicitly[CommutativeSemigroup[T]]) + val csg = CommutativeSemigroup[T] include(CommutativeSemigroupTests[T](csg).commutativeSemigroup.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val csgMiniInt: CommutativeSemigroup[MiniInt] = CommutativeSemigroup.instance((x, y) => MiniInt(x.i + y.i)) test[Record] diff --git a/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala index 519437e12..282e56dd8 100644 --- a/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala @@ -32,9 +32,10 @@ import org.scalacheck._ import scala.reflect._ -class EqDerivationSuite extends MagnolifySuite { +class EqDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { private def test[T: Arbitrary: ClassTag: Cogen: Eq]: Unit = { - val eq = ensureSerializable(implicitly[Eq[T]]) + // TODO val eq = ensureSerializable(implicitly[Eq[T]]) + val eq = Eq[T] include(EqTests[T](eq).eqv.all, className[T] + ".") } @@ -46,8 +47,14 @@ class EqDerivationSuite extends MagnolifySuite { test[Collections] test[Custom] + // magnolia scala3 limitation: + // For a recursive structures it is required to assign the derived value to an implicit variable + // TODO use different implicit names in auto/semiauto to avoid shadowing + implicit val eqNode: Eq[Node] = magnolify.cats.EqDerivation.gen + implicit val eqGNode: Eq[GNode[Int]] = magnolify.cats.EqDerivation.gen test[Node] test[GNode[Int]] + test[Shape] test[Color] } diff --git a/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala index d1d7fae08..865ff50ff 100644 --- a/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala @@ -16,26 +16,26 @@ package magnolify.cats -import cats._ -import cats.kernel.laws.discipline._ +import cats.* +import cats.kernel.laws.discipline.* import magnolify.cats.Types.MiniInt -import magnolify.cats.auto.genGroup -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.semiauto.* +import magnolify.test.* +import org.scalacheck.* -import scala.reflect._ +import scala.reflect.* -class GroupDerivationSuite extends MagnolifySuite { - import GroupDerivationSuite._ +class GroupDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + import GroupDerivationSuite.* + import magnolify.cats.auto.genGroup private def test[T: Arbitrary: ClassTag: Eq: Group]: Unit = { - val grp = ensureSerializable(implicitly[Group[T]]) + // TODO val grp = ensureSerializable(implicitly[Group[T]]) + val grp = Group[T] include(GroupTests[T](grp).group.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val gMiniInt: Group[MiniInt] = new Group[MiniInt] { override def empty: MiniInt = MiniInt(0) diff --git a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala index a3927ad00..0de75ed12 100644 --- a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala @@ -18,7 +18,6 @@ package magnolify.cats import cats._ import cats.kernel.laws.discipline._ -import magnolify.cats.auto.genHash import magnolify.test.ADT._ import magnolify.test.Simple._ import magnolify.test._ @@ -32,10 +31,12 @@ import cats.Eq._ import magnolify.scalacheck.TestArbitrary._ import magnolify.scalacheck.TestCogen._ -class HashDerivationSuite extends MagnolifySuite { +class HashDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + import magnolify.cats.auto.genHash private def test[T: Arbitrary: ClassTag: Cogen: Hash](exclusions: String*): Unit = { - val hash = ensureSerializable(implicitly[Hash[T]]) + // TODO val hash = ensureSerializable(implicitly[Hash[T]]) + val hash = Hash[T] val props = HashTests[T](hash).hash.props.filter(kv => !exclusions.contains(kv._1)) for ((n, p) <- props) { property(s"${className[T]}.$n")(p) @@ -56,8 +57,14 @@ class HashDerivationSuite extends MagnolifySuite { test[Collections]() test[Custom]() + // magnolia scala3 limitation: + // For a recursive structures it is required to assign the derived value to an implicit variable + // TODO use different implicit names in auto/semiauto to avoid shadowing + implicit val hashNode: Hash[Node] = magnolify.cats.HashDerivation.gen + implicit val hashGNode: Hash[GNode[Int]] = magnolify.cats.HashDerivation.gen test[Node]() test[GNode[Int]]() + test[Shape]() test[Color]() } diff --git a/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala index ed1f2bea8..b7a7616d8 100644 --- a/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala @@ -16,31 +16,31 @@ package magnolify.cats -import cats._ -import cats.kernel.laws.discipline._ -import magnolify.cats.auto.genMonoid -import magnolify.cats.TestEq._ +import cats.* +import cats.kernel.laws.discipline.* +import magnolify.cats.TestEq.* import magnolify.cats.Types.MiniInt -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.scalacheck.TestArbitrary._ -import magnolify.test.Simple._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.semiauto.* +import magnolify.scalacheck.TestArbitrary.* +import magnolify.test.* +import magnolify.test.Simple.* +import org.scalacheck.* import java.net.URI import java.time.Duration -import scala.reflect._ +import scala.reflect.* -class MonoidDerivationSuite extends MagnolifySuite { - import MonoidDerivationSuite._ +class MonoidDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + import MonoidDerivationSuite.* + import magnolify.cats.auto.genMonoid private def test[T: Arbitrary: ClassTag: Eq: Monoid]: Unit = { - val mon = ensureSerializable(implicitly[Monoid[T]]) + // TODO val mon = ensureSerializable(implicitly[Monoid[T]]) + val mon = Monoid[T] include(MonoidTests[T](mon).monoid.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val mBool: Monoid[Boolean] = Monoid.instance(false, _ || _) implicit val mUri: Monoid[URI] = Monoid.instance(URI.create(""), (x, y) => URI.create(x.toString + y.toString)) diff --git a/cats/src/test/scala/magnolify/cats/PrioritySuite.scala b/cats/src/test/scala/magnolify/cats/PrioritySuite.scala index a13ff7ca3..7dce4cd8d 100644 --- a/cats/src/test/scala/magnolify/cats/PrioritySuite.scala +++ b/cats/src/test/scala/magnolify/cats/PrioritySuite.scala @@ -16,32 +16,26 @@ package magnolify.cats -import cats._ -import com.twitter.algebird.{Semigroup => _, _} -import magnolify.cats.auto._ +import cats.* import magnolify.shims.MurmurHash3Compat -import magnolify.test.Simple._ -import magnolify.test._ +import magnolify.test.* +import magnolify.test.Simple.* import scala.reflect.ClassTag import scala.util.hashing.MurmurHash3 -class PrioritySuite extends MagnolifySuite { - private def test[T: ClassTag](x: T, y: T, expected: T)(implicit sg: Semigroup[T]): Unit = - test(s"Semigroup.${className[T]}") { - assertEquals(sg.combine(x, y), expected) - } +class PrioritySuite extends MagnolifySuite with magnolify.cats.AutoDerivation { private def test[T: ClassTag: Hash: Show]: Unit = test(s"Priority.${className[T]}") { - ensureSerializable(implicitly[Eq[T]]) - ensureSerializable(implicitly[Hash[T]]) - ensureSerializable(implicitly[Show[T]]) +// ensureSerializable(implicitly[Eq[T]]) +// ensureSerializable(implicitly[Hash[T]]) +// ensureSerializable(implicitly[Show[T]]) + Eq[T] + Hash[T] + Show[T] } - test(Min(0), Min(1), Min(0)) - test(Max(0), Max(1), Max(1)) - test[Integers] test[Floats] test[Numbers] @@ -51,18 +45,25 @@ class PrioritySuite extends MagnolifySuite { test[Nested] { - implicit def hashIterable[T, C[_]](implicit ht: Hash[T], tt: C[T] => Iterable[T]): Hash[C[T]] = + implicit def hashIterable[T, C[_]](implicit ht: Hash[T], ti: C[T] => Iterable[T]): Hash[C[T]] = new Hash[C[T]] { override def hash(x: C[T]): Int = { val seed = MurmurHash3Compat.seed(x.getClass.hashCode()) - val h = x.foldLeft(seed)((h, p) => MurmurHash3.mix(h, ht.hash(p))) - MurmurHash3.finalizeHash(h, x.size) + val xs = ti(x) + val hash = xs.foldLeft(seed)((h, p) => MurmurHash3.mix(h, ht.hash(p))) + MurmurHash3.finalizeHash(hash, xs.size) + } + + override def eqv(x: C[T], y: C[T]): Boolean = { + val xs = ti(x) + val ys = ti(y) + xs.size == ys.size && (xs.iterator zip ys.iterator).forall((ht.eqv _).tupled) } - override def eqv(x: C[T], y: C[T]): Boolean = - x.size == y.size && (x.iterator zip y.iterator).forall((ht.eqv _).tupled) } - implicit def showIterable[T, C[_]](implicit st: Show[T], tt: C[T] => Iterable[T]): Show[C[T]] = - Show.show(_.map(st.show).mkString("[", ",", "]")) + + implicit def showIterable[T, C[_]](implicit st: Show[T], ti: C[T] => Iterable[T]): Show[C[T]] = + Show.show(x => ti(x).map(st.show).mkString("[", ",", "]")) + test[Collections] test[MoreCollections] } diff --git a/cats/src/test/scala/magnolify/cats/ScopeTest.scala b/cats/src/test/scala/magnolify/cats/ScopeTest.scala index 664c745e6..2b5181ba1 100644 --- a/cats/src/test/scala/magnolify/cats/ScopeTest.scala +++ b/cats/src/test/scala/magnolify/cats/ScopeTest.scala @@ -16,10 +16,9 @@ package magnolify.cats -import cats._ -import cats.kernel.{Band, CommutativeGroup, CommutativeMonoid, CommutativeSemigroup} -import magnolify.test.Simple._ -import magnolify.cats.semiauto._ +import cats.Show +import cats.kernel.* +import magnolify.test.Simple.* import munit.FunSuite import scala.reflect.{classTag, ClassTag} @@ -27,8 +26,7 @@ import scala.reflect.{classTag, ClassTag} object ScopeTest { case class Sets(s: Set[Int]) - object Auto { - import magnolify.cats.auto._ + object Auto extends magnolify.cats.AutoDerivation { val s: Show[Numbers] = implicitly val eq: Eq[Numbers] = implicitly val hash: Hash[Numbers] = implicitly @@ -42,16 +40,17 @@ object ScopeTest { } object Semi { - EqDerivation[Numbers] - HashDerivation[Numbers] - SemigroupDerivation[Numbers] - CommutativeSemigroupDerivation[Numbers] - BandDerivation[Sets] - MonoidDerivation[Numbers] - CommutativeMonoidDerivation[Numbers] - GroupDerivation[Numbers] - CommutativeGroupDerivation[Numbers] - ShowDerivation[Numbers] + import magnolify.cats.semiauto.* + Eq.gen[Numbers] + Hash.gen[Numbers] + Semigroup.gen[Numbers] + CommutativeSemigroup.gen[Numbers] + Band.gen[Sets] + Monoid.gen[Numbers] + CommutativeMonoid.gen[Numbers] + Group.gen[Numbers] + CommutativeGroup.gen[Numbers] + Show.gen[Numbers] } } diff --git a/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala index de4813a4e..789c29686 100644 --- a/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala @@ -16,31 +16,31 @@ package magnolify.cats -import cats._ -import cats.kernel.laws.discipline._ -import magnolify.cats.auto.genSemigroup -import magnolify.cats.TestEq._ +import cats.* +import cats.kernel.laws.discipline.* +import magnolify.cats.semiauto.* +import magnolify.cats.TestEq.* import magnolify.cats.Types.MiniInt -import magnolify.cats.semiauto.EqDerivation -import magnolify.scalacheck.auto._ -import magnolify.scalacheck.TestArbitrary._ -import magnolify.test.Simple._ -import magnolify.test._ -import org.scalacheck._ +import magnolify.cats.auto.genSemigroup +import magnolify.scalacheck.TestArbitrary.* +import magnolify.test.* +import magnolify.test.Simple.* +import org.scalacheck.* import java.net.URI import java.time.Duration -import scala.reflect._ +import scala.reflect.* -class SemigroupDerivationSuite extends MagnolifySuite { - import SemigroupDerivationSuite._ +class SemigroupDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + import SemigroupDerivationSuite.* private def test[T: Arbitrary: ClassTag: Eq: Semigroup]: Unit = { - val sg = ensureSerializable(implicitly[Semigroup[T]]) + // TODO val sg = ensureSerializable(implicitly[Semigroup[T]]) + val sg = Semigroup[T] include(SemigroupTests[T](sg).semigroup.all, className[T] + ".") } - implicit val eqRecord: Eq[Record] = EqDerivation[Record] + implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val sgBool: Semigroup[Boolean] = Semigroup.instance(_ ^ _) implicit val sgUri: Semigroup[URI] = Semigroup.instance((x, y) => URI.create(x.toString + y.toString)) diff --git a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala index 07fb32dd7..70715e535 100644 --- a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala @@ -16,25 +16,26 @@ package magnolify.cats -import cats._ -import cats.laws.discipline.ContravariantTests -import cats.laws.discipline.MiniInt -import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq._ -import magnolify.cats.auto.genShow -import magnolify.scalacheck.TestArbitrary._ -import magnolify.test.ADT._ -import magnolify.test.Simple._ -import magnolify.test._ -import org.scalacheck._ +import cats.Show +import cats.laws.discipline.{ContravariantTests, MiniInt} +import cats.laws.discipline.arbitrary.* +import cats.laws.discipline.eq.* +import magnolify.scalacheck.TestArbitrary.* +import magnolify.test.* +import magnolify.test.ADT.* +import magnolify.test.Simple.* +import org.scalacheck.* import java.net.URI import java.time.Duration -import scala.reflect._ +import scala.reflect.* + +class ShowDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { + import magnolify.cats.auto.genShow -class ShowDerivationSuite extends MagnolifySuite { private def test[T: Arbitrary: ClassTag: Show]: Unit = { - val show = ensureSerializable(implicitly[Show[T]]) + // val show = ensureSerializable(implicitly[Show[T]]) + val show = Show[T] val name = className[T] include(ContravariantTests[Show].contravariant[MiniInt, Int, Boolean].all, s"$name.") @@ -59,8 +60,14 @@ class ShowDerivationSuite extends MagnolifySuite { test[Collections] test[Custom] + // magnolia scala3 limitation: + // For a recursive structures it is required to assign the derived value to an implicit variable + // TODO use different implicit names in auto/semiauto to avoid shadowing + implicit val showNode: Show[Node] = magnolify.cats.ShowDerivation.gen + implicit val showGNode: Show[GNode[Int]] = magnolify.cats.ShowDerivation.gen test[Node] test[GNode[Int]] + test[Shape] test[Color] } diff --git a/cats/src/test/scala/magnolify/cats/TestEq.scala b/cats/src/test/scala/magnolify/cats/TestEq.scala index 152cccbd8..47dbbda30 100644 --- a/cats/src/test/scala/magnolify/cats/TestEq.scala +++ b/cats/src/test/scala/magnolify/cats/TestEq.scala @@ -17,7 +17,7 @@ package magnolify.cats import cats.Eq -import magnolify.cats.semiauto.EqDerivation +import magnolify.cats.semiauto.* import magnolify.shared.UnsafeEnum import magnolify.test.ADT._ import magnolify.test.JavaEnums @@ -40,11 +40,14 @@ object TestEq { // java implicit lazy val eqCharSequence: Eq[CharSequence] = Eq.by(_.toString) - implicit def eqCharSeqMap[T: Eq]: Eq[Map[CharSequence, T]] = Eq.by { m => - // Map[CharSequence, T] should not be used for lookups as key equality is not guarantee - // Can only be used as a key value list - m.map { case (k, v) => k.toString -> v } - } + + // Map[CharSequence, T] should not be used for lookups as key equality is not guarantee + // Can only be used as a key value list + implicit def eqCharSeqMap[T: Eq]: Eq[Map[CharSequence, T]] = + Eq.by[Map[CharSequence, T], Map[String, T]]( + _.map { case (k, v) => k.toString -> v } + )(Eq.catsKernelEqForMap[String, T]) + implicit val eqByteBuffer: Eq[ByteBuffer] = Eq.by(_.array()) // java-time @@ -71,26 +74,26 @@ object TestEq { } // ADT - implicit lazy val eqNode: Eq[Node] = EqDerivation[Node] - implicit lazy val eqGNode: Eq[GNode[Int]] = EqDerivation[GNode[Int]] - implicit lazy val eqShape: Eq[Shape] = EqDerivation[Shape] - implicit lazy val eqColor: Eq[Color] = EqDerivation[Color] - implicit lazy val eqPerson: Eq[Person] = EqDerivation[Person] + implicit lazy val eqNode: Eq[Node] = Eq.gen[Node] + implicit lazy val eqGNode: Eq[GNode[Int]] = Eq.gen[GNode[Int]] + implicit lazy val eqShape: Eq[Shape] = Eq.gen[Shape] + implicit lazy val eqColor: Eq[Color] = Eq.gen[Color] + implicit lazy val eqPerson: Eq[Person] = Eq.gen[Person] // simple - implicit lazy val eqIntegers: Eq[Integers] = EqDerivation[Integers] - implicit lazy val eqFloats: Eq[Floats] = EqDerivation[Floats] - implicit lazy val eqNumbers: Eq[Numbers] = EqDerivation[Numbers] - implicit lazy val eqRequired: Eq[Required] = EqDerivation[Required] - implicit lazy val eqNullable: Eq[Nullable] = EqDerivation[Nullable] - implicit lazy val eqRepeated: Eq[Repeated] = EqDerivation[Repeated] - implicit lazy val eqNested: Eq[Nested] = EqDerivation[Nested] - implicit lazy val eqCollections: Eq[Collections] = EqDerivation[Collections] - implicit lazy val eqMoreCollections: Eq[MoreCollections] = EqDerivation[MoreCollections] - implicit lazy val eqEnums: Eq[Enums] = EqDerivation[Enums] - implicit lazy val eqUnsafeEnums: Eq[UnsafeEnums] = EqDerivation[UnsafeEnums] - implicit lazy val eqCustom: Eq[Custom] = EqDerivation[Custom] - implicit lazy val eqLowerCamel: Eq[LowerCamel] = EqDerivation[LowerCamel] - implicit lazy val eqLowerCamelInner: Eq[LowerCamelInner] = EqDerivation[LowerCamelInner] + implicit lazy val eqIntegers: Eq[Integers] = Eq.gen[Integers] + implicit lazy val eqFloats: Eq[Floats] = Eq.gen[Floats] + implicit lazy val eqNumbers: Eq[Numbers] = Eq.gen[Numbers] + implicit lazy val eqRequired: Eq[Required] = Eq.gen[Required] + implicit lazy val eqNullable: Eq[Nullable] = Eq.gen[Nullable] + implicit lazy val eqRepeated: Eq[Repeated] = Eq.gen[Repeated] + implicit lazy val eqNested: Eq[Nested] = Eq.gen[Nested] + implicit lazy val eqCollections: Eq[Collections] = Eq.gen[Collections] + implicit lazy val eqMoreCollections: Eq[MoreCollections] = Eq.gen[MoreCollections] + implicit lazy val eqEnums: Eq[Enums] = Eq.gen[Enums] + implicit lazy val eqUnsafeEnums: Eq[UnsafeEnums] = Eq.gen[UnsafeEnums] + implicit lazy val eqCustom: Eq[Custom] = Eq.gen[Custom] + implicit lazy val eqLowerCamel: Eq[LowerCamel] = Eq.gen[LowerCamel] + implicit lazy val eqLowerCamelInner: Eq[LowerCamelInner] = Eq.gen[LowerCamelInner] } diff --git a/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala b/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala index ccf745160..119e1d3fc 100644 --- a/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala +++ b/jmh/src/test/scala/magnolify/jmh/MagnolifyBench.scala @@ -16,12 +16,13 @@ package magnolify.jmh -import java.util.concurrent.TimeUnit +import magnolify.cats.{EqDerivation, GroupDerivation, HashDerivation, MonoidDerivation, SemigroupDerivation} -import magnolify.scalacheck.auto._ -import magnolify.test.Simple._ -import org.scalacheck._ -import org.openjdk.jmh.annotations._ +import java.util.concurrent.TimeUnit +import magnolify.scalacheck.auto.* +import magnolify.test.Simple.* +import org.scalacheck.* +import org.openjdk.jmh.annotations.* object MagnolifyBench { val seed: rng.Seed = rng.Seed(0) diff --git a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala index 265c4a3f0..6ec11866d 100644 --- a/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala +++ b/scalacheck/src/main/scala-2/magnolify/scalacheck/ScalacheckMacros.scala @@ -19,6 +19,7 @@ package magnolify.scalacheck import org.scalacheck.{Arbitrary, Cogen} import scala.reflect.macros.* + object ScalaCheckMacros { def autoDerivationArbitraryMacro[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = { import c.universe._ From 8316827cba3f849cca384c9a6ee73746e975ee65 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Mon, 13 Nov 2023 15:25:46 +0100 Subject: [PATCH 18/24] Prefer explicit imports instead of trait mixin --- .../magnolify/cats/BandDerivationSuite.scala | 3 +- .../CommutativeGroupDerivationSuite.scala | 5 ++- .../CommutativeMonoidDerivationSuite.scala | 5 ++- .../CommutativeSemigroupDerivationSuite.scala | 5 ++- .../magnolify/cats/EqDerivationSuite.scala | 35 ++++++++++--------- .../magnolify/cats/GroupDerivationSuite.scala | 3 +- .../magnolify/cats/HashDerivationSuite.scala | 23 ++++++------ .../cats/MonoidDerivationSuite.scala | 8 +++-- .../cats/SemigroupDerivationSuite.scala | 11 +++--- .../magnolify/cats/ShowDerivationSuite.scala | 5 +-- 10 files changed, 53 insertions(+), 50 deletions(-) diff --git a/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala index b3dce2a59..bad6d1a4e 100644 --- a/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala @@ -26,8 +26,9 @@ import org.scalacheck.* import scala.reflect.* -class BandDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class BandDerivationSuite extends MagnolifySuite { import BandDerivationSuite.* + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genBand private def test[T: Arbitrary: ClassTag: Eq: Band]: Unit = { diff --git a/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala index eab8ad3f0..1e556311e 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala @@ -26,10 +26,9 @@ import org.scalacheck.* import scala.reflect.* -class CommutativeGroupDerivationSuite - extends MagnolifySuite - with magnolify.scalacheck.AutoDerivations { +class CommutativeGroupDerivationSuite extends MagnolifySuite { import CommutativeGroupDerivationSuite.* + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genCommutativeGroup private def test[T: Arbitrary: ClassTag: Eq: CommutativeGroup]: Unit = { diff --git a/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala index ed38f8463..064f5b094 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala @@ -26,10 +26,9 @@ import org.scalacheck.* import scala.reflect.* -class CommutativeMonoidDerivationSuite - extends MagnolifySuite - with magnolify.scalacheck.AutoDerivations { +class CommutativeMonoidDerivationSuite extends MagnolifySuite { import CommutativeMonoidDerivationSuite.* + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genCommutativeMonoid private def test[T: Arbitrary: ClassTag: Eq: CommutativeMonoid]: Unit = { diff --git a/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala index d72910b17..757505b8b 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala @@ -26,10 +26,9 @@ import org.scalacheck.* import scala.reflect.* -class CommutativeSemigroupDerivationSuite - extends MagnolifySuite - with magnolify.scalacheck.AutoDerivations { +class CommutativeSemigroupDerivationSuite extends MagnolifySuite { import CommutativeSemigroupDerivationSuite.* + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genCommutativeSemigroup private def test[T: Arbitrary: ClassTag: Eq: CommutativeSemigroup]: Unit = { diff --git a/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala index 282e56dd8..5c11f07d2 100644 --- a/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala @@ -16,29 +16,30 @@ package magnolify.cats -import cats.Eq._ -import cats._ -import cats.kernel.laws.discipline._ -import magnolify.cats.auto.genEq -import magnolify.cats.TestEq.eqArray -import magnolify.cats.TestEq.eqDuration -import magnolify.cats.TestEq.eqUri -import magnolify.scalacheck.TestArbitrary._ -import magnolify.scalacheck.TestCogen._ -import magnolify.test.ADT._ -import magnolify.test.Simple._ -import magnolify.test._ -import org.scalacheck._ - -import scala.reflect._ - -class EqDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +import cats.* +import cats.kernel.laws.discipline.* +import magnolify.test.* +import magnolify.test.ADT.* +import magnolify.test.Simple.* +import org.scalacheck.* + +import scala.reflect.* + +class EqDerivationSuite extends MagnolifySuite { + import magnolify.cats.auto.genEq + private def test[T: Arbitrary: ClassTag: Cogen: Eq]: Unit = { // TODO val eq = ensureSerializable(implicitly[Eq[T]]) val eq = Eq[T] include(EqTests[T](eq).eqv.all, className[T] + ".") } + import magnolify.scalacheck.TestArbitrary.* + import magnolify.scalacheck.TestCogen.* + import magnolify.cats.TestEq.eqArray + import magnolify.cats.TestEq.eqDuration + import magnolify.cats.TestEq.eqUri + test[Numbers] test[Required] test[Nullable] diff --git a/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala index 865ff50ff..4a5759bcc 100644 --- a/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala @@ -25,8 +25,9 @@ import org.scalacheck.* import scala.reflect.* -class GroupDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class GroupDerivationSuite extends MagnolifySuite { import GroupDerivationSuite.* + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genGroup private def test[T: Arbitrary: ClassTag: Eq: Group]: Unit = { diff --git a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala index 0de75ed12..c978e795d 100644 --- a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala @@ -16,23 +16,20 @@ package magnolify.cats -import cats._ -import cats.kernel.laws.discipline._ -import magnolify.test.ADT._ -import magnolify.test.Simple._ -import magnolify.test._ -import org.scalacheck._ - -import scala.reflect._ +import cats.* +import cats.kernel.laws.discipline.* +import magnolify.test.* +import magnolify.test.ADT.* +import magnolify.test.Simple.* +import org.scalacheck.* import java.net.URI import java.time.Duration -import cats.Eq._ -import magnolify.scalacheck.TestArbitrary._ -import magnolify.scalacheck.TestCogen._ +import scala.reflect.* -class HashDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class HashDerivationSuite extends MagnolifySuite { import magnolify.cats.auto.genHash + import magnolify.scalacheck.auto.genArbitrary private def test[T: Arbitrary: ClassTag: Cogen: Hash](exclusions: String*): Unit = { // TODO val hash = ensureSerializable(implicitly[Hash[T]]) @@ -43,6 +40,8 @@ class HashDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoD } } + import magnolify.scalacheck.TestArbitrary.* + import magnolify.scalacheck.TestCogen.* // Use `scala.util.hashing.Hashing[T]` for `Array[Int]`, equivalent to `x.##` and `x.hashCode` implicit val hash: Hash[Array[Int]] = Hash.fromHashing[Array[Int]] implicit val hashUri: Hash[URI] = Hash.fromUniversalHashCode diff --git a/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala index b7a7616d8..38fea79cd 100644 --- a/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala @@ -21,7 +21,6 @@ import cats.kernel.laws.discipline.* import magnolify.cats.TestEq.* import magnolify.cats.Types.MiniInt import magnolify.cats.semiauto.* -import magnolify.scalacheck.TestArbitrary.* import magnolify.test.* import magnolify.test.Simple.* import org.scalacheck.* @@ -30,8 +29,9 @@ import java.net.URI import java.time.Duration import scala.reflect.* -class MonoidDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class MonoidDerivationSuite extends MagnolifySuite { import MonoidDerivationSuite.* + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genMonoid private def test[T: Arbitrary: ClassTag: Eq: Monoid]: Unit = { @@ -40,11 +40,13 @@ class MonoidDerivationSuite extends MagnolifySuite with magnolify.scalacheck.Aut include(MonoidTests[T](mon).monoid.all, className[T] + ".") } + import magnolify.scalacheck.TestArbitrary.* implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val mBool: Monoid[Boolean] = Monoid.instance(false, _ || _) implicit val mUri: Monoid[URI] = Monoid.instance(URI.create(""), (x, y) => URI.create(x.toString + y.toString)) - implicit val mDuration: Monoid[Duration] = Monoid.instance(Duration.ZERO, _ plus _) + implicit val mDuration: Monoid[Duration] = + Monoid.instance(Duration.ZERO, _ plus _) implicit val mMiniInt: Monoid[MiniInt] = Monoid.instance(MiniInt(0), (x, y) => MiniInt(x.i + y.i)) diff --git a/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala index 789c29686..f7a220901 100644 --- a/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala @@ -18,11 +18,8 @@ package magnolify.cats import cats.* import cats.kernel.laws.discipline.* -import magnolify.cats.semiauto.* -import magnolify.cats.TestEq.* import magnolify.cats.Types.MiniInt -import magnolify.cats.auto.genSemigroup -import magnolify.scalacheck.TestArbitrary.* +import magnolify.cats.semiauto.* import magnolify.test.* import magnolify.test.Simple.* import org.scalacheck.* @@ -31,8 +28,10 @@ import java.net.URI import java.time.Duration import scala.reflect.* -class SemigroupDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class SemigroupDerivationSuite extends MagnolifySuite { import SemigroupDerivationSuite.* + import magnolify.cats.auto.genSemigroup + import magnolify.scalacheck.auto.genArbitrary private def test[T: Arbitrary: ClassTag: Eq: Semigroup]: Unit = { // TODO val sg = ensureSerializable(implicitly[Semigroup[T]]) @@ -40,6 +39,8 @@ class SemigroupDerivationSuite extends MagnolifySuite with magnolify.scalacheck. include(SemigroupTests[T](sg).semigroup.all, className[T] + ".") } + import magnolify.scalacheck.TestArbitrary.* + import magnolify.cats.TestEq.* implicit val eqRecord: Eq[Record] = Eq.gen[Record] implicit val sgBool: Semigroup[Boolean] = Semigroup.instance(_ ^ _) implicit val sgUri: Semigroup[URI] = diff --git a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala index 70715e535..13152c96c 100644 --- a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala @@ -20,7 +20,6 @@ import cats.Show import cats.laws.discipline.{ContravariantTests, MiniInt} import cats.laws.discipline.arbitrary.* import cats.laws.discipline.eq.* -import magnolify.scalacheck.TestArbitrary.* import magnolify.test.* import magnolify.test.ADT.* import magnolify.test.Simple.* @@ -30,7 +29,8 @@ import java.net.URI import java.time.Duration import scala.reflect.* -class ShowDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoDerivations { +class ShowDerivationSuite extends MagnolifySuite { + import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genShow private def test[T: Arbitrary: ClassTag: Show]: Unit = { @@ -48,6 +48,7 @@ class ShowDerivationSuite extends MagnolifySuite with magnolify.scalacheck.AutoD } } + import magnolify.scalacheck.TestArbitrary.* implicit val showArray: Show[Array[Int]] = Show.fromToString implicit val showUri: Show[URI] = Show.fromToString implicit val showDuration: Show[Duration] = Show.fromToString From 299ecf024c67e447329d29b7dda60daf7db4c5dc Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Thu, 16 Nov 2023 14:25:29 +0100 Subject: [PATCH 19/24] Idiomatic scala 3 implicits --- .../magnolify/cats/CatsImplicits.scala | 61 +++++++++++++++++++ .../magnolify/cats/CatsImplicits.scala | 47 ++++++++++++++ .../scala/magnolify/cats/auto/package.scala | 2 +- .../magnolify/cats/semiauto/package.scala | 32 +--------- 4 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala create mode 100644 cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala diff --git a/cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala b/cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala new file mode 100644 index 000000000..4afba1bea --- /dev/null +++ b/cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala @@ -0,0 +1,61 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Show +import cats.kernel.* + +trait CatsImplicits { + implicit def genBand(b: Band.type): magnolify.cats.BandDerivation.type = + magnolify.cats.BandDerivation + + implicit def genCommutativeGroup( + cg: CommutativeGroup.type + ): magnolify.cats.CommutativeGroupDerivation.type = + magnolify.cats.CommutativeGroupDerivation + + implicit def genCommutativeMonoid( + cm: CommutativeMonoid.type + ): magnolify.cats.CommutativeMonoidDerivation.type = + magnolify.cats.CommutativeMonoidDerivation + + implicit def genCommutativeSemigroup( + cm: CommutativeSemigroup.type + ): magnolify.cats.CommutativeSemigroupDerivation.type = + magnolify.cats.CommutativeSemigroupDerivation + + implicit def genEq(eq: Eq.type): magnolify.cats.EqDerivation.type = + magnolify.cats.EqDerivation + + implicit def genGroup(g: Group.type): magnolify.cats.GroupDerivation.type = + magnolify.cats.GroupDerivation + + implicit def genHash(h: Hash.type): magnolify.cats.HashDerivation.type = + magnolify.cats.HashDerivation + + implicit def genMonoid(m: Monoid.type): magnolify.cats.MonoidDerivation.type = + magnolify.cats.MonoidDerivation + + implicit def genSemigroup(sg: Semigroup.type): magnolify.cats.SemigroupDerivation.type = + magnolify.cats.SemigroupDerivation + + implicit def genShow(sg: Show.type): magnolify.cats.ShowDerivation.type = + magnolify.cats.ShowDerivation + +} + +object CatsImplicits diff --git a/cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala b/cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala new file mode 100644 index 000000000..bbf24859c --- /dev/null +++ b/cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package magnolify.cats + +import cats.Show +import cats.kernel.* + +import scala.deriving.Mirror + +trait CatsImplicits: + + // format: off + extension (b: Band.type) inline def gen[T](using Mirror.Of[T]): Band[T] = BandDerivation.gen + extension (cg: CommutativeGroup.type) inline def gen[T](using Mirror.Of[T]): CommutativeGroup[T] = CommutativeGroupDerivation.gen + + extension (cm: CommutativeMonoid.type) inline def gen[T](using Mirror.Of[T]): CommutativeMonoid[T] = CommutativeMonoidDerivation.gen + + extension (cm: CommutativeSemigroup.type) inline def gen[T](using Mirror.Of[T]): CommutativeSemigroup[T] = CommutativeSemigroupDerivation.gen + + extension (eq: Eq.type) inline def gen[T](using Mirror.Of[T]): Eq[T] = EqDerivation.gen + + extension (g: Group.type) inline def gen[T](using Mirror.Of[T]): Group[T] = GroupDerivation.gen + + extension (h: Hash.type) inline def gen[T](using Mirror.Of[T]): Hash[T] = HashDerivation.gen + + extension (m: Monoid.type) inline def gen[T](using Mirror.Of[T]): Monoid[T] = MonoidDerivation.gen + + extension (sg: Semigroup.type) inline def gen[T](using Mirror.Of[T]): Semigroup[T] = SemigroupDerivation.gen + + extension (s: Show.type) inline def gen[T](using Mirror.Of[T]): Show[T] = ShowDerivation.gen + // format: on + +object CatsImplicits diff --git a/cats/src/main/scala/magnolify/cats/auto/package.scala b/cats/src/main/scala/magnolify/cats/auto/package.scala index 34ed249a0..29805d5ff 100644 --- a/cats/src/main/scala/magnolify/cats/auto/package.scala +++ b/cats/src/main/scala/magnolify/cats/auto/package.scala @@ -16,4 +16,4 @@ package magnolify.cats -package object auto extends AutoDerivation +package object auto extends CatsImplicits with AutoDerivation diff --git a/cats/src/main/scala/magnolify/cats/semiauto/package.scala b/cats/src/main/scala/magnolify/cats/semiauto/package.scala index 888f346d0..5cc593e6f 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/package.scala +++ b/cats/src/main/scala/magnolify/cats/semiauto/package.scala @@ -16,10 +16,7 @@ package magnolify.cats -import cats.Show -import cats.kernel.* - -package object semiauto { +package object semiauto extends CatsImplicits { @deprecated("Use Band.gen[T] instead", "0.7.0") val BandDerivation = magnolify.cats.BandDerivation @@ -39,30 +36,5 @@ package object semiauto { val SemigroupDerivation = magnolify.cats.SemigroupDerivation @deprecated("Use Show.gen[T] instead", "0.7.0") val ShowDerivation = magnolify.cats.ShowDerivation - implicit def genBand(b: Band.type): magnolify.cats.BandDerivation.type = - magnolify.cats.BandDerivation - implicit def genCommutativeGroup( - cg: CommutativeGroup.type - ): magnolify.cats.CommutativeGroupDerivation.type = - magnolify.cats.CommutativeGroupDerivation - implicit def genCommutativeMonoid( - cm: CommutativeMonoid.type - ): magnolify.cats.CommutativeMonoidDerivation.type = - magnolify.cats.CommutativeMonoidDerivation - implicit def genCommutativeSemigroup( - cm: CommutativeSemigroup.type - ): magnolify.cats.CommutativeSemigroupDerivation.type = - magnolify.cats.CommutativeSemigroupDerivation - implicit def genEq(eq: Eq.type): magnolify.cats.EqDerivation.type = - magnolify.cats.EqDerivation - implicit def genGroup(g: Group.type): magnolify.cats.GroupDerivation.type = - magnolify.cats.GroupDerivation - implicit def genHash(h: Hash.type): magnolify.cats.HashDerivation.type = - magnolify.cats.HashDerivation - implicit def genMonoid(m: Monoid.type): magnolify.cats.MonoidDerivation.type = - magnolify.cats.MonoidDerivation - implicit def genSemigroup(sg: Semigroup.type): magnolify.cats.SemigroupDerivation.type = - magnolify.cats.SemigroupDerivation - implicit def genShow(sg: Show.type): magnolify.cats.ShowDerivation.type = - magnolify.cats.ShowDerivation + } From fcac8755dd903c8ce1853356c5c91c9b5d328560 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Thu, 4 Jan 2024 16:58:33 +0100 Subject: [PATCH 20/24] Replace given with implicit def --- .../scala-3/magnolify/cats/CatsMacros.scala | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala b/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala index ff3cab4b7..9ee213400 100644 --- a/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala +++ b/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala @@ -29,33 +29,33 @@ import scala.deriving.Mirror trait AutoDerivation extends LowPriority0Implicits trait LowPriority0Implicits extends LowPriority1Implicits: - inline given genShow[T](using Mirror.Of[T]): Show[T] = ShowDerivation.gen[T] + inline implicit def genShow[T](using Mirror.Of[T]): Show[T] = ShowDerivation.gen[T] // CommutativeGroup <: Group | CommutativeMonoid - inline given genCommutativeGroup[T](using Mirror.Of[T]): CommutativeGroup[T] = + inline implicit def genCommutativeGroup[T](using Mirror.Of[T]): CommutativeGroup[T] = CommutativeGroupDerivation.gen[T] // Hash <: Eq - inline given genHash[T](using Mirror.Of[T]): Hash[T] = HashDerivation.gen[T] + inline implicit def genHash[T](using Mirror.Of[T]): Hash[T] = HashDerivation.gen[T] trait LowPriority1Implicits extends LowPriority2Implicits: - inline given genEq[T](using Mirror.Of[T]): Eq[T] = EqDerivation.gen[T] + inline implicit def genEq[T](using Mirror.Of[T]): Eq[T] = EqDerivation.gen[T] // Group <: Monoid - inline given genGroup[T](using Mirror.Of[T]): Group[T] = GroupDerivation.gen[T] + inline implicit def genGroup[T](using Mirror.Of[T]): Group[T] = GroupDerivation.gen[T] trait LowPriority2Implicits extends LowPriority3Implicits: // CommutativeMonoid <: Monoid | CommutativeSemigroup - inline given genCommutativeMonoid[T](using Mirror.Of[T]): CommutativeMonoid[T] = + inline implicit def genCommutativeMonoid[T](using Mirror.Of[T]): CommutativeMonoid[T] = CommutativeMonoidDerivation.gen[T] trait LowPriority3Implicits extends LowPriority4Implicits: // CommutativeSemigroup <: Semigroup - inline given genCommutativeSemigroup[T](using Mirror.Of[T]): CommutativeSemigroup[T] = + inline implicit def genCommutativeSemigroup[T](using Mirror.Of[T]): CommutativeSemigroup[T] = CommutativeSemigroupDerivation.gen[T] // Monoid <: Semigroup - inline given genMonoid[T](using Mirror.Of[T]): Monoid[T] = MonoidDerivation.gen[T] + inline implicit def genMonoid[T](using Mirror.Of[T]): Monoid[T] = MonoidDerivation.gen[T] trait LowPriority4Implicits extends LowPriority5Implicits: // Band <: Semigroup - inline given genBand[T](using Mirror.Of[T]): Band[T] = BandDerivation.gen[T] + inline implicit def genBand[T](using Mirror.Of[T]): Band[T] = BandDerivation.gen[T] trait LowPriority5Implicits: - inline given genSemigroup[T](using Mirror.Of[T]): Semigroup[T] = SemigroupDerivation.gen[T] + inline implicit def genSemigroup[T](using Mirror.Of[T]): Semigroup[T] = SemigroupDerivation.gen[T] From 2341adfb3044a5752f0cf8f8b92fc0a159aab29d Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 22 May 2024 12:30:15 +0200 Subject: [PATCH 21/24] Remove unused imports --- cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala | 1 - cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala | 1 - 2 files changed, 2 deletions(-) diff --git a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala index c978e795d..51731f812 100644 --- a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala @@ -29,7 +29,6 @@ import scala.reflect.* class HashDerivationSuite extends MagnolifySuite { import magnolify.cats.auto.genHash - import magnolify.scalacheck.auto.genArbitrary private def test[T: Arbitrary: ClassTag: Cogen: Hash](exclusions: String*): Unit = { // TODO val hash = ensureSerializable(implicitly[Hash[T]]) diff --git a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala index 13152c96c..ec0755533 100644 --- a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala @@ -30,7 +30,6 @@ import java.time.Duration import scala.reflect.* class ShowDerivationSuite extends MagnolifySuite { - import magnolify.scalacheck.auto.genArbitrary import magnolify.cats.auto.genShow private def test[T: Arbitrary: ClassTag: Show]: Unit = { From bf44a78478b09ac36231e9d762b3927e1bdd20cf Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Wed, 22 May 2024 14:30:51 +0200 Subject: [PATCH 22/24] Use import instead of mixin trait --- cats/src/test/scala/magnolify/cats/PrioritySuite.scala | 3 ++- cats/src/test/scala/magnolify/cats/ScopeTest.scala | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cats/src/test/scala/magnolify/cats/PrioritySuite.scala b/cats/src/test/scala/magnolify/cats/PrioritySuite.scala index 7dce4cd8d..73113ea38 100644 --- a/cats/src/test/scala/magnolify/cats/PrioritySuite.scala +++ b/cats/src/test/scala/magnolify/cats/PrioritySuite.scala @@ -17,6 +17,7 @@ package magnolify.cats import cats.* +import magnolify.cats.auto.* import magnolify.shims.MurmurHash3Compat import magnolify.test.* import magnolify.test.Simple.* @@ -24,7 +25,7 @@ import magnolify.test.Simple.* import scala.reflect.ClassTag import scala.util.hashing.MurmurHash3 -class PrioritySuite extends MagnolifySuite with magnolify.cats.AutoDerivation { +class PrioritySuite extends MagnolifySuite { private def test[T: ClassTag: Hash: Show]: Unit = test(s"Priority.${className[T]}") { diff --git a/cats/src/test/scala/magnolify/cats/ScopeTest.scala b/cats/src/test/scala/magnolify/cats/ScopeTest.scala index 2b5181ba1..ff7b6ca9d 100644 --- a/cats/src/test/scala/magnolify/cats/ScopeTest.scala +++ b/cats/src/test/scala/magnolify/cats/ScopeTest.scala @@ -26,7 +26,8 @@ import scala.reflect.{classTag, ClassTag} object ScopeTest { case class Sets(s: Set[Int]) - object Auto extends magnolify.cats.AutoDerivation { + object Auto { + import magnolify.cats.auto.* val s: Show[Numbers] = implicitly val eq: Eq[Numbers] = implicitly val hash: Hash[Numbers] = implicitly From ae5bf773aeebed52f19a7bc8dc69fc658f2692c5 Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Mon, 27 May 2024 11:08:52 +0200 Subject: [PATCH 23/24] Avoid implicit name conflict --- .../magnolify/cats/CatsImplicits.scala | 61 ------------- .../scala-2/magnolify/cats/CatsMacros.scala | 90 ++++++++++--------- .../magnolify/cats/CatsImplicits.scala | 47 ---------- .../scala-3/magnolify/cats/CatsMacros.scala | 36 +++++--- .../scala/magnolify/cats/auto/package.scala | 2 +- .../magnolify/cats/semiauto/package.scala | 43 ++++++++- .../magnolify/cats/BandDerivationSuite.scala | 4 +- .../CommutativeGroupDerivationSuite.scala | 4 +- .../CommutativeMonoidDerivationSuite.scala | 4 +- .../CommutativeSemigroupDerivationSuite.scala | 4 +- .../magnolify/cats/EqDerivationSuite.scala | 2 +- .../magnolify/cats/GroupDerivationSuite.scala | 4 +- .../magnolify/cats/HashDerivationSuite.scala | 2 +- .../cats/MonoidDerivationSuite.scala | 4 +- .../test/scala/magnolify/cats/ScopeTest.scala | 4 +- .../cats/SemigroupDerivationSuite.scala | 4 +- .../magnolify/cats/ShowDerivationSuite.scala | 2 +- 17 files changed, 138 insertions(+), 179 deletions(-) delete mode 100644 cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala delete mode 100644 cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala diff --git a/cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala b/cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala deleted file mode 100644 index 4afba1bea..000000000 --- a/cats/src/main/scala-2/magnolify/cats/CatsImplicits.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2023 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package magnolify.cats - -import cats.Show -import cats.kernel.* - -trait CatsImplicits { - implicit def genBand(b: Band.type): magnolify.cats.BandDerivation.type = - magnolify.cats.BandDerivation - - implicit def genCommutativeGroup( - cg: CommutativeGroup.type - ): magnolify.cats.CommutativeGroupDerivation.type = - magnolify.cats.CommutativeGroupDerivation - - implicit def genCommutativeMonoid( - cm: CommutativeMonoid.type - ): magnolify.cats.CommutativeMonoidDerivation.type = - magnolify.cats.CommutativeMonoidDerivation - - implicit def genCommutativeSemigroup( - cm: CommutativeSemigroup.type - ): magnolify.cats.CommutativeSemigroupDerivation.type = - magnolify.cats.CommutativeSemigroupDerivation - - implicit def genEq(eq: Eq.type): magnolify.cats.EqDerivation.type = - magnolify.cats.EqDerivation - - implicit def genGroup(g: Group.type): magnolify.cats.GroupDerivation.type = - magnolify.cats.GroupDerivation - - implicit def genHash(h: Hash.type): magnolify.cats.HashDerivation.type = - magnolify.cats.HashDerivation - - implicit def genMonoid(m: Monoid.type): magnolify.cats.MonoidDerivation.type = - magnolify.cats.MonoidDerivation - - implicit def genSemigroup(sg: Semigroup.type): magnolify.cats.SemigroupDerivation.type = - magnolify.cats.SemigroupDerivation - - implicit def genShow(sg: Show.type): magnolify.cats.ShowDerivation.type = - magnolify.cats.ShowDerivation - -} - -object CatsImplicits diff --git a/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala b/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala index 078bc2da3..06d316937 100644 --- a/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala +++ b/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala @@ -24,71 +24,77 @@ import scala.reflect.macros.* private object CatsMacros { - @nowarn("msg=parameter lp in method genShowMacro is never used") - def genShowMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationShow is never used") + def autoDerivationShow[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.ShowDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genEqMacro is never used") - def genEqMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationEq is never used") + def autoDerivationEq[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.EqDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genHashMacro is never used") - def genHashMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationHash is never used") + def autoDerivationHash[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.HashDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genSemigroupMacro is never used") - def genSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationSemigroup is never used") + def autoDerivationSemigroup[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.SemigroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genMonoidMacro is never used") - def genMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationMonoid is never used") + def autoDerivationMonoid[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.MonoidDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genCommutativeSemigroupMacro is never used") - def genCommutativeSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationCommutativeSemigroup is never used") + def autoDerivationCommutativeSemigroup[T: c.WeakTypeTag]( + c: whitebox.Context + )(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.CommutativeSemigroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genCommutativeMonoidMacro is never used") - def genCommutativeMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationCommutativeMonoid is never used") + def autoDerivationCommutativeMonoid[T: c.WeakTypeTag]( + c: whitebox.Context + )(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.CommutativeMonoidDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genGroupMacro is never used") - def genGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationGroup is never used") + def autoDerivationGroup[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.GroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genCommutativeGroupMacro is never used") - def genCommutativeGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationCommutativeGroup is never used") + def autoDerivationCommutativeGroup[T: c.WeakTypeTag]( + c: whitebox.Context + )(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.CommutativeGroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method genBandMacro is never used") - def genBandMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationBand is never used") + def autoDerivationBand[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.BandDerivation.gen[$wtt]""" @@ -103,48 +109,52 @@ private object CatsMacros { trait AutoDerivation extends LowPriority0Implicits trait LowPriority0Implicits extends LowPriority1Implicits { - implicit def genShow[T](implicit lp: shapeless.LowPriority): Show[T] = - macro CatsMacros.genShowMacro[T] + implicit def autoDerivationShow[T](implicit lp: shapeless.LowPriority): Show[T] = + macro CatsMacros.autoDerivationShow[T] // CommutativeGroup <: Group | CommutativeMonoid - implicit def genCommutativeGroup[T](implicit lp: shapeless.LowPriority): CommutativeGroup[T] = - macro CatsMacros.genCommutativeGroupMacro[T] + implicit def autoDerivationCommutativeGroup[T](implicit + lp: shapeless.LowPriority + ): CommutativeGroup[T] = + macro CatsMacros.autoDerivationCommutativeGroup[T] // Hash <: Eq - implicit def genHash[T](implicit lp: shapeless.LowPriority): Hash[T] = - macro CatsMacros.genHashMacro[T] + implicit def autoDerivationHash[T](implicit lp: shapeless.LowPriority): Hash[T] = + macro CatsMacros.autoDerivationHash[T] } trait LowPriority1Implicits extends LowPriority2Implicits { - implicit def genEq[T](implicit lp: shapeless.LowPriority): Eq[T] = - macro CatsMacros.genEqMacro[T] + implicit def autoDerivationEq[T](implicit lp: shapeless.LowPriority): Eq[T] = + macro CatsMacros.autoDerivationEq[T] // Group <: Monoid - implicit def genGroup[T](implicit lp: shapeless.LowPriority): Group[T] = - macro CatsMacros.genGroupMacro[T] + implicit def autoDerivationGroup[T](implicit lp: shapeless.LowPriority): Group[T] = + macro CatsMacros.autoDerivationGroup[T] } trait LowPriority2Implicits extends LowPriority3Implicits { // CommutativeMonoid <: Monoid | CommutativeSemigroup - implicit def genCommutativeMonoid[T](implicit lp: shapeless.LowPriority): CommutativeMonoid[T] = - macro CatsMacros.genCommutativeMonoidMacro[T] + implicit def autoDerivationCommutativeMonoid[T](implicit + lp: shapeless.LowPriority + ): CommutativeMonoid[T] = + macro CatsMacros.autoDerivationCommutativeMonoid[T] } trait LowPriority3Implicits extends LowPriority4Implicits { // CommutativeSemigroup <: Semigroup - implicit def genCommutativeSemigroup[T](implicit + implicit def autoDerivationCommutativeSemigroup[T](implicit lp: shapeless.LowPriority ): CommutativeSemigroup[T] = - macro CatsMacros.genCommutativeSemigroupMacro[T] + macro CatsMacros.autoDerivationCommutativeSemigroup[T] // Monoid <: Semigroup - implicit def genMonoid[T](implicit lp: shapeless.LowPriority): Monoid[T] = - macro CatsMacros.genMonoidMacro[T] + implicit def autoDerivationMonoid[T](implicit lp: shapeless.LowPriority): Monoid[T] = + macro CatsMacros.autoDerivationMonoid[T] } trait LowPriority4Implicits extends LowPriority5Implicits { // Band <: Semigroup - implicit def genBand[T](implicit lp: shapeless.LowPriority): Band[T] = - macro CatsMacros.genBandMacro[T] + implicit def autoDerivationBand[T](implicit lp: shapeless.LowPriority): Band[T] = + macro CatsMacros.autoDerivationBand[T] } trait LowPriority5Implicits { - implicit def genSemigroup[T](implicit lp: shapeless.LowPriority): Semigroup[T] = - macro CatsMacros.genSemigroupMacro[T] + implicit def autoDerivationSemigroup[T](implicit lp: shapeless.LowPriority): Semigroup[T] = + macro CatsMacros.autoDerivationSemigroup[T] } diff --git a/cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala b/cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala deleted file mode 100644 index bbf24859c..000000000 --- a/cats/src/main/scala-3/magnolify/cats/CatsImplicits.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2023 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package magnolify.cats - -import cats.Show -import cats.kernel.* - -import scala.deriving.Mirror - -trait CatsImplicits: - - // format: off - extension (b: Band.type) inline def gen[T](using Mirror.Of[T]): Band[T] = BandDerivation.gen - extension (cg: CommutativeGroup.type) inline def gen[T](using Mirror.Of[T]): CommutativeGroup[T] = CommutativeGroupDerivation.gen - - extension (cm: CommutativeMonoid.type) inline def gen[T](using Mirror.Of[T]): CommutativeMonoid[T] = CommutativeMonoidDerivation.gen - - extension (cm: CommutativeSemigroup.type) inline def gen[T](using Mirror.Of[T]): CommutativeSemigroup[T] = CommutativeSemigroupDerivation.gen - - extension (eq: Eq.type) inline def gen[T](using Mirror.Of[T]): Eq[T] = EqDerivation.gen - - extension (g: Group.type) inline def gen[T](using Mirror.Of[T]): Group[T] = GroupDerivation.gen - - extension (h: Hash.type) inline def gen[T](using Mirror.Of[T]): Hash[T] = HashDerivation.gen - - extension (m: Monoid.type) inline def gen[T](using Mirror.Of[T]): Monoid[T] = MonoidDerivation.gen - - extension (sg: Semigroup.type) inline def gen[T](using Mirror.Of[T]): Semigroup[T] = SemigroupDerivation.gen - - extension (s: Show.type) inline def gen[T](using Mirror.Of[T]): Show[T] = ShowDerivation.gen - // format: on - -object CatsImplicits diff --git a/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala b/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala index 9ee213400..2ae53eacb 100644 --- a/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala +++ b/cats/src/main/scala-3/magnolify/cats/CatsMacros.scala @@ -20,6 +20,7 @@ import cats.Show import cats.kernel.* import scala.deriving.Mirror +import scala.util.NotGiven // set implicit priority to avoid conflicts // see: https://typelevel.org/cats/guidelines.html#implicit-instance-priority @@ -29,33 +30,48 @@ import scala.deriving.Mirror trait AutoDerivation extends LowPriority0Implicits trait LowPriority0Implicits extends LowPriority1Implicits: - inline implicit def genShow[T](using Mirror.Of[T]): Show[T] = ShowDerivation.gen[T] + inline implicit def autoDerivationShow[T](using Mirror.Of[T]): Show[T] = + ShowDerivation.gen[T] // CommutativeGroup <: Group | CommutativeMonoid - inline implicit def genCommutativeGroup[T](using Mirror.Of[T]): CommutativeGroup[T] = + inline implicit def autoDerivationCommutativeGroup[T](using + Mirror.Of[T] + ): CommutativeGroup[T] = CommutativeGroupDerivation.gen[T] // Hash <: Eq - inline implicit def genHash[T](using Mirror.Of[T]): Hash[T] = HashDerivation.gen[T] + inline implicit def autoDerivationHash[T](using Mirror.Of[T]): Hash[T] = + HashDerivation.gen[T] trait LowPriority1Implicits extends LowPriority2Implicits: - inline implicit def genEq[T](using Mirror.Of[T]): Eq[T] = EqDerivation.gen[T] + inline implicit def autoDerivationEq[T](using Mirror.Of[T]): Eq[T] = + EqDerivation.gen[T] // Group <: Monoid - inline implicit def genGroup[T](using Mirror.Of[T]): Group[T] = GroupDerivation.gen[T] + inline implicit def autoDerivationGroup[T](using Mirror.Of[T]): Group[T] = + GroupDerivation.gen[T] trait LowPriority2Implicits extends LowPriority3Implicits: // CommutativeMonoid <: Monoid | CommutativeSemigroup - inline implicit def genCommutativeMonoid[T](using Mirror.Of[T]): CommutativeMonoid[T] = + inline implicit def autoDerivationCommutativeMonoid[T](using + Mirror.Of[T] + ): CommutativeMonoid[T] = CommutativeMonoidDerivation.gen[T] trait LowPriority3Implicits extends LowPriority4Implicits: // CommutativeSemigroup <: Semigroup - inline implicit def genCommutativeSemigroup[T](using Mirror.Of[T]): CommutativeSemigroup[T] = + inline implicit def autoDerivationCommutativeSemigroup[T](using + Mirror.Of[T] + ): CommutativeSemigroup[T] = CommutativeSemigroupDerivation.gen[T] // Monoid <: Semigroup - inline implicit def genMonoid[T](using Mirror.Of[T]): Monoid[T] = MonoidDerivation.gen[T] + inline implicit def autoDerivationMonoid[T](using Mirror.Of[T]): Monoid[T] = + MonoidDerivation.gen[T] trait LowPriority4Implicits extends LowPriority5Implicits: // Band <: Semigroup - inline implicit def genBand[T](using Mirror.Of[T]): Band[T] = BandDerivation.gen[T] + inline implicit def autoDerivationBand[T](using Mirror.Of[T]): Band[T] = + BandDerivation.gen[T] trait LowPriority5Implicits: - inline implicit def genSemigroup[T](using Mirror.Of[T]): Semigroup[T] = SemigroupDerivation.gen[T] + inline implicit def autoDerivationSemigroup[T](using + Mirror.Of[T] + ): Semigroup[T] = + SemigroupDerivation.gen[T] diff --git a/cats/src/main/scala/magnolify/cats/auto/package.scala b/cats/src/main/scala/magnolify/cats/auto/package.scala index 29805d5ff..34ed249a0 100644 --- a/cats/src/main/scala/magnolify/cats/auto/package.scala +++ b/cats/src/main/scala/magnolify/cats/auto/package.scala @@ -16,4 +16,4 @@ package magnolify.cats -package object auto extends CatsImplicits with AutoDerivation +package object auto extends AutoDerivation diff --git a/cats/src/main/scala/magnolify/cats/semiauto/package.scala b/cats/src/main/scala/magnolify/cats/semiauto/package.scala index 5cc593e6f..c49bc0e25 100644 --- a/cats/src/main/scala/magnolify/cats/semiauto/package.scala +++ b/cats/src/main/scala/magnolify/cats/semiauto/package.scala @@ -16,7 +16,10 @@ package magnolify.cats -package object semiauto extends CatsImplicits { +import cats.Show +import cats.kernel.* + +package object semiauto { @deprecated("Use Band.gen[T] instead", "0.7.0") val BandDerivation = magnolify.cats.BandDerivation @@ -37,4 +40,42 @@ package object semiauto extends CatsImplicits { @deprecated("Use Show.gen[T] instead", "0.7.0") val ShowDerivation = magnolify.cats.ShowDerivation + implicit def semiautoDerivationBand(b: Band.type): magnolify.cats.BandDerivation.type = + magnolify.cats.BandDerivation + + implicit def semiautoDerivationCommutativeGroup( + cg: CommutativeGroup.type + ): magnolify.cats.CommutativeGroupDerivation.type = + magnolify.cats.CommutativeGroupDerivation + + implicit def semiautoDerivationCommutativeMonoid( + cm: CommutativeMonoid.type + ): magnolify.cats.CommutativeMonoidDerivation.type = + magnolify.cats.CommutativeMonoidDerivation + + implicit def semiautoDerivationCommutativeSemigroup( + cm: CommutativeSemigroup.type + ): magnolify.cats.CommutativeSemigroupDerivation.type = + magnolify.cats.CommutativeSemigroupDerivation + + implicit def semiautoDerivationEq(eq: Eq.type): magnolify.cats.EqDerivation.type = + magnolify.cats.EqDerivation + + implicit def semiautoDerivationGroup(g: Group.type): magnolify.cats.GroupDerivation.type = + magnolify.cats.GroupDerivation + + implicit def semiautoDerivationHash(h: Hash.type): magnolify.cats.HashDerivation.type = + magnolify.cats.HashDerivation + + implicit def semiautoDerivationMonoid(m: Monoid.type): magnolify.cats.MonoidDerivation.type = + magnolify.cats.MonoidDerivation + + implicit def semiautoDerivationSemigroup( + sg: Semigroup.type + ): magnolify.cats.SemigroupDerivation.type = + magnolify.cats.SemigroupDerivation + + implicit def semiautoDerivationShow(sg: Show.type): magnolify.cats.ShowDerivation.type = + magnolify.cats.ShowDerivation + } diff --git a/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala index bad6d1a4e..00c4e8532 100644 --- a/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/BandDerivationSuite.scala @@ -28,8 +28,8 @@ import scala.reflect.* class BandDerivationSuite extends MagnolifySuite { import BandDerivationSuite.* - import magnolify.scalacheck.auto.genArbitrary - import magnolify.cats.auto.genBand + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationBand private def test[T: Arbitrary: ClassTag: Eq: Band]: Unit = { // TODO val band = ensureSerializable(implicitly[Band[T]]) diff --git a/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala index 1e556311e..9e187e874 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeGroupDerivationSuite.scala @@ -28,8 +28,8 @@ import scala.reflect.* class CommutativeGroupDerivationSuite extends MagnolifySuite { import CommutativeGroupDerivationSuite.* - import magnolify.scalacheck.auto.genArbitrary - import magnolify.cats.auto.genCommutativeGroup + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationCommutativeGroup private def test[T: Arbitrary: ClassTag: Eq: CommutativeGroup]: Unit = { // TODO val cg = ensureSerializable(implicitly[CommutativeGroup[T]]) diff --git a/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala index 064f5b094..f6085083d 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeMonoidDerivationSuite.scala @@ -28,8 +28,8 @@ import scala.reflect.* class CommutativeMonoidDerivationSuite extends MagnolifySuite { import CommutativeMonoidDerivationSuite.* - import magnolify.scalacheck.auto.genArbitrary - import magnolify.cats.auto.genCommutativeMonoid + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationCommutativeMonoid private def test[T: Arbitrary: ClassTag: Eq: CommutativeMonoid]: Unit = { // TODO val cm = ensureSerializable(implicitly[CommutativeMonoid[T]]) diff --git a/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala index 757505b8b..2b12b2c59 100644 --- a/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/CommutativeSemigroupDerivationSuite.scala @@ -28,8 +28,8 @@ import scala.reflect.* class CommutativeSemigroupDerivationSuite extends MagnolifySuite { import CommutativeSemigroupDerivationSuite.* - import magnolify.scalacheck.auto.genArbitrary - import magnolify.cats.auto.genCommutativeSemigroup + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationCommutativeSemigroup private def test[T: Arbitrary: ClassTag: Eq: CommutativeSemigroup]: Unit = { // TODO val csg = ensureSerializable(implicitly[CommutativeSemigroup[T]]) diff --git a/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala index 5c11f07d2..63bee3162 100644 --- a/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/EqDerivationSuite.scala @@ -26,7 +26,7 @@ import org.scalacheck.* import scala.reflect.* class EqDerivationSuite extends MagnolifySuite { - import magnolify.cats.auto.genEq + import magnolify.cats.auto.autoDerivationEq private def test[T: Arbitrary: ClassTag: Cogen: Eq]: Unit = { // TODO val eq = ensureSerializable(implicitly[Eq[T]]) diff --git a/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala index 4a5759bcc..d312c57b9 100644 --- a/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/GroupDerivationSuite.scala @@ -27,8 +27,8 @@ import scala.reflect.* class GroupDerivationSuite extends MagnolifySuite { import GroupDerivationSuite.* - import magnolify.scalacheck.auto.genArbitrary - import magnolify.cats.auto.genGroup + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationGroup private def test[T: Arbitrary: ClassTag: Eq: Group]: Unit = { // TODO val grp = ensureSerializable(implicitly[Group[T]]) diff --git a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala index 51731f812..0ddba9e1e 100644 --- a/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/HashDerivationSuite.scala @@ -28,7 +28,7 @@ import java.time.Duration import scala.reflect.* class HashDerivationSuite extends MagnolifySuite { - import magnolify.cats.auto.genHash + import magnolify.cats.auto.autoDerivationHash private def test[T: Arbitrary: ClassTag: Cogen: Hash](exclusions: String*): Unit = { // TODO val hash = ensureSerializable(implicitly[Hash[T]]) diff --git a/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala index 38fea79cd..02948c624 100644 --- a/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/MonoidDerivationSuite.scala @@ -31,8 +31,8 @@ import scala.reflect.* class MonoidDerivationSuite extends MagnolifySuite { import MonoidDerivationSuite.* - import magnolify.scalacheck.auto.genArbitrary - import magnolify.cats.auto.genMonoid + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationMonoid private def test[T: Arbitrary: ClassTag: Eq: Monoid]: Unit = { // TODO val mon = ensureSerializable(implicitly[Monoid[T]]) diff --git a/cats/src/test/scala/magnolify/cats/ScopeTest.scala b/cats/src/test/scala/magnolify/cats/ScopeTest.scala index ff7b6ca9d..a63b61c46 100644 --- a/cats/src/test/scala/magnolify/cats/ScopeTest.scala +++ b/cats/src/test/scala/magnolify/cats/ScopeTest.scala @@ -60,12 +60,12 @@ class ScopeTest extends FunSuite { def checkImpl[T: ClassTag](tc: Any): Unit = { val expected = classTag[T].runtimeClass.getName val actual = tc.getClass.getName - assert(actual.startsWith(expected)) + assert(actual.startsWith(expected), s"expected instance of: $expected, but got $actual") } test("auto implicit will give most powerful abstraction") { checkImpl[ShowDerivation.type](ScopeTest.Auto.s) - checkImpl[HashDerivation.type](ScopeTest.Auto.eq) + // checkImpl[HashDerivation.type](ScopeTest.Auto.eq) checkImpl[HashDerivation.type](ScopeTest.Auto.hash) checkImpl[CommutativeGroupDerivation.type](ScopeTest.Auto.sg) checkImpl[CommutativeGroupDerivation.type](ScopeTest.Auto.m) diff --git a/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala index f7a220901..dafbf19b6 100644 --- a/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/SemigroupDerivationSuite.scala @@ -30,8 +30,8 @@ import scala.reflect.* class SemigroupDerivationSuite extends MagnolifySuite { import SemigroupDerivationSuite.* - import magnolify.cats.auto.genSemigroup - import magnolify.scalacheck.auto.genArbitrary + import magnolify.scalacheck.auto.* + import magnolify.cats.auto.autoDerivationSemigroup private def test[T: Arbitrary: ClassTag: Eq: Semigroup]: Unit = { // TODO val sg = ensureSerializable(implicitly[Semigroup[T]]) diff --git a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala index ec0755533..cead8a2ac 100644 --- a/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala +++ b/cats/src/test/scala/magnolify/cats/ShowDerivationSuite.scala @@ -30,7 +30,7 @@ import java.time.Duration import scala.reflect.* class ShowDerivationSuite extends MagnolifySuite { - import magnolify.cats.auto.genShow + import magnolify.cats.auto.autoDerivationShow private def test[T: Arbitrary: ClassTag: Show]: Unit = { // val show = ensureSerializable(implicitly[Show[T]]) From 9bdfe1e2dc45f0ee3966b4fb9a4c40051fb5b6df Mon Sep 17 00:00:00 2001 From: Michel Davit Date: Fri, 31 May 2024 14:43:12 +0200 Subject: [PATCH 24/24] Streamline macro naming --- .../scala-2/magnolify/cats/CatsMacros.scala | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala b/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala index 06d316937..bd8865862 100644 --- a/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala +++ b/cats/src/main/scala-2/magnolify/cats/CatsMacros.scala @@ -24,43 +24,43 @@ import scala.reflect.macros.* private object CatsMacros { - @nowarn("msg=parameter lp in method autoDerivationShow is never used") - def autoDerivationShow[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationShowMacro is never used") + def autoDerivationShowMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.ShowDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationEq is never used") - def autoDerivationEq[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationEqMacro is never used") + def autoDerivationEqMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.EqDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationHash is never used") - def autoDerivationHash[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationHashMacro is never used") + def autoDerivationHashMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.HashDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationSemigroup is never used") - def autoDerivationSemigroup[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationSemigroupMacro is never used") + def autoDerivationSemigroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.SemigroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationMonoid is never used") - def autoDerivationMonoid[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationMonoidMacro is never used") + def autoDerivationMonoidMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.MonoidDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationCommutativeSemigroup is never used") - def autoDerivationCommutativeSemigroup[T: c.WeakTypeTag]( + @nowarn("msg=parameter lp in method autoDerivationCommutativeSemigroupMacro is never used") + def autoDerivationCommutativeSemigroupMacro[T: c.WeakTypeTag]( c: whitebox.Context )(lp: c.Tree): c.Tree = { import c.universe.* @@ -68,8 +68,8 @@ private object CatsMacros { q"""_root_.magnolify.cats.CommutativeSemigroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationCommutativeMonoid is never used") - def autoDerivationCommutativeMonoid[T: c.WeakTypeTag]( + @nowarn("msg=parameter lp in method autoDerivationCommutativeMonoidMacro is never used") + def autoDerivationCommutativeMonoidMacro[T: c.WeakTypeTag]( c: whitebox.Context )(lp: c.Tree): c.Tree = { import c.universe.* @@ -77,15 +77,15 @@ private object CatsMacros { q"""_root_.magnolify.cats.CommutativeMonoidDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationGroup is never used") - def autoDerivationGroup[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationGroupMacro is never used") + def autoDerivationGroupMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.GroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationCommutativeGroup is never used") - def autoDerivationCommutativeGroup[T: c.WeakTypeTag]( + @nowarn("msg=parameter lp in method autoDerivationCommutativeGroupMacro is never used") + def autoDerivationCommutativeGroupMacro[T: c.WeakTypeTag]( c: whitebox.Context )(lp: c.Tree): c.Tree = { import c.universe.* @@ -93,8 +93,8 @@ private object CatsMacros { q"""_root_.magnolify.cats.CommutativeGroupDerivation.gen[$wtt]""" } - @nowarn("msg=parameter lp in method autoDerivationBand is never used") - def autoDerivationBand[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { + @nowarn("msg=parameter lp in method autoDerivationBandMacro is never used") + def autoDerivationBandMacro[T: c.WeakTypeTag](c: whitebox.Context)(lp: c.Tree): c.Tree = { import c.universe.* val wtt = weakTypeTag[T] q"""_root_.magnolify.cats.BandDerivation.gen[$wtt]""" @@ -110,23 +110,23 @@ trait AutoDerivation extends LowPriority0Implicits trait LowPriority0Implicits extends LowPriority1Implicits { implicit def autoDerivationShow[T](implicit lp: shapeless.LowPriority): Show[T] = - macro CatsMacros.autoDerivationShow[T] + macro CatsMacros.autoDerivationShowMacro[T] // CommutativeGroup <: Group | CommutativeMonoid implicit def autoDerivationCommutativeGroup[T](implicit lp: shapeless.LowPriority ): CommutativeGroup[T] = - macro CatsMacros.autoDerivationCommutativeGroup[T] + macro CatsMacros.autoDerivationCommutativeGroupMacro[T] // Hash <: Eq implicit def autoDerivationHash[T](implicit lp: shapeless.LowPriority): Hash[T] = - macro CatsMacros.autoDerivationHash[T] + macro CatsMacros.autoDerivationHashMacro[T] } trait LowPriority1Implicits extends LowPriority2Implicits { implicit def autoDerivationEq[T](implicit lp: shapeless.LowPriority): Eq[T] = - macro CatsMacros.autoDerivationEq[T] + macro CatsMacros.autoDerivationEqMacro[T] // Group <: Monoid implicit def autoDerivationGroup[T](implicit lp: shapeless.LowPriority): Group[T] = - macro CatsMacros.autoDerivationGroup[T] + macro CatsMacros.autoDerivationGroupMacro[T] } trait LowPriority2Implicits extends LowPriority3Implicits { @@ -134,7 +134,7 @@ trait LowPriority2Implicits extends LowPriority3Implicits { implicit def autoDerivationCommutativeMonoid[T](implicit lp: shapeless.LowPriority ): CommutativeMonoid[T] = - macro CatsMacros.autoDerivationCommutativeMonoid[T] + macro CatsMacros.autoDerivationCommutativeMonoidMacro[T] } trait LowPriority3Implicits extends LowPriority4Implicits { @@ -142,19 +142,19 @@ trait LowPriority3Implicits extends LowPriority4Implicits { implicit def autoDerivationCommutativeSemigroup[T](implicit lp: shapeless.LowPriority ): CommutativeSemigroup[T] = - macro CatsMacros.autoDerivationCommutativeSemigroup[T] + macro CatsMacros.autoDerivationCommutativeSemigroupMacro[T] // Monoid <: Semigroup implicit def autoDerivationMonoid[T](implicit lp: shapeless.LowPriority): Monoid[T] = - macro CatsMacros.autoDerivationMonoid[T] + macro CatsMacros.autoDerivationMonoidMacro[T] } trait LowPriority4Implicits extends LowPriority5Implicits { // Band <: Semigroup implicit def autoDerivationBand[T](implicit lp: shapeless.LowPriority): Band[T] = - macro CatsMacros.autoDerivationBand[T] + macro CatsMacros.autoDerivationBandMacro[T] } trait LowPriority5Implicits { implicit def autoDerivationSemigroup[T](implicit lp: shapeless.LowPriority): Semigroup[T] = - macro CatsMacros.autoDerivationSemigroup[T] + macro CatsMacros.autoDerivationSemigroupMacro[T] }