@@ -355,31 +355,59 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
355
355
symbolsToSynthesize.flatMap(syntheticDefIfMissing)
356
356
}
357
357
358
+ private def hasWriteReplace (clazz : ClassSymbol )(using Context ): Boolean =
359
+ clazz.membersNamed(nme.writeReplace)
360
+ .filterWithPredicate(s => s.signature == Signature (defn.AnyRefType , isJava = false ))
361
+ .exists
362
+
363
+ private def writeReplaceDef (clazz : ClassSymbol )(using Context ): TermSymbol =
364
+ newSymbol(clazz, nme.writeReplace, Method | Private | Synthetic ,
365
+ MethodType (Nil , defn.AnyRefType ), coord = clazz.coord).entered.asTerm
366
+
358
367
/** If this is a serializable static object `Foo`, add the method:
359
368
*
360
369
* private def writeReplace(): AnyRef =
361
370
* new scala.runtime.ModuleSerializationProxy(classOf[Foo.type])
362
371
*
363
372
* unless an implementation already exists, otherwise do nothing.
364
373
*/
365
- def serializableObjectMethod (clazz : ClassSymbol )(using Context ): List [Tree ] = {
366
- def hasWriteReplace : Boolean =
367
- clazz.membersNamed(nme.writeReplace)
368
- .filterWithPredicate(s => s.signature == Signature (defn.AnyRefType , isJava = false ))
369
- .exists
370
- if (clazz.is(Module ) && clazz.isStatic && clazz.isSerializable && ! hasWriteReplace) {
371
- val writeReplace = newSymbol(clazz, nme.writeReplace, Method | Private | Synthetic ,
372
- MethodType (Nil , defn.AnyRefType ), coord = clazz.coord).entered.asTerm
374
+ def serializableObjectMethod (clazz : ClassSymbol )(using Context ): List [Tree ] =
375
+ if clazz.is(Module ) && clazz.isStatic && clazz.isSerializable && ! hasWriteReplace(clazz) then
373
376
List (
374
- DefDef (writeReplace ,
377
+ DefDef (writeReplaceDef(clazz) ,
375
378
_ => New (defn.ModuleSerializationProxyClass .typeRef,
376
379
defn.ModuleSerializationProxyConstructor ,
377
380
List (Literal (Constant (clazz.sourceModule.termRef)))))
378
381
.withSpan(ctx.owner.span.focus))
379
- }
380
382
else
381
383
Nil
382
- }
384
+
385
+ /** does this class extend `scala.runtime.EnumValue` and derive from an enum definition? */
386
+ extension (sym : ClassSymbol ) def isEnumValueImplementation (using Context ): Boolean =
387
+ derivesFrom(defn.EnumValueClass ) && classParents.exists(_.typeSymbol.flags.is(Enum ))
388
+
389
+ /** If this the class backing a serializable singleton enum value with base class `MyEnum`,
390
+ * and not deriving from `java.lang.Enum` add the method:
391
+ *
392
+ * private def writeReplace(): AnyRef =
393
+ * new scala.runtime.EnumValueSerializationProxy(classOf[MyEnum], this.ordinal)
394
+ *
395
+ * unless an implementation already exists, otherwise do nothing.
396
+ */
397
+ def serializableEnumValueMethod (clazz : ClassSymbol )(using Context ): List [Tree ] =
398
+ if clazz.isEnumValueImplementation
399
+ && ! clazz.derivesFrom(defn.JavaEnumClass )
400
+ && clazz.isSerializable
401
+ && ! hasWriteReplace(clazz)
402
+ then
403
+ List (
404
+ DefDef (writeReplaceDef(clazz),
405
+ _ => New (defn.EnumValueSerializationProxyClass .typeRef,
406
+ defn.EnumValueSerializationProxyConstructor ,
407
+ List (Literal (Constant (clazz.classParents.head)), This (clazz).select(nme.ordinal).ensureApplied)))
408
+ .withSpan(ctx.owner.span.focus))
409
+ else
410
+ Nil
383
411
384
412
/** The class
385
413
*
@@ -528,6 +556,6 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
528
556
def addSyntheticMembers (impl : Template )(using Context ): Template = {
529
557
val clazz = ctx.owner.asClass
530
558
addMirrorSupport(
531
- cpy.Template (impl)(body = serializableObjectMethod(clazz) ::: caseAndValueMethods(clazz) ::: impl.body))
559
+ cpy.Template (impl)(body = serializableObjectMethod(clazz) ::: serializableEnumValueMethod(clazz) ::: caseAndValueMethods(clazz) ::: impl.body))
532
560
}
533
561
}
0 commit comments