@@ -6,6 +6,7 @@ import Contexts.Context
6
6
import Symbols ._
7
7
import Flags ._
8
8
import Names ._
9
+ import NameOps ._
9
10
import Decorators ._
10
11
import TypeUtils ._
11
12
import Annotations .Annotation
@@ -23,9 +24,6 @@ abstract class AccessProxies {
23
24
import ast .tpd ._
24
25
import AccessProxies ._
25
26
26
- def getterName : ClassifiedNameKind
27
- def setterName : ClassifiedNameKind
28
-
29
27
/** accessor -> accessed */
30
28
private val accessedBy = newMutableSymbolMap[Symbol ]
31
29
@@ -38,7 +36,7 @@ abstract class AccessProxies {
38
36
polyDefDef(accessor.asTerm, tps => argss => {
39
37
val accessRef = ref(TermRef (cls.thisType, accessed))
40
38
val rhs =
41
- if (accessor.name.is(setterName) &&
39
+ if (accessor.name.isSetterName &&
42
40
argss.nonEmpty && argss.head.nonEmpty) // defensive conditions
43
41
accessRef.becomes(argss.head.head)
44
42
else
@@ -49,34 +47,60 @@ abstract class AccessProxies {
49
47
/** Add all needed accessors to the `body` of class `cls` */
50
48
def addAccessorDefs (cls : Symbol , body : List [Tree ])(implicit ctx : Context ): List [Tree ] = {
51
49
val accDefs = accessorDefs(cls)
50
+ transforms.println(i " add accessors for $cls: $accDefs%, % " )
52
51
if (accDefs.isEmpty) body else body ++ accDefs
53
52
}
54
53
55
54
trait Insert {
56
55
import ast .tpd ._
57
56
57
+ def accessorNameKind : ClassifiedNameKind
58
58
def needsAccessor (sym : Symbol )(implicit ctx : Context ): Boolean
59
59
60
60
/** A fresh accessor symbol */
61
- def newAccessorSymbol (owner : Symbol , name : TermName , info : Type , pos : Position )(implicit ctx : Context ): TermSymbol = {
61
+ private def newAccessorSymbol (owner : Symbol , name : TermName , info : Type , pos : Position )(implicit ctx : Context ): TermSymbol = {
62
62
val sym = ctx.newSymbol(owner, name, Synthetic | Method , info, coord = pos).entered
63
63
if (sym.allOverriddenSymbols.exists(! _.is(Deferred ))) sym.setFlag(Override )
64
64
sym
65
65
}
66
66
67
+ /** An accessor symbol, create a fresh one unless one exists already */
68
+ private def accessorSymbol (owner : Symbol , accessorName : TermName , accessorInfo : Type , accessed : Symbol )(implicit ctx : Context ) = {
69
+ def refersToAccessed (sym : Symbol ) = accessedBy.get(sym) == Some (accessed)
70
+ owner.info.decl(accessorName).suchThat(refersToAccessed).symbol.orElse {
71
+ val acc = newAccessorSymbol(owner, accessorName, accessorInfo, accessed.pos)
72
+ accessedBy(acc) = accessed
73
+ acc
74
+ }
75
+ }
76
+
77
+ /** Rewire reference to refer to `accessor` symbol */
78
+ private def rewire (reference : RefTree , accessor : Symbol )(implicit ctx : Context ): Tree = {
79
+ reference match {
80
+ case Select (qual, _) => qual.select(accessor)
81
+ case Ident (name) => ref(accessor)
82
+ }
83
+ }.withPos(reference.pos)
84
+
85
+ /** Given a reference to a getter accessor, the corresponding setter reference */
86
+ def useSetter (getterRef : RefTree )(implicit ctx : Context ): Tree = {
87
+ val getter = getterRef.symbol
88
+ val accessed = accessedBy(getter)
89
+ val accessedName = accessed.name.asTermName
90
+ val setterName = accessorNameKind(accessedName.setterName)
91
+ val setterInfo = MethodType (getter.info.widenExpr :: Nil , defn.UnitType )
92
+ val setter = accessorSymbol(getter.owner, setterName, setterInfo, accessed)
93
+ rewire(getterRef, setter)
94
+ }
95
+
67
96
/** Create an accessor unless one exists already, and replace the original
68
97
* access with a reference to the accessor.
69
98
*
70
99
* @param reference The original reference to the non-public symbol
71
100
* @param onLHS The reference is on the left-hand side of an assignment
72
101
*/
73
- def useAccessor (reference : RefTree , onLHS : Boolean )(implicit ctx : Context ): Tree = {
74
-
75
- def nameKind = if (onLHS) setterName else getterName
102
+ def useAccessor (reference : RefTree )(implicit ctx : Context ): Tree = {
76
103
val accessed = reference.symbol.asTerm
77
-
78
- def refersToAccessed (sym : Symbol ) = accessedBy.get(sym) == Some (accessed)
79
-
80
104
var accessorClass = hostForAccessorOf(accessed : Symbol )
81
105
if (! accessorClass.exists) {
82
106
val curCls = ctx.owner.enclosingClass
@@ -85,27 +109,11 @@ abstract class AccessProxies {
85
109
reference.pos)
86
110
accessorClass = curCls
87
111
}
88
-
89
- val accessorRawInfo =
90
- if (onLHS) MethodType (accessed.info :: Nil , defn.UnitType )
91
- else accessed.info.ensureMethodic
112
+ val accessorName = accessorNameKind(accessed.name)
92
113
val accessorInfo =
93
- accessorRawInfo.asSeenFrom(accessorClass.thisType, accessed.owner)
94
- val accessorName = nameKind(accessed.name)
95
-
96
- val accessorSymbol =
97
- accessorClass.info.decl(accessorName).suchThat(refersToAccessed).symbol
98
- .orElse {
99
- val acc = newAccessorSymbol(accessorClass, accessorName, accessorInfo, accessed.pos)
100
- accessedBy(acc) = accessed
101
- acc
102
- }
103
-
104
- { reference match {
105
- case Select (qual, _) => qual.select(accessorSymbol)
106
- case Ident (name) => ref(accessorSymbol)
107
- }
108
- }.withPos(reference.pos)
114
+ accessed.info.ensureMethodic.asSeenFrom(accessorClass.thisType, accessed.owner)
115
+ val accessor = accessorSymbol(accessorClass, accessorName, accessorInfo, accessed)
116
+ rewire(reference, accessor)
109
117
}
110
118
111
119
/** Replace tree with a reference to an accessor if needed */
@@ -115,15 +123,16 @@ abstract class AccessProxies {
115
123
ctx.error(" Implementation restriction: cannot use private constructors in inline methods" , tree.pos)
116
124
tree // TODO: create a proper accessor for the private constructor
117
125
}
118
- else useAccessor(tree, onLHS = false )
119
- case Assign (lhs : RefTree , rhs) if needsAccessor(lhs.symbol) =>
120
- cpy.Apply (tree)(useAccessor(lhs, onLHS = true ), List (rhs))
126
+ else useAccessor(tree)
121
127
case _ =>
122
128
tree
123
129
}
124
130
}
125
131
}
126
132
object AccessProxies {
133
+ /** Where an accessor for the `accessed` symbol should be placed.
134
+ * This is the closest enclosing class that has `accessed` as a member.
135
+ */
127
136
def hostForAccessorOf (accessed : Symbol )(implicit ctx : Context ): Symbol =
128
137
ctx.owner.ownersIterator.findSymbol(_.derivesFrom(accessed.owner))
129
- }
138
+ }
0 commit comments