diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2012-08-06 19:37:07 +0200 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2012-08-06 23:09:33 +0200 |
commit | 7bcb9da47362ba862a695f7c82c0095a8205e3e2 (patch) | |
tree | f3434a982cb3104a1abc7f1fd3f4751f5e896da7 /src | |
parent | 3cbe07f3e3ddb7201d1d174399d14d4a69df52fd (diff) | |
download | scala-7bcb9da47362ba862a695f7c82c0095a8205e3e2.tar.gz scala-7bcb9da47362ba862a695f7c82c0095a8205e3e2.tar.bz2 scala-7bcb9da47362ba862a695f7c82c0095a8205e3e2.zip |
mirrors now support overriden fields and methods
Previously `checkMemberOf` was blocking base fields and methods
that are overriden in receiver.getClass. Now this is fixed.
The fix also uncovered an issue with field mirrors. Currently
their `get` and `set` methods don't respect overriding and always
return field values from a base class.
After discussing this on a reflection meeting, we decided that this
behavior is desirable and that for overriding people should use
reflectMethod and then apply on getters/setters. See the discussion at:
https://github.com/scala/scala/pull/1054.
Diffstat (limited to 'src')
-rw-r--r-- | src/reflect/scala/reflect/api/Mirrors.scala | 16 | ||||
-rw-r--r-- | src/reflect/scala/reflect/runtime/JavaMirrors.scala | 6 |
2 files changed, 21 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 41acd73492..8f69ab526b 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -33,6 +33,14 @@ trait Mirrors { self: Universe => /** Reflects against a field symbol and returns a mirror * that can be used to get and, if appropriate, set the value of the field. * + * FieldMirrors are the only way to get at private[this] vals and vars and + * might be useful to inspect the data of underlying Java fields. + * For all other uses, it's better to go through the fields accessor. + * + * In particular, there should be no need to ever access a field mirror + * when reflecting on just the public members of a class or trait. + * Note also that only accessor MethodMirrors, but not FieldMirrors will accurately reflect overriding behavior. + * * To get a field symbol by the name of the field you would like to reflect, * use `<this mirror>.symbol.typeSignature.member(newTermName(<name of the field>)).asTerm.accessed`. * For further information about member lookup refer to `Symbol.typeSignature`. @@ -107,6 +115,10 @@ trait Mirrors { self: Universe => * Scala reflection uses reflection capabilities of the underlying platform, * so `FieldMirror.get` might throw platform-specific exceptions associated * with getting a field or invoking a getter method of the field. + * + * If `symbol` represents a field of a base class with respect to the class of the receiver, + * and this base field is overriden in the class of the receiver, then this method will retrieve + * the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor. */ def get: Any @@ -117,6 +129,10 @@ trait Mirrors { self: Universe => * Scala reflection uses reflection capabilities of the underlying platform, * so `FieldMirror.get` might throw platform-specific exceptions associated * with setting a field or invoking a setter method of the field. + * + * If `symbol` represents a field of a base class with respect to the class of the receiver, + * and this base field is overriden in the class of the receiver, then this method will set + * the value of the base field. To achieve overriding behavior, use reflectMethod on an accessor. */ def set(value: Any): Unit } diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index f9407d5b1b..d671225c37 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -161,7 +161,11 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym } else if (wannabe.owner == AnyValClass) { if (!owner.isPrimitiveValueClass && !owner.isDerivedValueClass) ErrorNotMember(wannabe, owner) } else { - if (!owner.info.member(wannabe.name).alternatives.contains(wannabe)) ErrorNotMember(wannabe, owner) + def isMemberOf(wannabe: Symbol, owner: ClassSymbol): Boolean = { + val isNonShadowedMember = owner.info.member(wannabe.name).alternatives.contains(wannabe) + isNonShadowedMember || owner.info.baseClasses.tail.exists(base => isMemberOf(wannabe, base.asClass)) + } + if (!isMemberOf(wannabe, owner)) ErrorNotMember(wannabe, owner) } } |