Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-build cats module on scala3 #859

Draft
wants to merge 24 commits into
base: scala3-scalacheck
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 cats/test

- name: Check binary compatibility
if: '!(matrix.scala == ''3'')'
Expand Down
13 changes: 9 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -110,7 +110,9 @@ val scala212 = "2.12.19"
val scalaDefault = scala213
val scala3Projects = List(
"shared",
"test"
"test",
"scalacheck",
"cats"
)

// github actions
Expand Down Expand Up @@ -267,7 +269,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(
Expand Down Expand Up @@ -373,6 +377,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
)

Expand All @@ -387,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
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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]
}
160 changes: 160 additions & 0 deletions cats/src/main/scala-2/magnolify/cats/CatsMacros.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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 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 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 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 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 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 autoDerivationCommutativeSemigroupMacro is never used")
def autoDerivationCommutativeSemigroupMacro[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 autoDerivationCommutativeMonoidMacro is never used")
def autoDerivationCommutativeMonoidMacro[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 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 autoDerivationCommutativeGroupMacro is never used")
def autoDerivationCommutativeGroupMacro[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 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]"""
}
}

// 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 autoDerivationShow[T](implicit lp: shapeless.LowPriority): Show[T] =
macro CatsMacros.autoDerivationShowMacro[T]
// CommutativeGroup <: Group | CommutativeMonoid
implicit def autoDerivationCommutativeGroup[T](implicit
lp: shapeless.LowPriority
): CommutativeGroup[T] =
macro CatsMacros.autoDerivationCommutativeGroupMacro[T]
// Hash <: Eq
implicit def autoDerivationHash[T](implicit lp: shapeless.LowPriority): Hash[T] =
macro CatsMacros.autoDerivationHashMacro[T]
}

trait LowPriority1Implicits extends LowPriority2Implicits {
implicit def autoDerivationEq[T](implicit lp: shapeless.LowPriority): Eq[T] =
macro CatsMacros.autoDerivationEqMacro[T]
// Group <: Monoid
implicit def autoDerivationGroup[T](implicit lp: shapeless.LowPriority): Group[T] =
macro CatsMacros.autoDerivationGroupMacro[T]
}

trait LowPriority2Implicits extends LowPriority3Implicits {
// CommutativeMonoid <: Monoid | CommutativeSemigroup
implicit def autoDerivationCommutativeMonoid[T](implicit
lp: shapeless.LowPriority
): CommutativeMonoid[T] =
macro CatsMacros.autoDerivationCommutativeMonoidMacro[T]
}

trait LowPriority3Implicits extends LowPriority4Implicits {
// CommutativeSemigroup <: Semigroup
implicit def autoDerivationCommutativeSemigroup[T](implicit
lp: shapeless.LowPriority
): CommutativeSemigroup[T] =
macro CatsMacros.autoDerivationCommutativeSemigroupMacro[T]
// Monoid <: Semigroup
implicit def autoDerivationMonoid[T](implicit lp: shapeless.LowPriority): Monoid[T] =
macro CatsMacros.autoDerivationMonoidMacro[T]
}

trait LowPriority4Implicits extends LowPriority5Implicits {
// Band <: Semigroup
implicit def autoDerivationBand[T](implicit lp: shapeless.LowPriority): Band[T] =
macro CatsMacros.autoDerivationBandMacro[T]
}

trait LowPriority5Implicits {
implicit def autoDerivationSemigroup[T](implicit lp: shapeless.LowPriority): Semigroup[T] =
macro CatsMacros.autoDerivationSemigroupMacro[T]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading