summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-06-08 11:43:20 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-06-08 15:35:23 +0200
commitabc1c0be79ac2fb2b0e75c87a489570a9c71aa6e (patch)
tree5d2723fa39aa8b28337b1e005ae06891667580a2 /src
parent2123201e3cbc34676d2936226539bdfa0555c275 (diff)
downloadscala-abc1c0be79ac2fb2b0e75c87a489570a9c71aa6e.tar.gz
scala-abc1c0be79ac2fb2b0e75c87a489570a9c71aa6e.tar.bz2
scala-abc1c0be79ac2fb2b0e75c87a489570a9c71aa6e.zip
tests and fixes for the mirror API
Diffstat (limited to 'src')
-rw-r--r--src/reflect/scala/reflect/api/Mirrors.scala77
-rw-r--r--src/reflect/scala/reflect/api/TagInterop.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala95
3 files changed, 99 insertions, 75 deletions
diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala
index 2fcee8f227..348ab3656b 100644
--- a/src/reflect/scala/reflect/api/Mirrors.scala
+++ b/src/reflect/scala/reflect/api/Mirrors.scala
@@ -5,10 +5,6 @@ trait Mirrors { self: Universe =>
type RuntimeClass >: Null
- // [Eugene++ to Martin] how do we reflect against inner classes?
- // presumably, we should add `reflectClass` to both InstanceMirror (inner classes) and TemplateMirror (nested classes)
- // in the former case, the resulting ClassMirror should remember the outer instance that spawned it to use it in reflective construction
-
// [Eugene] also, it might make sense to provide shortcuts for the API
//
// for example, right now to invoke the same method for several different instances, you need:
@@ -31,8 +27,8 @@ trait Mirrors { self: Universe =>
/** The instance value reflected by this mirror */
def instance: Any
- /** The mirror corresponding to the run-time class of the reflected instance. */
- def reflectClass: ClassMirror
+ /** 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.
@@ -48,6 +44,12 @@ trait Mirrors { self: Universe =>
* @throws ???
*/
def reflectMethod(method: MethodSymbol): MethodMirror
+
+ /** .. */
+ def reflectClass(cls: ClassSymbol): ClassMirror
+
+ /** .. */
+ def reflectModule(mod: ModuleSymbol): ModuleMirror
}
/** A mirror that reflects a field */
@@ -57,7 +59,7 @@ trait Mirrors { self: Universe =>
def receiver: AnyRef
/** The field symbol representing the field */
- def field: TermSymbol
+ def symbol: TermSymbol
/** Retrieves the value stored in the field */
def get: Any
@@ -73,9 +75,10 @@ trait Mirrors { self: Universe =>
def receiver: AnyRef
/** The method symbol representing the method */
- def method: MethodSymbol
+ 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
def apply(args: Any*): Any
}
@@ -97,8 +100,6 @@ trait Mirrors { self: Universe =>
/** The Scala symbol corresponding to the reflected runtime class or module. */
def symbol: Symbol
- // [Eugene++ to Martin] I've removed `typeSignature`, because we can obtain it via `symbol.typeSignature`
-
/** Optionally, the mirror of the companion reflected by this mirror.
* If this mirror reflects a Scala object, the mirror for the companion class, or None
* if the mirror represents a Scala object that comes without a class.
@@ -157,8 +158,8 @@ trait Mirrors { self: Universe =>
def companion: Option[ModuleMirror]
}
- /** The API of a mirror for a reflective universe */
- trait RuntimeMirror extends MirrorOf[Mirrors.this.type] { self =>
+ /** 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
@@ -166,37 +167,15 @@ trait Mirrors { self: Universe =>
*/
def reflect(obj: Any): InstanceMirror
- /** A reflective mirror for the given Runtime class
- * @param runtimeClass A Runtime class object
- * @return The mirror for `runtimeClass`
- */
- def reflectClass(runtimeClass: RuntimeClass): ClassMirror
-
- /** A reflective mirror for the Runtime class with the given name in the
- * current classloader.
- * @param name The fully qualified name of the class
- * @return The mirror for the runtime class with fully qualified name
- * `name` in the current class loader.
- * @throws java.lang.ClassNotFoundException if no class with that name exists
- * to do: throws anything else?
- */
- def reflectClass(fullName: String): ClassMirror
+ /** .. */
+ def reflectClass(cls: ClassSymbol): ClassMirror
- /** A reflective mirror for the given Runtime class
- * @param runtimeClass A Runtime class object
- * @return The mirror for `runtimeClass`
- */
- def reflectModule(runtimeClass: RuntimeClass): ModuleMirror
+ /** .. */
+ def reflectModule(mod: ModuleSymbol): ModuleMirror
+ }
- /** A reflective mirror for the Runtime class with the given name in the
- * current classloader.
- * @param name The fully qualified name of the class
- * @return The mirror for the runtime class with fully qualified name
- * `name` in the current class loader.
- * @throws java.lang.ClassNotFoundException if no class with that name exists
- * to do: throws anything else?
- */
- def reflectModule(fullName: String): 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
*/
@@ -209,5 +188,21 @@ trait Mirrors { self: Universe =>
* because there is no unique Java class corresponding to a Scala generic array
*/
def runtimeClass(cls: ClassSymbol): RuntimeClass
+
+ /** A class symbol for the specified runtime class.
+ * @return The class 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?
+ */
+ 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.
+ * @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?
+ */
+ def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol
}
}
diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala
index 95c4e78cf4..f1938083b5 100644
--- a/src/reflect/scala/reflect/api/TagInterop.scala
+++ b/src/reflect/scala/reflect/api/TagInterop.scala
@@ -25,7 +25,7 @@ trait TagInterop { self: JavaUniverse =>
mirror.universe match {
case ju: JavaUniverse =>
val jm = mirror.asInstanceOf[ju.Mirror]
- val sym = jm.reflectClass(manifest.erasure).symbol
+ val sym = jm.classSymbol(manifest.erasure)
val tpe =
if (manifest.typeArguments.isEmpty) sym.asType
else ju.appliedType(sym.asTypeConstructor, manifest.typeArguments map (targ => ju.manifestToTypeTag(jm, targ)) map (_.in(jm).tpe))
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index ed03ac30f9..38d280ec73 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -32,6 +32,8 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
jm
}
+ override type RuntimeClass = java.lang.Class[_]
+
override type Mirror = JavaMirror
override lazy val rootMirror: Mirror = createMirror(NoSymbol, rootClassLoader)
@@ -105,30 +107,32 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
// ----------- Implementations of mirror operations and classes -------------------
- def reflect(obj: Any): InstanceMirror =
- new JavaInstanceMirror(obj.asInstanceOf[AnyRef])
-
- def reflectClass(runtimeClass: RuntimeClass): ClassMirror =
- new JavaClassMirror(classToScala(runtimeClass))
-
- def reflectClass(fullName: String): ClassMirror =
- reflectClass(java.lang.Class.forName(fullName))
+ def reflect(obj: Any): InstanceMirror = new JavaInstanceMirror(obj.asInstanceOf[AnyRef])
- def reflectModule(runtimeClass: RuntimeClass): ModuleMirror =
- new JavaModuleMirror(classToScala(runtimeClass).companionModule.asModuleSymbol)
+ 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")
+ new JavaClassMirror(null, cls)
+ }
- def reflectModule(fullName: String): ModuleMirror =
- reflectModule(java.lang.Class.forName(fullName))
+ 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")
+ new JavaModuleMirror(null, mod)
+ }
def runtimeClass(tpe: Type): RuntimeClass = typeToJavaClass(tpe)
def runtimeClass(cls: ClassSymbol): RuntimeClass = classToJava(cls)
+ def classSymbol(rtcls: RuntimeClass): ClassSymbol = classToScala(rtcls)
+
+ def moduleSymbol(rtcls: RuntimeClass): ModuleSymbol = classToScala(rtcls).companionModule.asModuleSymbol
+
private class JavaInstanceMirror(obj: AnyRef)
extends InstanceMirror {
def instance = obj
- def reflectClass = wholemirror.reflectClass(obj.getClass)
+ 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.
@@ -139,79 +143,101 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
""".trim.stripMargin)
new JavaFieldMirror(obj, field)
}
- def reflectMethod(method: MethodSymbol): MethodMirror = new JavaMethodMirror(obj, method)
+ def reflectMethod(method: MethodSymbol): MethodMirror = {
+ // [Eugene+++] check whether `method` represents a member of a `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")
+ 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")
+ new JavaModuleMirror(instance, mod)
+ }
}
- private class JavaFieldMirror(val receiver: AnyRef, val field: TermSymbol)
+ private class JavaFieldMirror(val receiver: AnyRef, val symbol: TermSymbol)
extends FieldMirror {
lazy val jfield = {
- val jfield = fieldToJava(field)
+ val jfield = fieldToJava(symbol)
if (!jfield.isAccessible) jfield.setAccessible(true)
jfield
}
def get = jfield.get(receiver)
def set(value: Any) = {
- if (!field.isMutable) throw new Error("cannot set an immutable field")
+ if (!symbol.isMutable) throw new Error("cannot set an immutable field")
jfield.set(receiver, value)
}
}
- private class JavaMethodMirror(val receiver: AnyRef, val method: MethodSymbol)
+ private class JavaMethodMirror(val receiver: AnyRef, val symbol: MethodSymbol)
extends MethodMirror {
lazy val jmeth = {
- val jmeth = methodToJava(method)
+ val jmeth = methodToJava(symbol)
if (!jmeth.isAccessible) jmeth.setAccessible(true)
jmeth
}
def apply(args: Any*): Any =
- if (method.owner == ArrayClass)
- method.name match {
+ if (symbol.owner == ArrayClass)
+ symbol.name match {
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 $method")
+ case _ => throw new Error(s"unexpected array method $symbol")
}
else
jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
}
- private class JavaConstructorMirror(val method: MethodSymbol)
+ private class JavaConstructorMirror(val outer: AnyRef, val symbol: MethodSymbol)
extends MethodMirror {
- override val receiver = null
+ override val receiver = outer
lazy val jconstr = {
- val jconstr = constructorToJava(method)
+ val jconstr = constructorToJava(symbol)
if (!jconstr.isAccessible) jconstr.setAccessible(true)
jconstr
}
- def apply(args: Any*): Any = jconstr.newInstance(args.asInstanceOf[Seq[AnyRef]]: _*)
+ def apply(args: Any*): Any = {
+ val effectiveArgs =
+ if (outer == null) args.asInstanceOf[Seq[AnyRef]]
+ else outer +: args.asInstanceOf[Seq[AnyRef]]
+ jconstr.newInstance(effectiveArgs: _*)
+ }
}
private abstract class JavaTemplateMirror
extends TemplateMirror {
+ def outer: AnyRef
def erasure: ClassSymbol
lazy val runtimeClass = classToJava(erasure)
lazy val signature = typeToScala(runtimeClass)
}
- private class JavaClassMirror(val symbol: ClassSymbol)
+ private class JavaClassMirror(val outer: AnyRef, val symbol: ClassSymbol)
extends JavaTemplateMirror with ClassMirror {
def erasure = symbol
def isStatic = false
- def reflectConstructor(constructor: MethodSymbol) = new JavaConstructorMirror(constructor)
+ def reflectConstructor(constructor: MethodSymbol) = new JavaConstructorMirror(outer, constructor)
def companion: Option[ModuleMirror] = symbol.companionModule match {
- case module: ModuleSymbol => Some(new JavaModuleMirror(module))
+ case module: ModuleSymbol => Some(new JavaModuleMirror(outer, module))
case _ => None
}
}
- private class JavaModuleMirror(val symbol: ModuleSymbol)
+ private class JavaModuleMirror(val outer: AnyRef, val symbol: ModuleSymbol)
extends JavaTemplateMirror with ModuleMirror {
def erasure = symbol.moduleClass.asClassSymbol
def isStatic = true
- def instance = singletonInstance(classLoader, symbol.fullName)
+ def instance = {
+ if (!symbol.owner.isPackageClass) throw new Error("inner and nested modules are not supported yet")
+ singletonInstance(classLoader, symbol.fullName)
+ }
def companion: Option[ClassMirror] = symbol.companionClass match {
- case cls: ClassSymbol => Some(new JavaClassMirror(cls))
+ case cls: ClassSymbol => Some(new JavaClassMirror(outer, cls))
case _ => None
}
}
@@ -929,7 +955,10 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { self: Sym
def constructorToJava(constr: MethodSymbol): jConstructor[_] = constructorCache.toJava(constr) {
val jclazz = classToJava(constr.owner.asClassSymbol)
val paramClasses = transformedType(constr).paramTypes map typeToJavaClass
- jclazz getConstructor (paramClasses: _*)
+ val effectiveParamClasses =
+ if (!constr.owner.owner.isStaticOwner) jclazz.getEnclosingClass +: paramClasses
+ else paramClasses
+ jclazz getConstructor (effectiveParamClasses: _*)
}
private def jArrayClass(elemClazz: jClass[_]): jClass[_] = {