Skip to content

Commit 04d7592

Browse files
committed
Fix #95 by failing a compilation in case of no leaf subclasses was found for the ADT base
1 parent c48084b commit 04d7592

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

macros/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMaker.scala

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,20 @@ object JsonCodecMaker {
143143
s"of a sealed definition for '$tpe' or using a custom implicitly accessible codec for the ADT base."))
144144
}
145145

146-
def adtLeafClasses(tpe: Type): Set[Type] = tpe.typeSymbol.asClass.knownDirectSubclasses.flatMap { s =>
147-
val subTpe = s.asClass.toType
148-
if (isSealedAdtBase(subTpe)) adtLeafClasses(subTpe)
149-
else if (s.asClass.isCaseClass) Set(subTpe)
150-
else fail("Only case classes & case objects are supported for ADT leaf classes. Please consider using " +
151-
s"of them for ADT with base '$tpe' or using a custom implicitly accessible codec for the ADT base.")
146+
def adtLeafClasses(tpe: Type): Seq[Type] = {
147+
def collectRecursively(tpe: Type): Set[Type] =
148+
tpe.typeSymbol.asClass.knownDirectSubclasses.flatMap { s =>
149+
val subTpe = s.asClass.toType
150+
if (isSealedAdtBase(subTpe)) collectRecursively(subTpe)
151+
else if (s.asClass.isCaseClass) Set(subTpe)
152+
else fail("Only case classes & case objects are supported for ADT leaf classes. Please consider using " +
153+
s"of them for ADT with base '$tpe' or using a custom implicitly accessible codec for the ADT base.")
154+
}
155+
156+
val classes = collectRecursively(tpe).toSeq
157+
if (classes.isEmpty) fail(s"Cannot find leaf classes for ADT base '$tpe'. Please consider adding them or " +
158+
"using a custom implicitly accessible codec for the ADT base.")
159+
classes
152160
}
153161

154162
def companion(tpe: Type): Tree = Ident(tpe.typeSymbol.companion)
@@ -702,7 +710,7 @@ object JsonCodecMaker {
702710
JsonReader.toHashCode(cs, cs.length)
703711
}
704712

705-
val leafClasses = adtLeafClasses(tpe).toSeq
713+
val leafClasses = adtLeafClasses(tpe)
706714
val discrName = codecConfig.discriminatorFieldName
707715
checkDiscriminatorValueCollisions(discrName, leafClasses.map(discriminatorValue))
708716
val discriminatorValueError = q"in.discriminatorValueError($discrName)"

macros/src/test/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMakerSpec.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,22 @@ class JsonCodecMakerSpec extends WordSpec with Matchers {
931931
.stripMargin.replace('\n', ' ')
932932
})
933933
}
934+
"don't generate codec for ADT base without leaf classes" in {
935+
assert(intercept[TestFailedException](assertCompiles {
936+
"""sealed trait X
937+
|JsonCodecMaker.make[X](CodecMakerConfig())""".stripMargin
938+
}).getMessage.contains {
939+
"""Cannot find leaf classes for ADT base 'X'. Please consider adding them or using a custom implicitly
940+
|accessible codec for the ADT base.""".stripMargin.replace('\n', ' ')
941+
})
942+
assert(intercept[TestFailedException](assertCompiles {
943+
"""sealed abstract class X
944+
|JsonCodecMaker.make[X](CodecMakerConfig())""".stripMargin
945+
}).getMessage.contains {
946+
"""Cannot find leaf classes for ADT base 'X'. Please consider adding them or using a custom implicitly
947+
|accessible codec for the ADT base.""".stripMargin.replace('\n', ' ')
948+
})
949+
}
934950
"don't generate codec for case objects which are mapped to the same discriminator value" in {
935951
assert(intercept[TestFailedException](assertCompiles {
936952
"""sealed trait X

0 commit comments

Comments
 (0)