Skip to content

Commit bf1507d

Browse files
committed
Fix codec derivation using Scala 2 for generic ADT with free type parameters for cases
1 parent c7e0101 commit bf1507d

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

jsoniter-scala-macros/shared/src/main/scala-2/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMaker.scala

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -978,20 +978,30 @@ object JsonCodecMaker {
978978
def collectRecursively(tpe: Type): Unit = {
979979
val tpeTypeArgs = typeArgs(tpe)
980980
val tpeClass = tpe.typeSymbol.asClass
981-
var typeParamsAndArgs = Map.empty[String, Type]
981+
var typeParamsAndArgs = Map.empty[Symbol, Type]
982982
if (tpeTypeArgs ne Nil) tpeClass.typeParams.zip(tpeTypeArgs).foreach { case (typeParam, typeArg) =>
983-
typeParamsAndArgs = typeParamsAndArgs.updated(typeParam.toString, typeArg)
983+
typeParamsAndArgs = typeParamsAndArgs.updated(typeParam, typeArg)
984984
}
985985
val subClasses = tpeClass.knownDirectSubclasses.toArray
986986
scala.util.Sorting.stableSort(subClasses)
987987
subClasses.foreach { s =>
988988
val classSymbol = s.asClass
989989
var subTpe = classSymbol.toType
990-
if (tpeTypeArgs ne Nil) {
991-
val typeParams = classSymbol.typeParams
992-
subTpe = subTpe.substituteTypes(typeParams, typeParams.map(tp => typeParamsAndArgs.getOrElse(tp.toString, fail {
993-
s"Cannot resolve generic type(s) for '$subTpe'. Please provide a custom implicitly accessible codec for it."
994-
})))
990+
val typeParams = classSymbol.typeParams
991+
if (typeParams.nonEmpty) {
992+
val subTpeBaseTypeArgs = typeArgs(subTpe.baseType(tpeClass))
993+
var subTpeParamsToArgs = Map.empty[Symbol, Type]
994+
subTpeBaseTypeArgs.zip(tpeTypeArgs).foreach { case (childBaseTypeArg, typeArg) =>
995+
childBaseTypeArg match {
996+
case TypeRef(_, typeParam, Nil) => subTpeParamsToArgs = subTpeParamsToArgs.updated(typeParam, typeArg)
997+
case _ =>
998+
}
999+
}
1000+
subTpe = subTpe.substituteTypes(typeParams, typeParams.map { typeParam =>
1001+
subTpeParamsToArgs.getOrElse(typeParam, typeParamsAndArgs.getOrElse(typeParam, fail {
1002+
s"Cannot resolve generic type(s) for '$subTpe'. Please provide a custom implicitly accessible codec for it."
1003+
}))
1004+
})
9951005
}
9961006
if (isSealedClass(subTpe)) collectRecursively(subTpe)
9971007
else if (isValueClass(subTpe)) {

jsoniter-scala-macros/shared/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMakerSpec.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import java.util.{Objects, UUID}
66
import com.github.plokhotnyuk.jsoniter_scala.core.{JsonValueCodec, _}
77
import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker._
88
import org.scalatest.exceptions.TestFailedException
9+
910
import java.util.concurrent.ThreadLocalRandom
1011
import scala.annotation.switch
1112
import scala.util.control.NonFatal
@@ -3112,6 +3113,16 @@ class JsonCodecMakerSpec extends VerifyingSpec {
31123113
verifySerDeser(codecOfFooForOption, Bar[Option](_root_.scala.Some(1)), """{"type":"Bar","a":1}""")
31133114
verifySerDeser(codecOfFooForOption, Baz[Option](_root_.scala.Some("VVV")), """{"type":"Baz","a":"VVV"}""")
31143115
}
3116+
"serialize and deserialize generic ADT with free type parameters for cases" in {
3117+
sealed trait GADT[A] extends Product with Serializable
3118+
3119+
case class FixedType(value: Int) extends GADT[Int]
3120+
3121+
case class VarType[B](value: B) extends GADT[B]
3122+
3123+
verifySerDeser(make[List[GADT[Int]]], List(FixedType(100), VarType(200)),
3124+
"""[{"type":"FixedType","value":100},{"type":"VarType","value":200}]""")
3125+
}
31153126
"serialize and deserialize recursive higher-kinded types" in {
31163127
case class HigherKindedType[F[_]](f: F[Int], fs: F[HigherKindedType[F]])
31173128

0 commit comments

Comments
 (0)