@@ -15,6 +15,9 @@ import DenotTransformers._
1515import dotty .tools .dotc .ast .Trees ._
1616import SymUtils ._
1717
18+ import annotation .threadUnsafe
19+ import collection .mutable
20+
1821object CompleteJavaEnums {
1922 val name : String = " completeJavaEnums"
2023
@@ -40,10 +43,6 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
4043 sym == defn.JavaEnumClass .primaryConstructor ||
4144 sym.owner.derivesFromJavaEnum))
4245 addConstrParams(sym.info)
43- else if isJavaEnumValueImpl(sym) then
44- sym.asClass.delete(tp.decl(nme.toString_).symbol)
45- sym.asClass.delete(tp.decl(nme.ordinalDollar).symbol)
46- tp
4746 else tp
4847
4948 /** Add constructor parameters `$name: String` and `$ordinal: Int` to the end of
@@ -114,37 +113,42 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
114113
115114 private def isJavaEnumValueImpl (cls : Symbol )(using Context ): Boolean =
116115 cls.isAnonymousClass
117- && ((cls.owner.name eq nme.DOLLAR_NEW ) || cls.owner.isAllOf(EnumCase ))
118- && {
119- val enumCls = cls.owner.owner.linkedClass
120- enumCls.derivesFromJavaEnum && enumCls.is(Enum )
121- }
116+ && (((cls.owner.name eq nme.DOLLAR_NEW ) && cls.owner.isAllOf(Private | Synthetic )) || cls.owner.isAllOf(EnumCase ))
117+ && cls.owner.owner.linkedClass.derivesFromJavaEnum
118+
119+ @ threadUnsafe
120+ private lazy val enumCaseOrdinals : mutable.Map [Symbol , Int ] = mutable.AnyRefMap .empty
121+
122+ private def registerEnumClass (cls : Symbol )(using Context ): Unit =
123+ cls.children.zipWithIndex.foreach(enumCaseOrdinals.put)
124+
125+ private def ordinalFor (enumCase : Symbol ): Int = enumCaseOrdinals.remove(enumCase).get
122126
123127 /** 1. If this is an enum class, add $name and $ordinal parameters to its
124128 * parameter accessors and pass them on to the java.lang.Enum constructor.
125129 *
126- * 2. If this is an anonymous class that implement a value enum case,
130+ * 2. If this is an anonymous class that implement a singleton enum case,
127131 * pass $name and $ordinal parameters to the enum superclass. The class
128132 * looks like this:
129133 *
130134 * class $anon extends E(...) {
131135 * ...
132- * private def $ordinal = N
133- * override def toString = S
134- * ...
135136 * }
136137 *
137138 * After the transform it is expanded to
138139 *
139- * class $anon extends E(..., N, S) {
140- * ...
141- * "removed $ordinal and toString"
142- * ...
140+ * class $anon extends E(..., $name, _$ordinal) { // if class implements a simple enum case
141+ * "same as before"
142+ * }
143+ *
144+ * class $anon extends E(..., "A", 0) { // if class implements a value enum case `A` with ordinal 0
145+ * "same as before"
143146 * }
144147 */
145148 override def transformTemplate (templ : Template )(using Context ): Template = {
146149 val cls = templ.symbol.owner
147150 if cls.derivesFromJavaEnum then
151+ registerEnumClass(cls)
148152 val (params, rest) = decomposeTemplateBody(templ.body)
149153 val addedDefs = addedParams(cls, isLocal= true , ParamAccessor )
150154 val addedSyms = addedDefs.map(_.symbol.entered)
@@ -153,14 +157,15 @@ class CompleteJavaEnums extends MiniPhase with InfoTransformer { thisPhase =>
153157 parents = addEnumConstrArgs(defn.JavaEnumClass , templ.parents, addedSyms.map(ref)),
154158 body = params ++ addedDefs ++ addedForwarders ++ rest)
155159 else if isJavaEnumValueImpl(cls) then
156- def rhsOf (name : TermName ) =
157- templ.body.collect({ case mdef : DefDef if mdef.name == name => mdef.rhs }).head
158- def removeDefs (body : List [Tree ], names : TermName * ) =
159- body.filterNot { case ndef : DefDef => names.contains(ndef.name); case _ => false }
160- val args = List (rhsOf(nme.toString_), rhsOf(nme.ordinalDollar))
160+ def creatorParamRef (name : TermName ) =
161+ ref(cls.owner.paramSymss.head.find(_.name == name).get)
162+ val args =
163+ if cls.owner.isAllOf(EnumCase ) then
164+ List (Literal (Constant (cls.owner.name.toString)), Literal (Constant (ordinalFor(cls.owner))))
165+ else
166+ List (creatorParamRef(nme.nameDollar), creatorParamRef(nme.ordinalDollar_))
161167 cpy.Template (templ)(
162168 parents = addEnumConstrArgs(cls.owner.owner.linkedClass, templ.parents, args),
163- body = removeDefs(templ.body, nme.toString_, nme.ordinalDollar)
164169 )
165170 else templ
166171 }
0 commit comments