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

Commit c6c6b32

Browse files
Migrate to scala 3 (#311)
* 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
1 parent dee5ab9 commit c6c6b32

File tree

45 files changed

+668
-353
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+668
-353
lines changed

.scalafmt.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
version = 3.0.8
22
maxColumn = 120
3+
runner.dialect = scala3
4+
fileOverride {
5+
"glob:**/scala-2/**" {
6+
runner.dialect = scala213
7+
}
8+
}

build.sbt

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import com.softwaremill.Publish.{ossPublishSettings, updateDocs}
66

77
val scala212 = "2.12.14"
88
val scala213 = "2.13.6"
9+
val scala3 = "3.0.2"
910

10-
val scalaIdeaVersion = scala212 // the version for which to import sources into intellij
11+
val scalaIdeaVersion = scala3 // the version for which to import sources into intellij
1112

1213
val scalatestVersion = "3.2.10"
1314
val specs2Version = "4.13.0"
@@ -51,9 +52,20 @@ lazy val core = (projectMatrix in file("core"))
5152
.settings(commonSettings)
5253
.settings(
5354
name := "diffx-core",
55+
libraryDependencies ++= {
56+
CrossVersion.partialVersion(scalaVersion.value) match {
57+
case Some((3, _)) =>
58+
Seq(
59+
"com.softwaremill.magnolia1_3" %%% "magnolia" % "1.0.0-M7"
60+
)
61+
case _ =>
62+
Seq(
63+
"com.propensive" %%% "magnolia" % "0.17.0",
64+
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided
65+
)
66+
}
67+
},
5468
libraryDependencies ++= Seq(
55-
"com.propensive" %%% "magnolia" % "0.17.0",
56-
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
5769
"org.scalatest" %%% "scalatest-flatspec" % scalatestVersion % Test,
5870
"org.scalatest" %%% "scalatest-freespec" % scalatestVersion % Test,
5971
"org.scalatest" %%% "scalatest-shouldmatchers" % scalatestVersion % Test,
@@ -62,10 +74,10 @@ lazy val core = (projectMatrix in file("core"))
6274
versionSpecificScalaSources
6375
)
6476
.jvmPlatform(
65-
scalaVersions = List(scala212, scala213)
77+
scalaVersions = List(scala212, scala213, scala3)
6678
)
6779
.jsPlatform(
68-
scalaVersions = List(scala212, scala213)
80+
scalaVersions = List(scala212, scala213, scala3)
6981
)
7082

7183
lazy val scalatestMust = (projectMatrix in file("scalatest-must"))
@@ -80,10 +92,10 @@ lazy val scalatestMust = (projectMatrix in file("scalatest-must"))
8092
)
8193
.dependsOn(core)
8294
.jvmPlatform(
83-
scalaVersions = List(scala212, scala213)
95+
scalaVersions = List(scala212, scala213, scala3)
8496
)
8597
.jsPlatform(
86-
scalaVersions = List(scala212, scala213)
98+
scalaVersions = List(scala212, scala213, scala3)
8799
)
88100

89101
lazy val scalatestShould = (projectMatrix in file("scalatest-should"))
@@ -98,10 +110,10 @@ lazy val scalatestShould = (projectMatrix in file("scalatest-should"))
98110
)
99111
.dependsOn(core)
100112
.jvmPlatform(
101-
scalaVersions = List(scala212, scala213)
113+
scalaVersions = List(scala212, scala213, scala3)
102114
)
103115
.jsPlatform(
104-
scalaVersions = List(scala212, scala213)
116+
scalaVersions = List(scala212, scala213, scala3)
105117
)
106118

107119
lazy val scalatestLegacy = (projectMatrix in file("scalatest"))
@@ -116,10 +128,10 @@ lazy val scalatestLegacy = (projectMatrix in file("scalatest"))
116128
)
117129
.dependsOn(core)
118130
.jvmPlatform(
119-
scalaVersions = List(scala212, scala213)
131+
scalaVersions = List(scala212, scala213, scala3)
120132
)
121133
.jsPlatform(
122-
scalaVersions = List(scala212, scala213)
134+
scalaVersions = List(scala212, scala213, scala3)
123135
)
124136

125137
lazy val specs2 = (projectMatrix in file("specs2"))
@@ -149,10 +161,10 @@ lazy val utest = (projectMatrix in file("utest"))
149161
)
150162
.dependsOn(core)
151163
.jvmPlatform(
152-
scalaVersions = List(scala212, scala213)
164+
scalaVersions = List(scala212, scala213, scala3)
153165
)
154166
.jsPlatform(
155-
scalaVersions = List(scala212, scala213)
167+
scalaVersions = List(scala212, scala213, scala3)
156168
)
157169

