@@ -23,8 +23,9 @@ import ValueClasses.isDerivedValueClass
23
23
* def productArity: Int
24
24
* def productPrefix: String
25
25
*
26
- * Special handling:
27
- * protected def readResolve(): AnyRef
26
+ * Add to serializable static objects, unless an implementation
27
+ * already exists:
28
+ * private def writeReplace(): AnyRef
28
29
*
29
30
* Selectively added to value classes, unless a non-default
30
31
* implementation already exists:
@@ -50,8 +51,10 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
50
51
def caseSymbols (implicit ctx : Context ): List [Symbol ] = { initSymbols; myCaseSymbols }
51
52
def caseModuleSymbols (implicit ctx : Context ): List [Symbol ] = { initSymbols; myCaseModuleSymbols }
52
53
53
- /** The synthetic methods of the case or value class `clazz`. */
54
- def syntheticMethods (clazz : ClassSymbol )(implicit ctx : Context ): List [Tree ] = {
54
+ /** If this is a case or value class, return the appropriate additional methods,
55
+ * otherwise return nothing.
56
+ */
57
+ def caseAndValueMethods (clazz : ClassSymbol )(implicit ctx : Context ): List [Tree ] = {
55
58
val clazzType = clazz.appliedRef
56
59
lazy val accessors =
57
60
if (isDerivedValueClass(clazz)) clazz.paramAccessors.take(1 ) // Tail parameters can only be `erased`
@@ -255,12 +258,38 @@ class SyntheticMethods(thisPhase: DenotTransformer) {
255
258
*/
256
259
def canEqualBody (that : Tree ): Tree = that.isInstance(AnnotatedType (clazzType, Annotation (defn.UncheckedAnnot )))
257
260
258
- symbolsToSynthesize flatMap syntheticDefIfMissing
261
+ symbolsToSynthesize. flatMap( syntheticDefIfMissing)
259
262
}
260
263
261
- def addSyntheticMethods (impl : Template )(implicit ctx : Context ): Template =
262
- if (ctx.owner.is(Case ) || isDerivedValueClass(ctx.owner))
263
- cpy.Template (impl)(body = impl.body ++ syntheticMethods(ctx.owner.asClass))
264
+ /** If this is a serializable static object `Foo`, add the method:
265
+ *
266
+ * private def writeReplace(): AnyRef =
267
+ * new scala.runtime.ModuleSerializationProxy(classOf[Foo.type])
268
+ *
269
+ * unless an implementation already exists, otherwise do nothing.
270
+ */
271
+ def serializableObjectMethod (clazz : ClassSymbol )(implicit ctx : Context ): List [Tree ] = {
272
+ def hasWriteReplace : Boolean =
273
+ clazz.membersNamed(nme.writeReplace)
274
+ .filterWithPredicate(s => s.signature == Signature (defn.AnyRefType , isJava = false ))
275
+ .exists
276
+ if (clazz.is(Module ) && clazz.isStatic && clazz.isSerializable && ! hasWriteReplace) {
277
+ val writeReplace = ctx.newSymbol(clazz, nme.writeReplace, Method | Private | Synthetic ,
278
+ MethodType (Nil , defn.AnyRefType ), coord = clazz.coord).entered.asTerm
279
+ List (
280
+ DefDef (writeReplace,
281
+ _ => New (defn.ModuleSerializationProxyType ,
282
+ defn.ModuleSerializationProxyConstructor ,
283
+ List (Literal (Constant (clazz.sourceModule.termRef)))))
284
+ .withSpan(ctx.owner.span.focus))
285
+ }
264
286
else
265
- impl
287
+ Nil
288
+ }
289
+
290
+ def addSyntheticMethods (impl : Template )(implicit ctx : Context ): Template = {
291
+ val clazz = ctx.owner.asClass
292
+ cpy.Template (impl)(body = serializableObjectMethod(clazz) ::: caseAndValueMethods(clazz) ::: impl.body)
293
+ }
294
+
266
295
}
0 commit comments