Skip to content

Commit 93fc31c

Browse files
committed
Simplification, do not generate methods if java
1 parent 7ee28d5 commit 93fc31c

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,18 @@ object DesugarEnums {
132132
* }
133133
*/
134134
private def enumValueCreator(using Context) = {
135-
val ordinalDef = ordinalMeth(Ident(nme.ordinalDollar_))
136-
val toStringDef = toStringMeth(Ident(nme.nameDollar))
135+
val fieldMethods =
136+
if isJavaEnum then Nil
137+
else
138+
val ordinalDef = ordinalMeth(Ident(nme.ordinalDollar_))
139+
val toStringDef = toStringMeth(Ident(nme.nameDollar))
140+
List(ordinalDef, toStringDef)
137141
val creator = New(Template(
138142
constr = emptyConstructor,
139143
parents = enumClassRef :: scalaRuntimeDot(tpnme.EnumValue) :: Nil,
140144
derived = Nil,
141145
self = EmptyValDef,
142-
body = List(ordinalDef, toStringDef) ++ registerCall
146+
body = fieldMethods ::: registerCall
143147
).withAttachment(ExtendsSingletonMirror, ()))
144148
DefDef(nme.DOLLAR_NEW, Nil,
145149
List(List(param(nme.ordinalDollar_, defn.IntType), param(nme.nameDollar, defn.StringType))),
@@ -265,10 +269,10 @@ object DesugarEnums {
265269
def param(name: TermName, typ: Type)(using Context) =
266270
ValDef(name, TypeTree(typ), EmptyTree).withFlags(Param)
267271

272+
private def isJavaEnum(using Context): Boolean = ctx.owner.linkedClass.derivesFrom(defn.JavaEnumClass)
273+
268274
def ordinalMeth(body: Tree)(using Context): DefDef =
269-
val isJEnum = ctx.owner.linkedClass.derivesFrom(defn.JavaEnumClass)
270-
val method = DefDef(if isJEnum then nme.ordinalDollar else nme.ordinal, Nil, Nil, TypeTree(defn.IntType), body)
271-
if isJEnum then method.withMods(Modifiers(Private)) else method
275+
DefDef(nme.ordinal, Nil, Nil, TypeTree(defn.IntType), body)
272276

273277
def toStringMeth(body: Tree)(using Context): DefDef =
274278
DefDef(nme.toString_, Nil, Nil, TypeTree(defn.StringType), body).withFlags(Override)
@@ -287,11 +291,15 @@ object DesugarEnums {
287291
expandSimpleEnumCase(name, mods, span)
288292
else {
289293
val (tag, scaffolding) = nextOrdinal(CaseKind.Object)
290-
val ordinalDef = ordinalMethLit(tag)
291-
val toStringDef = toStringMethLit(name.toString)
294+
val fieldMethods =
295+
if isJavaEnum then Nil
296+
else
297+
val ordinalDef = ordinalMethLit(tag)
298+
val toStringDef = toStringMethLit(name.toString)
299+
List(ordinalDef, toStringDef)
292300
val impl1 = cpy.Template(impl)(
293301
parents = impl.parents :+ scalaRuntimeDot(tpnme.EnumValue),
294-
body = List(ordinalDef, toStringDef) ++ registerCall)
302+
body = fieldMethods ::: registerCall)
295303
.withAttachment(ExtendsSingletonMirror, ())
296304
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods.withAddedFlags(EnumValue, span))
297305
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)

compiler/src/dotty/tools/dotc/transform/CompleteJavaEnums.scala

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import DenotTransformers._
1515
import dotty.tools.dotc.ast.Trees._
1616
import SymUtils._
1717

18+
import annotation.threadUnsafe
19+
import collection.mutable
20+
1821
object 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

Comments
 (0)