From bab827a5426aeb654006573712eb7aabc047db36 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Wed, 11 Jul 2012 14:46:01 +0200 Subject: SI-5895 fixes FieldMirrors reflectField now accepts getters and setters along with the field symbols, it also checks whether a field has a reasonable binary representation (this is necessary, because ctor parameters that are unused outside of their declaring constructors don't get compiled down to Java fields/methods). --- .../scala/reflect/runtime/JavaMirrors.scala | 25 ++++++++++++++-------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 185621efa4..1c5ea9caba 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -133,15 +133,22 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym def symbol = wholemirror.classSymbol(obj.getClass) def reflectField(field: TermSymbol): FieldMirror = { // [Eugene+++] check whether `field` represents a member of a `symbol` - 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) + if ((field.isMethod && !field.isAccessor) || field.isModule) throw new Error(s"expected a field or accessor method symbol, you provided a ${field.kind} symbol") + val name = + if (field.isGetter) nme.getterToLocal(field.name) + else if (field.isSetter) nme.getterToLocal(nme.setterToGetter(field.name)) + else field.name + val field1 = (field.owner.info decl name).asTermSymbol + try fieldToJava(field1) + catch { + case _: NoSuchFieldException => + throw new Error(s""" + |this Scala field isn't represented as a Java field, neither it has a Java accessor method + |note that private parameters of class constructors don't get mapped onto fields and/or accessors, + |unless they are used outside of their declaring constructors. + """.trim.stripMargin) + } + new JavaFieldMirror(obj, field1) } def reflectMethod(method: MethodSymbol): MethodMirror = { // [Eugene+++] check whether `method` represents a member of a `symbol` -- cgit v1.2.3 From 911bbc4fdd889ea8a880b4ae47a490f64c54a2a9 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 17 Jul 2012 17:54:41 +0200 Subject: SI-5984 improves error reporting in JavaMirrors Factors out error raising code and introduces a special exception class for Scala reflection errors. Also adds membership sanity checks to reflectXXX. Previously reflectField, reflectMethod, reflectClass and reflectModule in InstanceMirror didn't check that the symbols being passed to them actually correspond to some member of the related class. --- src/library/scala/reflect/package.scala | 3 ++ .../scala/reflect/runtime/JavaMirrors.scala | 45 ++++++++++++++-------- ...eflection-constructormirror-inner-badpath.check | 2 +- ...flection-constructormirror-nested-badpath.check | 2 +- ...ection-constructormirror-toplevel-badpath.check | 2 +- .../run/reflection-fieldmirror-ctorparam.check | 2 +- .../run/reflection-fieldmirror-getsetval.check | 2 +- .../reflection-modulemirror-inner-badpath.check | 4 +- .../reflection-modulemirror-nested-badpath.check | 4 +- .../reflection-modulemirror-toplevel-badpath.check | 4 +- test/files/run/reflection-sanitychecks.check | 8 ++++ test/files/run/reflection-sanitychecks.scala | 30 +++++++++++++++ 12 files changed, 80 insertions(+), 28 deletions(-) create mode 100644 test/files/run/reflection-sanitychecks.check create mode 100644 test/files/run/reflection-sanitychecks.scala (limited to 'src/reflect') diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index 9f9d4089c4..d97f2ec633 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -65,3 +65,6 @@ package object reflect { @deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0") type ScalaBeanInfo = scala.beans.ScalaBeanInfo } + +/** An exception that indicates an error during Scala reflection */ +case class ScalaReflectionException(msg: String) extends Exception(msg) diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 1c5ea9caba..e7bebd624c 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -107,15 +107,28 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym // ----------- Implementations of mirror operations and classes ------------------- + private def ErrorInnerClass(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror") + private def ErrorInnerModule(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror") + private def ErrorStaticClass(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror") + private def ErrorStaticModule(wannabe: Symbol) = throw new ScalaReflectionException(s"$wannabe is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror") + private def ErrorNotMember(wannabe: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a member of $owner, you provided ${wannabe.kind} ${wannabe.fullName}") + private def ErrorNotField(wannabe: Symbol) = throw new ScalaReflectionException(s"expected a field or an accessor method symbol, you provided $wannabe}") + private def ErrorNonExistentField(wannabe: Symbol) = throw new ScalaReflectionException(s""" + |Scala field ${wannabe.name} isn't represented as a Java field, neither it has a Java accessor method + |note that private parameters of class constructors don't get mapped onto fields and/or accessors, + |unless they are used outside of their declaring constructors. + """.trim.stripMargin) + private def ErrorSetImmutableField(wannabe: Symbol) = throw new ScalaReflectionException(s"cannot set an immutable field ${wannabe.name}") + def reflect(obj: Any): InstanceMirror = new JavaInstanceMirror(obj.asInstanceOf[AnyRef]) def reflectClass(cls: ClassSymbol): ClassMirror = { - if (!cls.isStatic) throw new Error("this is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror") + if (!cls.isStatic) ErrorInnerClass(cls) new JavaClassMirror(null, cls) } def reflectModule(mod: ModuleSymbol): ModuleMirror = { - if (!mod.isStatic) throw new Error("this is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror") + if (!mod.isStatic) ErrorInnerModule(mod) new JavaModuleMirror(null, mod) } @@ -127,13 +140,16 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol = classToScala(rtcls).companionModule.asModuleSymbol + private def checkMemberOf(wannabe: Symbol, owner: Symbol) = + if (!owner.info.member(wannabe.name).alternatives.contains(wannabe)) ErrorNotMember(wannabe, owner) + private class JavaInstanceMirror(obj: AnyRef) extends InstanceMirror { def instance = obj def symbol = wholemirror.classSymbol(obj.getClass) def reflectField(field: TermSymbol): FieldMirror = { - // [Eugene+++] check whether `field` represents a member of a `symbol` - if ((field.isMethod && !field.isAccessor) || field.isModule) throw new Error(s"expected a field or accessor method symbol, you provided a ${field.kind} symbol") + checkMemberOf(field, symbol) + if ((field.isMethod && !field.isAccessor) || field.isModule) ErrorNotField(field) val name = if (field.isGetter) nme.getterToLocal(field.name) else if (field.isSetter) nme.getterToLocal(nme.setterToGetter(field.name)) @@ -141,27 +157,22 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym val field1 = (field.owner.info decl name).asTermSymbol try fieldToJava(field1) catch { - case _: NoSuchFieldException => - throw new Error(s""" - |this Scala field isn't represented as a Java field, neither it has a Java accessor method - |note that private parameters of class constructors don't get mapped onto fields and/or accessors, - |unless they are used outside of their declaring constructors. - """.trim.stripMargin) + case _: NoSuchFieldException => ErrorNonExistentField(field1) } new JavaFieldMirror(obj, field1) } def reflectMethod(method: MethodSymbol): MethodMirror = { - // [Eugene+++] check whether `method` represents a member of a `symbol` + checkMemberOf(method, symbol) new JavaMethodMirror(obj, method) } def reflectClass(cls: ClassSymbol): ClassMirror = { - // [Eugene+++] check whether `cls` represents a member of a `symbol` - if (cls.isStatic) throw new Error("this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror") + if (cls.isStatic) ErrorStaticClass(cls) + checkMemberOf(cls, symbol) new JavaClassMirror(instance, cls) } def reflectModule(mod: ModuleSymbol): ModuleMirror = { - // [Eugene+++] check whether `mod` represents a member of a `symbol` - if (mod.isStatic) throw new Error("this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror") + if (mod.isStatic) ErrorStaticModule(mod) + checkMemberOf(mod, symbol) new JavaModuleMirror(instance, mod) } } @@ -175,7 +186,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym } def get = jfield.get(receiver) def set(value: Any) = { - if (!symbol.isMutable) throw new Error("cannot set an immutable field") + if (!symbol.isMutable) ErrorSetImmutableField(symbol) jfield.set(receiver, value) } } @@ -193,7 +204,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym case nme.length => jArray.getLength(receiver) case nme.apply => jArray.get(receiver, args(0).asInstanceOf[Int]) case nme.update => jArray.set(receiver, args(0).asInstanceOf[Int], args(1)) - case _ => throw new Error(s"unexpected array method $symbol") + case _ => assert(false, s"unexpected array method: $symbol") } else jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*) diff --git a/test/files/run/reflection-constructormirror-inner-badpath.check b/test/files/run/reflection-constructormirror-inner-badpath.check index 28b936eca1..2fb0610ad6 100644 --- a/test/files/run/reflection-constructormirror-inner-badpath.check +++ b/test/files/run/reflection-constructormirror-inner-badpath.check @@ -1,2 +1,2 @@ -this is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror +class R is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror () diff --git a/test/files/run/reflection-constructormirror-nested-badpath.check b/test/files/run/reflection-constructormirror-nested-badpath.check index 9ceb603dc2..acd21df9c0 100644 --- a/test/files/run/reflection-constructormirror-nested-badpath.check +++ b/test/files/run/reflection-constructormirror-nested-badpath.check @@ -1,2 +1,2 @@ -this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror +class R is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror () diff --git a/test/files/run/reflection-constructormirror-toplevel-badpath.check b/test/files/run/reflection-constructormirror-toplevel-badpath.check index 9ceb603dc2..acd21df9c0 100644 --- a/test/files/run/reflection-constructormirror-toplevel-badpath.check +++ b/test/files/run/reflection-constructormirror-toplevel-badpath.check @@ -1,2 +1,2 @@ -this is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror +class R is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror () diff --git a/test/files/run/reflection-fieldmirror-ctorparam.check b/test/files/run/reflection-fieldmirror-ctorparam.check index 7ae2cec81e..31f6491b14 100644 --- a/test/files/run/reflection-fieldmirror-ctorparam.check +++ b/test/files/run/reflection-fieldmirror-ctorparam.check @@ -1,3 +1,3 @@ -class java.lang.Error: this Scala field isn't represented as a Java field, neither it has a Java accessor method +class scala.ScalaReflectionException: Scala field x isn't represented as a Java field, neither it has a Java accessor method note that private parameters of class constructors don't get mapped onto fields and/or accessors, unless they are used outside of their declaring constructors. diff --git a/test/files/run/reflection-fieldmirror-getsetval.check b/test/files/run/reflection-fieldmirror-getsetval.check index 707bbcccce..e1927f68d0 100644 --- a/test/files/run/reflection-fieldmirror-getsetval.check +++ b/test/files/run/reflection-fieldmirror-getsetval.check @@ -1,2 +1,2 @@ 42 -cannot set an immutable field +cannot set an immutable field x diff --git a/test/files/run/reflection-modulemirror-inner-badpath.check b/test/files/run/reflection-modulemirror-inner-badpath.check index d3fe43336e..1e990ec900 100644 --- a/test/files/run/reflection-modulemirror-inner-badpath.check +++ b/test/files/run/reflection-modulemirror-inner-badpath.check @@ -1,2 +1,2 @@ -this is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror -() +object R is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror +() diff --git a/test/files/run/reflection-modulemirror-nested-badpath.check b/test/files/run/reflection-modulemirror-nested-badpath.check index 16a5b10390..f7980b9986 100644 --- a/test/files/run/reflection-modulemirror-nested-badpath.check +++ b/test/files/run/reflection-modulemirror-nested-badpath.check @@ -1,2 +1,2 @@ -this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror -() +object R is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror +() diff --git a/test/files/run/reflection-modulemirror-toplevel-badpath.check b/test/files/run/reflection-modulemirror-toplevel-badpath.check index 16a5b10390..f7980b9986 100644 --- a/test/files/run/reflection-modulemirror-toplevel-badpath.check +++ b/test/files/run/reflection-modulemirror-toplevel-badpath.check @@ -1,2 +1,2 @@ -this is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror -() +object R is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror +() diff --git a/test/files/run/reflection-sanitychecks.check b/test/files/run/reflection-sanitychecks.check new file mode 100644 index 0000000000..d977e0ed66 --- /dev/null +++ b/test/files/run/reflection-sanitychecks.check @@ -0,0 +1,8 @@ +field: 1 +method: 2 +class: CC +object: java.lang.Error: inner and nested modules are not supported yet +field: scala.ScalaReflectionException: expected a member of class C, you provided value D.foo +method: scala.ScalaReflectionException: expected a member of class C, you provided method D.bar +class: scala.ScalaReflectionException: expected a member of class C, you provided class D.C +object: scala.ScalaReflectionException: expected a member of class C, you provided object D.O diff --git a/test/files/run/reflection-sanitychecks.scala b/test/files/run/reflection-sanitychecks.scala new file mode 100644 index 0000000000..a6a24088a4 --- /dev/null +++ b/test/files/run/reflection-sanitychecks.scala @@ -0,0 +1,30 @@ +class C { + val foo = 1 + def bar = 2 + class C { override def toString = "CC" } + object O { override def toString = "CO" } +} + +class D { + val foo = 3 + def bar = 4 + class C { override def toString = "DC" } + object O { override def toString = "DO" } +} + +object Test extends App { + import scala.reflect.runtime.universe._ + import scala.reflect.runtime.{currentMirror => cm} + val im = cm.reflect(new C) + + def test(tpe: Type): Unit = { + def failsafe(action: => Any): Any = try action catch { case ex: Throwable => ex.toString } + println("field: " + failsafe(im.reflectField(tpe.member(newTermName("foo")).asTermSymbol).get)) + println("method: " + failsafe(im.reflectMethod(tpe.member(newTermName("bar")).asMethodSymbol)())) + println("class: " + failsafe(im.reflectClass(tpe.member(newTypeName("C")).asClassSymbol).reflectConstructor(typeOf[C].member(newTypeName("C")).asClassSymbol.typeSignature.member(newTermName("")).asMethodSymbol)())) + println("object: " + failsafe(im.reflectModule(tpe.member(newTermName("O")).asModuleSymbol).instance)) + } + + test(typeOf[C]) + test(typeOf[D]) +} \ No newline at end of file -- cgit v1.2.3 From baf3d1a2516e69660cd9a3d6ea3120327885fe93 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Tue, 17 Jul 2012 16:04:18 +0200 Subject: improves docs of scala.reflect.api.Mirrors --- src/reflect/scala/reflect/api/Mirrors.scala | 144 +++++++++++++++++++++------- 1 file changed, 110 insertions(+), 34 deletions(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala index 348ab3656b..27176a2a2d 100644 --- a/src/reflect/scala/reflect/api/Mirrors.scala +++ b/src/reflect/scala/reflect/api/Mirrors.scala @@ -27,28 +27,63 @@ trait Mirrors { self: Universe => /** The instance value reflected by this mirror */ def instance: Any - /** The symbol corresponding to the run-time class of the reflected instance. */ + /** The symbol corresponding to the run-time class of the reflected instance */ def symbol: ClassSymbol - /** Get value of field in reflected instance. - * @field A field symbol that should represent a field of the instance class. - * @return The value associated with that field in the reflected instance - * @throws ??? + /** Reflects against a field symbol and returns a mirror + * that can be used to get and, if appropriate, set the value of the field. + * + * To get a field symbol by the name of the field you would like to reflect, + * use `.symbol.typeSignature.member(newTermName()).asTermSymbol`. + * For further information about member lookup refer to `Symbol.typeSignature`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be a member (declared or inherited) of the class of the instance underlying this mirror. + * + * The input symbol can represent either a field itself or one of the corresponding accessors + * (in all cases the resulting mirror will refer to the field symbol). + * + * If a field symbol doesn't correspond to a reflectable entity of the underlying platform, + * a `ScalaReflectionException` exception will be thrown. This might happen, for example, for primary constructor parameters. + * Typically they produce class fields, however, private parameters that aren't used outside the constructor + * remain plain parameters of a constructor method of the class. */ def reflectField(field: TermSymbol): FieldMirror - /** Invokes a method on the reflected instance. - * @param meth A method symbol that should represent a method of the instance class - * @param args The arguments to pass to the method - * @return The result of invoking `meth(args)` on the reflected instance. - * @throws ??? + /** Reflects against a method symbol and returns a mirror + * that can be used to invoke the method provided. + * + * To get a method symbol by the name of the method you would like to reflect, + * use `.symbol.typeSignature.member(newTermName()).asMethodSymbol`. + * For further information about member lookup refer to `Symbol.typeSignature`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be a member (declared or inherited) of the instance underlying this mirror. */ def reflectMethod(method: MethodSymbol): MethodMirror - /** .. */ + /** Reflects against an inner class symbol and returns a mirror + * that can be used to create instances of the class, inspect its companion object or perform further reflections. + * + * To get a class symbol by the name of the class you would like to reflect, + * use `.symbol.typeSignature.member(newTypeName()).asClassSymbol`. + * For further information about member lookup refer to `Symbol.typeSignature`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be a member (declared or inherited) of the instance underlying this mirror. + */ def reflectClass(cls: ClassSymbol): ClassMirror - /** .. */ + /** Reflects against an inner module symbol and returns a mirror + * that can be used to get the instance of the object or inspect its companion class. + * + * To get a module symbol by the name of the object you would like to reflect, + * use `.symbol.typeSignature.member(newTermName()).asModuleSymbol`. + * For further information about member lookup refer to `Symbol.typeSignature`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be a member (declared or inherited) of the instance underlying this mirror. + */ def reflectModule(mod: ModuleSymbol): ModuleMirror } @@ -58,13 +93,31 @@ trait Mirrors { self: Universe => /** The object containing the field */ def receiver: AnyRef - /** The field symbol representing the field */ + /** The field symbol representing the field. + * + * In Scala `val` and `var` declarations are usually compiled down to a pair of + * a backing field and corresponding accessor/accessors, which means that a single + * declaration might correspond to up to three different symbols. Nevertheless + * the `FieldMirror.symbol` field always points to a backing field symbol. + */ def symbol: TermSymbol - /** Retrieves the value stored in the field */ + /** Retrieves the value stored in the field. + * + * 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. + */ def get: Any - /** Updates the value stored in the field */ + /** Updates the value stored in the field. + * + * If a field is immutable, a `ScalaReflectionException` will be thrown. + * + * 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. + */ def set(value: Any): Unit } @@ -77,8 +130,12 @@ trait Mirrors { self: Universe => /** The method symbol representing the method */ def symbol: MethodSymbol - /** The result of applying the method to the given arguments */ - // [Eugene+++] If it's a constructor, it should account for inner classes + /** The result of applying the method to the given arguments + * + * Scala reflection uses reflection capabilities of the underlying platform, + * so `FieldMirror.get` might throw platform-specific exceptions associated + * with invoking the corresponding method or constructor. + */ def apply(args: Any*): Any } @@ -97,7 +154,7 @@ trait Mirrors { self: Universe => */ def isStatic: Boolean - /** The Scala symbol corresponding to the reflected runtime class or module. */ + /** The Scala symbol corresponding to the reflected runtime class or object */ def symbol: Symbol /** Optionally, the mirror of the companion reflected by this mirror. @@ -116,7 +173,7 @@ trait Mirrors { self: Universe => /** A mirror that reflects a Scala object definition or the static parts of a runtime class */ trait ModuleMirror extends TemplateMirror { - /** The Scala module symbol corresponding to the reflected module. */ + /** The Scala module symbol corresponding to the reflected object */ override def symbol: ModuleSymbol /** If the reflected runtime class corresponds to a Scala object definition, @@ -137,15 +194,18 @@ trait Mirrors { self: Universe => /** A mirror that reflects the instance parts of a runtime class */ trait ClassMirror extends TemplateMirror { - /** The Scala class symbol corresponding to the reflected class. */ + /** The Scala class symbol corresponding to the reflected class */ override def symbol: ClassSymbol - /** Returns a fresh instance of by invoking that constructor. - * @throws InstantiationException if the class does not have a public - * constructor with an empty parameter list. - * @throws IllegalAccessException if the class or its constructor is not accessible. - * @throws ExceptionInInitializerError if the initialization of the constructor fails. - * @throws SecurityException if creating a new instance is not permitted. + /** Reflects against a constructor symbol and returns a mirror + * that can be used to invoke it and construct instances of this mirror's symbols. + * + * To get a constructor symbol you would like to reflect, + * use `.symbol.typeSignature.member(nme.CONSTRUCTOR).asMethodSymbol`. + * For further information about member lookup refer to `Symbol.typeSignature`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be a member (declared or inherited) of the class underlying this mirror. */ def reflectConstructor(constructor: MethodSymbol): MethodMirror @@ -161,24 +221,40 @@ trait Mirrors { self: Universe => /** A mirror that reflects instances and static classes */ trait ReflectiveMirror extends MirrorOf[Mirrors.this.type] { - /** A reflective mirror for the given object - * @param obj An arbitrary value - * @return The mirror for `obj`. + /** A reflective mirror for the given object. + * + * Such a mirror can be used to further reflect against the members of the object + * to get/set fields, invoke methods and inspect inner classes and objects. */ def reflect(obj: Any): InstanceMirror - /** .. */ + /** Reflects against a static class symbol and returns a mirror + * that can be used to create instances of the class, inspect its companion object or perform further reflections. + * + * To get a class symbol by the name of the class you would like to reflect, + * use `.classSymbol()`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be static, i.e. either top-level or nested within one or several static objects. + */ def reflectClass(cls: ClassSymbol): ClassMirror - /** .. */ + /** Reflects against a static module symbol and returns a mirror + * that can be used to get the instance of the object or inspect its companion class. + * + * To get a module symbol by the name of its companion class you would like to reflect, + * use `.classSymbol().companion.get`. + * + * The input symbol can be either private or non-private (Scala reflection transparently deals with visibility). + * It must be static, i.e. either top-level or nested within one or several static objects. + */ def reflectModule(mod: ModuleSymbol): ModuleMirror } /** The API of a mirror for a reflective universe */ trait RuntimeMirror extends ReflectiveMirror { self => - /** Maps a Scala type to the corresponding Java class object - */ + /** Maps a Scala type to the corresponding Java class object */ def runtimeClass(tpe: Type): RuntimeClass /** Maps a Scala class symbol to the corresponding Java class object @@ -198,7 +274,7 @@ trait Mirrors { self: Universe => def classSymbol(rtcls: RuntimeClass): ClassSymbol /** A module symbol for the specified runtime class. - * @return The module symbol for the runtime class in the current class loader. + * @return The module symbol for the runtime class in the current class loader. * @throws java.lang.ClassNotFoundException if no class with that name exists * @throws scala.reflect.internal.MissingRequirementError if no corresponding symbol exists * to do: throws anything else? -- cgit v1.2.3