Skip to content
Permalink
Browse files

fixes some issues with reflectField brought up today

  • Loading branch information
xeno-by committed Jun 7, 2012
1 parent 178069e commit 0c153ee15e714e0ca8752151012b8f1fa9642983
@@ -128,20 +128,41 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
extends InstanceMirror {
def instance = obj
def reflectClass = wholemirror.reflectClass(obj.getClass)
def reflectField(field: TermSymbol): FieldMirror = new JavaFieldMirror(obj, field)
def reflectField(field: TermSymbol): FieldMirror = {
if (field.isMethod || field.isModule) throw new Error(s"""
|expected a field symbol, you provided a ${field.kind} symbol
|A typical cause of this problem is using a field accessor symbol instead of a field symbol.
|To obtain a field symbol append nme.LOCAL_SUFFIX_STRING to the name of the field,
|when searching for a member with Type.members or Type.declarations.
|This is a temporary inconvenience that will be resolved before 2.10.0-final.
|More information can be found here: https://issues.scala-lang.org/browse/SI-5895.
""".trim.stripMargin)
new JavaFieldMirror(obj, field)
}
def reflectMethod(method: MethodSymbol): MethodMirror = new JavaMethodMirror(obj, method)
}

private class JavaFieldMirror(val receiver: AnyRef, val field: TermSymbol)
extends FieldMirror {
lazy val jfield = fieldToJava(field)
lazy val jfield = {
val jfield = fieldToJava(field)
if (!jfield.isAccessible) jfield.setAccessible(true)
jfield
}
def get = jfield.get(receiver)
def set(value: Any) = jfield.set(receiver, value)
def set(value: Any) = {
if (!field.isMutable) throw new Error("cannot set an immutable field")
jfield.set(receiver, value)
}
}

private class JavaMethodMirror(val receiver: AnyRef, val method: MethodSymbol)
extends MethodMirror {
lazy val jmeth = methodToJava(method)
lazy val jmeth = {
val jmeth = methodToJava(method)
if (!jmeth.isAccessible) jmeth.setAccessible(true)
jmeth
}
def apply(args: Any*): Any =
if (method.owner == ArrayClass)
method.name match {
@@ -157,7 +178,11 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
private class JavaConstructorMirror(val method: MethodSymbol)
extends MethodMirror {
override val receiver = null
lazy val jconstr = constructorToJava(method)
lazy val jconstr = {
val jconstr = constructorToJava(method)
if (!jconstr.isAccessible) jconstr.setAccessible(true)
jconstr
}
def apply(args: Any*): Any = jconstr.newInstance(args.asInstanceOf[Seq[AnyRef]]: _*)
}

@@ -877,7 +902,8 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
*/
def fieldToJava(fld: TermSymbol): jField = fieldCache.toJava(fld) {
val jclazz = classToJava(fld.owner.asClassSymbol)
try jclazz getDeclaredField fld.name.toString
val jname = nme.dropLocalSuffix(fld.name).toString
try jclazz getDeclaredField jname
catch {
case ex: NoSuchFieldException => jclazz getDeclaredField expandedName(fld)
}
@@ -889,7 +915,8 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
def methodToJava(meth: MethodSymbol): jMethod = methodCache.toJava(meth) {
val jclazz = classToJava(meth.owner.asClassSymbol)
val paramClasses = transformedType(meth).paramTypes map typeToJavaClass
try jclazz getDeclaredMethod (meth.name.toString, paramClasses: _*)
val jname = nme.dropLocalSuffix(meth.name).toString
try jclazz getDeclaredMethod (jname, paramClasses: _*)
catch {
case ex: NoSuchMethodException =>
jclazz getDeclaredMethod (expandedName(meth), paramClasses: _*)
@@ -0,0 +1 @@
class java.lang.NoSuchFieldException: Test$A$$x
@@ -0,0 +1,21 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
class A(x: Int) {
private[this] var xx = x
}

val a = new A(42)

val im: InstanceMirror = cm.reflect(a)
val cs = im.reflectClass.symbol
val f = cs.typeSignature.declaration(newTermName("x")).asTermSymbol
try {
val fm: FieldMirror = im.reflectField(f)
println(fm.get)
} catch {
case ex: Throwable =>
println(s"${ex.getClass}: ${ex.getMessage}")
}
}
@@ -0,0 +1,2 @@
42
cannot set an immutable field
@@ -0,0 +1,24 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
class A {
val x: Int = 42
}

val a = new A

val im: InstanceMirror = cm.reflect(a)
val cs = im.reflectClass.symbol
val f = cs.typeSignature.declaration(newTermName("x" + nme.LOCAL_SUFFIX_STRING)).asTermSymbol
val fm: FieldMirror = im.reflectField(f)
try {
println(fm.get)
fm.set(2)
println(fm.get)
println("this indicates a failure")
} catch {
case ex: Throwable =>
println(ex.getMessage)
}
}
@@ -0,0 +1,2 @@
42
2
@@ -0,0 +1,18 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
class A {
var x: Int = 42
}

val a = new A

val im: InstanceMirror = cm.reflect(a)
val cs = im.reflectClass.symbol
val f = cs.typeSignature.declaration(newTermName("x" + nme.LOCAL_SUFFIX_STRING)).asTermSymbol
val fm: FieldMirror = im.reflectField(f)
println(fm.get)
fm.set(2)
println(fm.get)
}
@@ -0,0 +1 @@
true
@@ -0,0 +1,16 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
class A {
var x: Int = 42
}

val a = new A

val im: InstanceMirror = cm.reflect(a)
val cs = im.reflectClass.symbol
val f = cs.typeSignature.declaration(newTermName("x" + nme.LOCAL_SUFFIX_STRING)).asTermSymbol
val fm: FieldMirror = im.reflectField(f)
println(fm.field.isVariable)
}
@@ -0,0 +1,3 @@
true
42
2
@@ -0,0 +1,19 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
class A {
private[this] var x: Int = 42
}

val a = new A

val im: InstanceMirror = cm.reflect(a)
val cs = im.reflectClass.symbol
val f = cs.typeSignature.declaration(newTermName("x")).asTermSymbol
val fm: FieldMirror = im.reflectField(f)
println(fm.field.isVariable)
println(fm.get)
fm.set(2)
println(fm.get)
}
@@ -0,0 +1,6 @@
expected a field symbol, you provided a method symbol
A typical cause of this problem is using a field accessor symbol instead of a field symbol.
To obtain a field symbol append nme.LOCAL_SUFFIX_STRING to the name of the field,
when searching for a member with Type.members or Type.declarations.
This is a temporary inconvenience that will be resolved before 2.10.0-final.
More information can be found here: https://issues.scala-lang.org/browse/SI-5895.
@@ -0,0 +1,22 @@
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
class A {
var x: Int = 42
}

val a = new A

val im: InstanceMirror = cm.reflect(a)
val cs = im.reflectClass.symbol
//val f = cs.typeSignature.declaration(newTermName("x" + nme.LOCAL_SUFFIX_STRING)).asTermSymbol
val f = cs.typeSignature.declaration(newTermName("x")).asTermSymbol
try {
val fm: FieldMirror = im.reflectField(f)
println("this indicates a failure")
} catch {
case ex: Throwable =>
println(ex.getMessage)
}
}

0 comments on commit 0c153ee

Please sign in to comment.
You can’t perform that action at this time.