158170
lazy val munit = (projectMatrix in file("munit"))
@@ -166,10 +178,10 @@ lazy val munit = (projectMatrix in file("munit"))
166178
)
167179
.dependsOn(core)
168180
.jvmPlatform(
169-
scalaVersions = List(scala212, scala213)
181+
scalaVersions = List(scala212, scala213, scala3)
170182
)
171183
.jsPlatform(
172-
scalaVersions = List(scala212, scala213),
184+
scalaVersions = List(scala212, scala213, scala3),
173185
settings = commonSettings ++ Seq(scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) })
174186
)
175187

@@ -185,10 +197,10 @@ lazy val tagging = (projectMatrix in file("tagging"))
185197
)
186198
.dependsOn(core)
187199
.jvmPlatform(
188-
scalaVersions = List(scala212, scala213)
200+
scalaVersions = List(scala212, scala213, scala3)
189201
)
190202
.jsPlatform(
191-
scalaVersions = List(scala212, scala213)
203+
scalaVersions = List(scala212, scala213, scala3)
192204
)
193205

194206
lazy val cats = (projectMatrix in file("cats"))
@@ -203,10 +215,10 @@ lazy val cats = (projectMatrix in file("cats"))
203215
)
204216
.dependsOn(core)
205217
.jvmPlatform(
206-
scalaVersions = List(scala212, scala213)
218+
scalaVersions = List(scala212, scala213, scala3)
207219
)
208220
.jsPlatform(
209-
scalaVersions = List(scala212, scala213)
221+
scalaVersions = List(scala212, scala213, scala3)
210222
)
211223

212224
lazy val refined = (projectMatrix in file("refined"))
@@ -221,12 +233,11 @@ lazy val refined = (projectMatrix in file("refined"))
221233
)
222234
.dependsOn(core)
223235
.jvmPlatform(
224-
scalaVersions = List(scala212, scala213)
236+
scalaVersions = List(scala212, scala213, scala3)
225237
)
226238
.jsPlatform(
227-
scalaVersions = List(scala212, scala213)
239+
scalaVersions = List(scala212, scala213, scala3)
228240
)
229-
//
230241

