summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-02-21 13:48:24 +0000
committerMartin Odersky <odersky@gmail.com>2011-02-21 13:48:24 +0000
commitebec4165292d9a8ec9b01b47ebd287964d205fd3 (patch)
treee08eb3605c2c8b2660274c96216a889016052a01
parenta765a6ff9497b7cd992c212e5d6660c79f9c2ee8 (diff)
downloadscala-ebec4165292d9a8ec9b01b47ebd287964d205fd3.tar.gz
scala-ebec4165292d9a8ec9b01b47ebd287964d205fd3.tar.bz2
scala-ebec4165292d9a8ec9b01b47ebd287964d205fd3.zip
Closes #4146.
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala94
1 files changed, 85 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index cc9990e0de..de22a50119 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -409,6 +409,67 @@ abstract class Constructors extends Transform with ast.TreeDSL {
case _ => false
}
*/
+
+ /** Create a getter or a setter and enter into `clazz` scope
+ */
+ def addAccessor(sym: Symbol, name: TermName, flags: Long) = {
+ val m = clazz.newMethod(sym.pos, name)
+ .setFlag(flags & ~LOCAL & ~PRIVATE)
+ m.privateWithin = clazz
+ clazz.info.decls.enter(m)
+ m
+ }
+
+ def addGetter(sym: Symbol): Symbol = {
+ val getr = addAccessor(
+ sym, nme.getterName(sym.name), getterFlags(sym.flags))
+ getr setInfo MethodType(List(), sym.tpe)
+ defBuf += localTyper.typed {
+ //util.trace("adding getter def for "+getr) {
+ atPos(sym.pos) {
+ DefDef(getr, Select(This(clazz), sym))
+ }//}
+ }
+ getr
+ }
+
+ def addSetter(sym: Symbol): Symbol = {
+ sym setFlag MUTABLE
+ val setr = addAccessor(
+ sym, nme.getterToSetter(nme.getterName(sym.name)), setterFlags(sym.flags))
+ setr setInfo MethodType(setr.newSyntheticValueParams(List(sym.tpe)), UnitClass.tpe)
+ defBuf += localTyper.typed {
+ //util.trace("adding setter def for "+setr) {
+ atPos(sym.pos) {
+ DefDef(setr, paramss =>
+ Assign(Select(This(clazz), sym), Ident(paramss.head.head)))
+ }//}
+ }
+ setr
+ }
+
+ def ensureAccessor(sym: Symbol)(acc: => Symbol) =
+ if (sym.owner == clazz && !sym.isMethod && sym.isPrivate) { // there's an access to a naked field of the enclosing class
+ var getr = acc
+ getr makeNotPrivate clazz
+ getr
+ } else {
+ if (sym.owner == clazz) sym makeNotPrivate clazz
+ NoSymbol
+ }
+
+ def ensureGetter(sym: Symbol): Symbol = ensureAccessor(sym) {
+ val getr = sym.getter(clazz)
+ if (getr != NoSymbol) getr else addGetter(sym)
+ }
+
+ def ensureSetter(sym: Symbol): Symbol = ensureAccessor(sym) {
+ var setr = sym.setter(clazz, hasExpandedName = false)
+ if (setr == NoSymbol) setr = sym.setter(clazz, hasExpandedName = true)
+ if (setr == NoSymbol) setr = addSetter(sym)
+ setr
+ }
+
def delayedInitClosure(stats: List[Tree]) =
localTyper.typed {
atPos(impl.pos) {
@@ -444,16 +505,31 @@ abstract class Constructors extends Transform with ast.TreeDSL {
}
}
case _ =>
- tree match {
- case Select(qual, _) =>
- val sym = tree.symbol
- sym makeNotPrivate sym.owner
- case Assign(lhs @ Select(_, _), _) =>
- lhs.symbol setFlag MUTABLE
- case _ =>
- changeOwner.changeOwner(tree)
+ super.transform {
+ tree match {
+ case Select(qual, _) =>
+ val getter = ensureGetter(tree.symbol)
+ if (getter != NoSymbol)
+ applyMethodTyper.typed {
+ atPos(tree.pos) {
+ Apply(Select(qual, getter), List())
+ }
+ }
+ else tree
+ case Assign(lhs @ Select(qual, _), rhs) =>
+ val setter = ensureSetter(lhs.symbol)
+ if (setter != NoSymbol)
+ applyMethodTyper.typed {
+ atPos(tree.pos) {
+ Apply(Select(qual, setter), List(rhs))
+ }
+ }
+ else tree
+ case _ =>
+ changeOwner.changeOwner(tree)
+ tree
+ }
}
- super.transform(tree)
}
}