Skip to content

Commit b1a0cdc

Browse files
committed
Implement bean property generation
1 parent e635705 commit b1a0cdc

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,8 @@ class Definitions {
890890

891891
// Annotation classes
892892
@tu lazy val AnnotationDefaultAnnot: ClassSymbol = requiredClass("scala.annotation.internal.AnnotationDefault")
893+
@tu lazy val BeanPropertyAnnot: ClassSymbol = requiredClass("scala.beans.BeanProperty")
894+
@tu lazy val BooleanBeanPropertyAnnot: ClassSymbol = requiredClass("scala.beans.BooleanBeanProperty")
893895
@tu lazy val BodyAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Body")
894896
@tu lazy val ChildAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Child")
895897
@tu lazy val ContextResultCountAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ContextResultCount")
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dotty.tools.dotc
2+
package transform
3+
4+
import core._
5+
import ast.tpd._
6+
import Contexts.Context
7+
import SymDenotations._
8+
import Symbols.newSymbol
9+
import Decorators._
10+
import Flags._
11+
import Names._
12+
import Types._
13+
14+
import DenotTransformers._
15+
16+
class BeanProperties(thisPhase: DenotTransformer):
17+
def addBeanMethods(impl: Template)(using Context): Template =
18+
val origBody = impl.body
19+
cpy.Template(impl)(body = impl.body.flatMap {
20+
case v: ValDef => generateAccessors(v)
21+
case _ => Nil
22+
} ::: origBody)
23+
24+
def generateAccessors(valDef: ValDef)(using Context): List[Tree] =
25+
import Symbols.defn
26+
27+
def generateGetter(valDef: ValDef)(using Context) : Tree =
28+
val prefix = if valDef.symbol.denot.hasAnnotation(defn.BooleanBeanPropertyAnnot) then "is" else "get"
29+
val meth = newSymbol(
30+
owner = summon[Context].owner,
31+
name = prefixedName(prefix, valDef.name),
32+
flags = Method | Permanent | Synthetic,
33+
info = MethodType(Nil, valDef.denot.info))
34+
.enteredAfter(thisPhase).asTerm
35+
meth.addAnnotations(valDef.symbol.annotations)
36+
val body: Tree = ref(valDef.symbol)
37+
DefDef(meth, body)
38+
39+
def maybeGenerateSetter(valDef: ValDef)(using Context): Option[Tree] =
40+
Option.when(valDef.denot.asSymDenotation.flags.is(Mutable)) {
41+
val owner = summon[Context].owner
42+
val meth = newSymbol(
43+
owner,
44+
name = prefixedName("set", valDef.name),
45+
flags = Method | Permanent | Synthetic,
46+
info = MethodType(valDef.name :: Nil, valDef.denot.info :: Nil, defn.UnitType)
47+
).enteredAfter(thisPhase).asTerm
48+
meth.addAnnotations(valDef.symbol.annotations)
49+
def body(params: List[List[Tree]]): Tree = Assign(ref(valDef.symbol), params.head.head)
50+
DefDef(meth, body)
51+
}
52+
53+
def prefixedName(prefix: String, valName: Name) =
54+
(prefix + valName.lastPart.toString.capitalize).toTermName
55+
56+
extension(a: SymDenotation) def isApplicable = a.hasAnnotation(defn.BeanPropertyAnnot) || a.hasAnnotation(defn.BooleanBeanPropertyAnnot)
57+
58+
if valDef.denot.symbol.isApplicable then
59+
generateGetter(valDef) +: maybeGenerateSetter(valDef) ++: Nil
60+
else Nil
61+
end generateAccessors

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
7575

7676
val superAcc: SuperAccessors = new SuperAccessors(thisPhase)
7777
val synthMbr: SyntheticMembers = new SyntheticMembers(thisPhase)
78+
val beanProps: BeanProperties = new BeanProperties(thisPhase)
7879

7980
private def newPart(tree: Tree): Option[New] = methPart(tree) match {
8081
case Select(nu: New, _) => Some(nu)
@@ -322,8 +323,10 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
322323
withNoCheckNews(templ.parents.flatMap(newPart)) {
323324
forwardParamAccessors(templ)
324325
synthMbr.addSyntheticMembers(
326+
beanProps.addBeanMethods(
325327
superAcc.wrapTemplate(templ)(
326328
super.transform(_).asInstanceOf[Template]))
329+
)
327330
}
328331
case tree: ValDef =>
329332
val tree1 = cpy.ValDef(tree)(rhs = normalizeErasedRhs(tree.rhs, tree.symbol))

0 commit comments

Comments
 (0)