Skip to content
This repository has been archived by the owner on Jan 24, 2025. It is now read-only.

Commit

Permalink
Migrate to scala 3 (#311)
Browse files Browse the repository at this point in the history
* Prepare for migration - move scala2 code which cannot be migrated to separate directory

* Compile base scala-3 code

* Enable tests for product derivation

* Enable basic tests for collections

* Autoderivation should in the end returns Derived[Diff]

* Convert Derived to value class so it can be inlined

(this is required by inline macro in scala3)

* Migrate ignore and modify macros to scala3

* Fix more of the DiffTest

* Migrate modifyMacro test

* Migrate ObjectMatcherTest

* Migrate DiffModifyIntegrationTest

* Fix docs compilation

* Bring back use of auto-derivation in scala-2 tests

* Fix js build

* Unify return type of `derived` method across scala versions

* Restore auto derivation for scala3

* Migrate useMatcher macro to scala3

* Uncomment "coproduct types with ignored fields" test

* Split derivedDiff into two methods

* Uncomment "set of products" test

* Uncomment rest of DiffModifyIntegrationTest

* Unify tests across scala versions

* Migrate scalatest to scala3

* Enable scala3 for cats module

* Enable scala3 for tagging module

* Enable scala3 for munit

* Add test for non case class instances to core

* Make fallback work on scala3

* Change autoDerive to autoDerived

* Cross compile core for scala3 js

* Cross compile utest for scala3 and scala3 js

* Enable autoDerivation in a way that works on all versions

* Enable scala3 js for cats module

* Enable scala3 js for tagging module

* Enable scala3 js for munit module

* Enable scala3 js for scalatest module

* Run scalafmt across all modules

* Simplify code as there is no need for DerivedLens anymore after switch to be an invariant tc

* Add missing autoDerivation to specs2-test

* Enable scala3 for refined module

* Update diffx supported scala version

* Add note on autoDerived method
  • Loading branch information
ghostbuster91 authored Oct 31, 2021
1 parent dee5ab9 commit c6c6b32
Show file tree
Hide file tree
Showing 45 changed files with 668 additions and 353 deletions.
6 changes: 6 additions & 0 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
version = 3.0.8
maxColumn = 120
runner.dialect = scala3
fileOverride {
"glob:**/scala-2/**" {
runner.dialect = scala213
}
}
55 changes: 33 additions & 22 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import com.softwaremill.Publish.{ossPublishSettings, updateDocs}

val scala212 = "2.12.14"
val scala213 = "2.13.6"
val scala3 = "3.0.2"

val scalaIdeaVersion = scala212 // the version for which to import sources into intellij
val scalaIdeaVersion = scala3 // the version for which to import sources into intellij

val scalatestVersion = "3.2.10"
val specs2Version = "4.13.0"
Expand Down Expand Up @@ -51,9 +52,20 @@ lazy val core = (projectMatrix in file("core"))
.settings(commonSettings)
.settings(
name := "diffx-core",
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((3, _)) =>
Seq(
"com.softwaremill.magnolia1_3" %%% "magnolia" % "1.0.0-M7"
)
case _ =>
Seq(
"com.propensive" %%% "magnolia" % "0.17.0",
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided
)
}
},
libraryDependencies ++= Seq(
"com.propensive" %%% "magnolia" % "0.17.0",
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.scalatest" %%% "scalatest-flatspec" % scalatestVersion % Test,
"org.scalatest" %%% "scalatest-freespec" % scalatestVersion % Test,
"org.scalatest" %%% "scalatest-shouldmatchers" % scalatestVersion % Test,
Expand All @@ -62,10 +74,10 @@ lazy val core = (projectMatrix in file("core"))
versionSpecificScalaSources
)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val scalatestMust = (projectMatrix in file("scalatest-must"))
Expand All @@ -80,10 +92,10 @@ lazy val scalatestMust = (projectMatrix in file("scalatest-must"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val scalatestShould = (projectMatrix in file("scalatest-should"))
Expand All @@ -98,10 +110,10 @@ lazy val scalatestShould = (projectMatrix in file("scalatest-should"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val scalatestLegacy = (projectMatrix in file("scalatest"))
Expand All @@ -116,10 +128,10 @@ lazy val scalatestLegacy = (projectMatrix in file("scalatest"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val specs2 = (projectMatrix in file("specs2"))
Expand Down Expand Up @@ -149,10 +161,10 @@ lazy val utest = (projectMatrix in file("utest"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val munit = (projectMatrix in file("munit"))
Expand All @@ -166,10 +178,10 @@ lazy val munit = (projectMatrix in file("munit"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213),
scalaVersions = List(scala212, scala213, scala3),
settings = commonSettings ++ Seq(scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) })
)

Expand All @@ -185,10 +197,10 @@ lazy val tagging = (projectMatrix in file("tagging"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val cats = (projectMatrix in file("cats"))
Expand All @@ -203,10 +215,10 @@ lazy val cats = (projectMatrix in file("cats"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)

lazy val refined = (projectMatrix in file("refined"))
Expand All @@ -221,12 +233,11 @@ lazy val refined = (projectMatrix in file("refined"))
)
.dependsOn(core)
.jvmPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
.jsPlatform(
scalaVersions = List(scala212, scala213)
scalaVersions = List(scala212, scala213, scala3)
)
//

lazy val docs = (projectMatrix in file("generated-docs")) // important: it must not be docs/
.enablePlugins(MdocPlugin)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.softwaremill.diffx

import com.softwaremill.diffx.generic.DiffMagnoliaDerivation
import magnolia.Magnolia

trait DiffCompanionMacro extends DiffMagnoliaDerivation {
def derived[T]: Diff[T] = macro Magnolia.gen[T]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.softwaremill.diffx

trait DiffLensMacro[T, U] {
def useMatcher[M](matcher: ObjectMatcher[M]): Diff[T] = macro ModifyMacro.withObjectMatcher[T, U, M]
}
6 changes: 6 additions & 0 deletions core/src/main/scala-2/com/softwaremill/diffx/DiffMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.softwaremill.diffx

trait DiffMacro[T] {
def modify[U](path: T => U): DiffLens[T, U] = macro ModifyMacro.modifyMacro[T, U]
def ignore[U](path: T => U)(implicit conf: DiffConfiguration): Diff[T] = macro ModifyMacro.ignoreMacro[T, U]
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,6 @@ import scala.reflect.macros.blackbox
object ModifyMacro {
private val ShapeInfo = "Path must have shape: _.field1.field2.each.field3.(...)"

def derivedModifyMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](
c: blackbox.Context
)(path: c.Expr[T => U]): c.Tree =
applyDerivedModified[T, U](c)(modifiedFromPathMacro(c)(path))

private def applyDerivedModified[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(
path: c.Expr[List[String]]
): c.Tree = {
import c.universe._
q"""com.softwaremill.diffx.DerivedDiffLens(${c.prefix}.dd.value, $path)"""
}

def derivedIgnoreMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](
c: blackbox.Context
)(path: c.Expr[T => U])(conf: c.Expr[DiffConfiguration]): c.Tree =
applyIgnoredModified[T, U](c)(modifiedFromPathMacro(c)(path), conf)

private def applyIgnoredModified[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(
path: c.Expr[List[String]],
conf: c.Expr[DiffConfiguration]
): c.Tree = {
import c.universe._
val lens = applyDerivedModified[T, U](c)(path)
q"""$lens.ignore($conf)"""
}

def ignoreMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](
c: blackbox.Context
)(path: c.Expr[T => U])(conf: c.Expr[DiffConfiguration]): c.Tree =
Expand All @@ -56,7 +30,7 @@ object ModifyMacro {
)(path: c.Expr[List[String]]): c.Tree = {
import c.universe._
q"""{
com.softwaremill.diffx.DiffLens(${c.prefix}.d, $path)
com.softwaremill.diffx.DiffLens(${c.prefix}, $path)
}"""
}

Expand Down Expand Up @@ -115,14 +89,6 @@ object ModifyMacro {
private[diffx] def modifiedFromPath[T, U](path: T => U): List[String] =
macro modifiedFromPathMacro[T, U]

def withObjectMatcherDerived[T: c.WeakTypeTag, U: c.WeakTypeTag, M: c.WeakTypeTag](
c: blackbox.Context
)(matcher: c.Expr[ObjectMatcher[M]]): c.Tree = {
import c.universe._
val diff = withObjectMatcher[T, U, M](c)(matcher)
q"com.softwaremill.diffx.Derived($diff)"
}

def withObjectMatcher[T: c.WeakTypeTag, U: c.WeakTypeTag, M: c.WeakTypeTag](
c: blackbox.Context
)(matcher: c.Expr[ObjectMatcher[M]]): c.Tree = {
Expand All @@ -141,7 +107,7 @@ object ModifyMacro {
if (!setRequirements && !iterableRequirements && !mapRequirements) { // weakTypeOf[U] <:< tq"Iterable[${u.typeArgs.head.termSymbol}]"
c.abort(c.enclosingPosition, s"Invalid objectMather type $u for given lens($t,$m)")
}
q"""
q"""
val lens = ${c.prefix}
lens.outer.modifyMatcherUnsafe(lens.path: _*)($matcher)
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
package com.softwaremill.diffx.generic

import com.softwaremill.diffx.{
Diff,
DiffContext,
DiffResultObject,
DiffResultValue,
FieldPath,
IdenticalValue,
nullGuard
}
import com.softwaremill.diffx.{Diff, DiffContext, DiffResultObject, DiffResultValue, nullGuard}
import magnolia._

import scala.collection.immutable.ListMap

trait DiffMagnoliaDerivation extends LowPriority {
trait DiffMagnoliaDerivation {
type Typeclass[T] = Diff[T]

def combine[T](ctx: ReadOnlyCaseClass[Typeclass, T]): Diff[T] = { (left: T, right: T, context: DiffContext) =>
Expand Down Expand Up @@ -44,15 +36,6 @@ trait DiffMagnoliaDerivation extends LowPriority {
}
}
}
}

trait LowPriority {
def fallback[T]: Diff[T] =
(left: T, right: T, context: DiffContext) => {
if (left != right) {
DiffResultValue(left, right)
} else {
IdenticalValue(left)
}
}
def fallback[T]: Diff[T] = Diff.useEquals[T]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package com.softwaremill.diffx.generic

import com.softwaremill.diffx.Derived
import magnolia.Magnolia
import scala.language.experimental.macros

object MagnoliaDerivedMacro {

import scala.reflect.macros.whitebox

def derivedGen[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[Derived[T]] = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.softwaremill.diffx

import com.softwaremill.diffx.generic.DiffMagnoliaDerivation
import com.softwaremill.diffx.generic.auto.DiffAutoDerivationOn

trait DiffCompanionMacro extends DiffMagnoliaDerivation {
given fallback[T](using DiffAutoDerivationOn): Derived[Diff[T]] = Derived(Diff.useEquals[T])
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.softwaremill.diffx

trait DiffLensMacro[T, U] { outer: DiffLens[T, U] =>
inline def useMatcher[M](inline matcher: ObjectMatcher[M]): Diff[T] = ${
ModifyMacro.withObjectMatcher[T, U, M]('outer)('matcher)
}
}
8 changes: 8 additions & 0 deletions core/src/main/scala-3/com/softwaremill/diffx/DiffMacro.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.softwaremill.diffx

trait DiffMacro[T] { outer: Diff[T] =>
inline def modify[U](inline path: T => U): DiffLens[T, U] = ${ ModifyMacro.modifyMacro[T, U]('outer)('path) }
inline def ignore[U](inline path: T => U)(implicit config: DiffConfiguration): Diff[T] = ${
ModifyMacro.ignoreMacro[T, U]('outer)('path, 'config)
}
}
Loading

0 comments on commit c6c6b32

Please sign in to comment.