231242
lazy val docs = (projectMatrix in file("generated-docs")) // important: it must not be docs/
232243
.enablePlugins(MdocPlugin)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.softwaremill.diffx
2+
3+
import com.softwaremill.diffx.generic.DiffMagnoliaDerivation
4+
import magnolia.Magnolia
5+
6+
trait DiffCompanionMacro extends DiffMagnoliaDerivation {
7+
def derived[T]: Diff[T] = macro Magnolia.gen[T]
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.softwaremill.diffx
2+
3+
trait DiffLensMacro[T, U] {
4+
def useMatcher[M](matcher: ObjectMatcher[M]): Diff[T] = macro ModifyMacro.withObjectMatcher[T, U, M]
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.softwaremill.diffx
2+
3+
trait DiffMacro[T] {
4+
def modify[U](path: T => U): DiffLens[T, U] = macro ModifyMacro.modifyMacro[T, U]
5+
def ignore[U](path: T => U)(implicit conf: DiffConfiguration): Diff[T] = macro ModifyMacro.ignoreMacro[T, U]
6+
}

core/src/main/scala/com/softwaremill/diffx/ModifyMacro.scala renamed to core/src/main/scala-2/com/softwaremill/diffx/ModifyMacro.scala

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,6 @@ import scala.reflect.macros.blackbox
88
object ModifyMacro {
99
private val ShapeInfo = "Path must have shape: _.field1.field2.each.field3.(...)"
1010

11-
def derivedModifyMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](
12-
c: blackbox.Context
13-
)(path: c.Expr[T => U]): c.Tree =
14-
applyDerivedModified[T, U](c)(modifiedFromPathMacro(c)(path))
15-
16-
private def applyDerivedModified[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(
17-
path: c.Expr[List[String]]
18-
): c.Tree = {
19-
import c.universe._
20-
q"""com.softwaremill.diffx.DerivedDiffLens(${c.prefix}.dd.value, $path)"""
21-
}
22-
23-
def derivedIgnoreMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](
24-
c: blackbox.Context
25-
)(path: c.Expr[T => U])(conf: c.Expr[DiffConfiguration]): c.Tree =
26-
applyIgnoredModified[T, U](c)(modifiedFromPathMacro(c)(path), conf)
27-
28-
private def applyIgnoredModified[T: c.WeakTypeTag, U: c.WeakTypeTag](c: blackbox.Context)(
29-
path: c.Expr[List[String]],
30-
conf: c.Expr[DiffConfiguration]
31-
): c.Tree = {
32-
import c.universe._
33-
val lens = applyDerivedModified[T, U](c)(path)
34-
q"""$lens.ignore($conf)"""
35-
}
36-
3711
def ignoreMacro[T: c.WeakTypeTag, U: c.WeakTypeTag](
3812
c: blackbox.Context
3913
)(path: c.Expr[T => U])(conf: c.Expr[DiffConfiguration]): c.Tree =
@@ -56,7 +30,7 @@ object ModifyMacro {
5630
)(path: c.Expr[List[String]]): c.Tree = {
5731
import c.universe._
5832
q"""{
59-
com.softwaremill.diffx.DiffLens(${c.prefix}.d, $path)
33+
com.softwaremill.diffx.DiffLens(${c.prefix}, $path)
6034
}"""
6135
}
6236

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

118-
def withObjectMatcherDerived[T: c.WeakTypeTag, U: c.WeakTypeTag, M: c.WeakTypeTag](
119-
c: blackbox.Context
120-
)(matcher: c.Expr[ObjectMatcher[M]]): c.Tree = {
121-
import c.universe._
122-
val diff = withObjectMatcher[T, U, M](c)(matcher)
123-
q"com.softwaremill.diffx.Derived($diff)"
124-
}
125-
12692
def withObjectMatcher[T: c.WeakTypeTag, U: c.WeakTypeTag, M: c.WeakTypeTag](
12793
c: blackbox.Context
12894
)(matcher: c.Expr[ObjectMatcher[M]]): c.Tree = {
@@ -141,7 +107,7 @@ object ModifyMacro {
141107
if (!setRequirements && !iterableRequirements && !mapRequirements) { // weakTypeOf[U] <:< tq"Iterable[${u.typeArgs.head.termSymbol}]"
142108
c.abort(c.enclosingPosition, s"Invalid objectMather type $u for given lens($t,$m)")
143109
}
144-
q"""
110+
q"""
145111
val lens = ${c.prefix}
146112
lens.outer.modifyMatcherUnsafe(lens.path: _*)($matcher)
147113
"""

core/src/main/scala/com/softwaremill/diffx/generic/DiffMagnoliaDerivation.scala renamed to core/src/main/scala-2/com/softwaremill/diffx/generic/DiffMagnoliaDerivation.scala

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
package com.softwaremill.diffx.generic
22

3-
import com.softwaremill.diffx.{
4-
Diff,
5-
DiffContext,
6-
DiffResultObject,
7-
DiffResultValue,
8-
FieldPath,
9-
IdenticalValue,
10-
nullGuard
11-
}
3+
import com.softwaremill.diffx.{Diff, DiffContext, DiffResultObject, DiffResultValue, nullGuard}
124
import magnolia._
135

146
import scala.collection.immutable.ListMap
157

16-
trait DiffMagnoliaDerivation extends LowPriority {
8+
trait DiffMagnoliaDerivation {
179
type Typeclass[T] = Diff[T]
1810

1911
def combine[T](ctx: ReadOnlyCaseClass[Typeclass, T]): Diff[T] = { (left: T, right: T, context: DiffContext) =>
@@ -44,15 +36,6 @@ trait DiffMagnoliaDerivation extends LowPriority {
4436
}
4537
}
4638
}
47-
}
4839

49-
trait LowPriority {
50-
def fallback[T]: Diff[T] =
51-
(left: T, right: T, context: DiffContext) => {
52-
if (left != right) {
53-
DiffResultValue(left, right)
54-
} else {
55-
IdenticalValue(left)
56-
}
57-
}
40+
def fallback[T]: Diff[T] = Diff.useEquals[T]
5841
}

core/src/main/scala/com/softwaremill/diffx/generic/MagnoliaDerivedMacro.scala renamed to core/src/main/scala-2/com/softwaremill/diffx/generic/MagnoliaDerivedMacro.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package com.softwaremill.diffx.generic
22

33
import com.softwaremill.diffx.Derived
44
import magnolia.Magnolia
5-
import scala.language.experimental.macros
65

76
object MagnoliaDerivedMacro {
7+
88
import scala.reflect.macros.whitebox
99

1010
def derivedGen[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[Derived[T]] = {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.softwaremill.diffx
2+
3+
import com.softwaremill.diffx.generic.DiffMagnoliaDerivation
4+
import com.softwaremill.diffx.generic.auto.DiffAutoDerivationOn
5+
6+
trait DiffCompanionMacro extends DiffMagnoliaDerivation {
7+
given fallback[T](using DiffAutoDerivationOn): Derived[Diff[T]] = Derived(Diff.useEquals[T])
8+
}

0 commit comments

Comments
 (0)