summaryrefslogtreecommitdiff
path: root/test/files/run/reflection-magicsymbols-invoke.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-08-04 11:08:10 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-08-06 23:09:30 +0200
commit432d7b86cb7c46d0415b8c06bf8045e309c63f03 (patch)
treec8d768c86d849a5cddf59f2ef6fce8de889b1310 /test/files/run/reflection-magicsymbols-invoke.scala
parent114367c0b2ce5f48186d4270c1724090fd77877b (diff)
downloadscala-432d7b86cb7c46d0415b8c06bf8045e309c63f03.tar.gz
scala-432d7b86cb7c46d0415b8c06bf8045e309c63f03.tar.bz2
scala-432d7b86cb7c46d0415b8c06bf8045e309c63f03.zip
SI-6178 reflective invocation of magic symbols
In Scala there are some methods that only exist in symbol tables, but don't have corresponding method entries in Java class files. To the best of my knowledge, these methods can be subdivided into five groups: 1) stuff weaved onto Any, AnyVal and AnyRef (aka Object), 2) magic methods that Scala exposes to fix Java arrays, 3) magic methods declared on Scala primitive value classes, 4) compile-time methods (such as classOf and all kinds of macros), 5) miscellaneous stuff (currently only String_+). To support these magic symbols, I've modified the `checkMemberOf` validator to special case Any/AnyVal/AnyRef methods and adjusted MethodMirror and ConstructorMirror classes to use special invokers for those instead of relying on Java reflection. Support for value classes will arrive in the subsequent commit, because it requires some unrelated changes to the mirror API (currently mirrors only support AnyRefs as their targets).
Diffstat (limited to 'test/files/run/reflection-magicsymbols-invoke.scala')
-rw-r--r--test/files/run/reflection-magicsymbols-invoke.scala94
1 files changed, 94 insertions, 0 deletions
diff --git a/test/files/run/reflection-magicsymbols-invoke.scala b/test/files/run/reflection-magicsymbols-invoke.scala
new file mode 100644
index 0000000000..61ecc6458d
--- /dev/null
+++ b/test/files/run/reflection-magicsymbols-invoke.scala
@@ -0,0 +1,94 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.universe.definitions._
+import scala.reflect.runtime.{currentMirror => cm}
+
+object Test extends App {
+ def key(sym: Symbol) = sym + ": " + sym.typeSignature
+ def test(tpe: Type, receiver: Any, method: String, args: Any*) {
+ def wrap[T](op: => T) =
+ try {
+ var result = op.asInstanceOf[AnyRef]
+ if (scala.runtime.ScalaRunTime.isArray(result))
+ result = scala.runtime.ScalaRunTime.toObjectArray(result).toList
+ println(result)
+ } catch {
+ case ex: Throwable =>
+ val realex = scala.reflect.runtime.ReflectionUtils.unwrapThrowable(ex)
+ println(realex.getClass + ": " + realex.getMessage)
+ }
+ print(s"testing ${tpe.typeSymbol.name}.$method: ")
+ wrap({
+ if (method == nme.CONSTRUCTOR.toString) {
+ val ctor = tpe.declaration(nme.CONSTRUCTOR).asMethod
+ cm.reflectClass(ctor.owner.asClass).reflectConstructor(ctor)(args: _*)
+ } else {
+ val meth = tpe.declaration(newTermName(method).encodedName.toTermName).asMethod
+ cm.reflect(receiver).reflectMethod(meth)(args: _*)
+ }
+ })
+ }
+
+ println("============\nAny")
+ println("it's important to print the list of Any's members")
+ println("if some of them change (possibly, adding and/or removing magic symbols), we must update this test")
+ typeOf[Any].members.toList.sortBy(key).foreach(sym => println(key(sym)))
+ test(typeOf[Any], "2", "!=", "2")
+ test(typeOf[Any], "2", "##")
+ test(typeOf[Any], "2", "==", "2")
+ test(typeOf[Any], "2", "asInstanceOf")
+ test(typeOf[Any], "2", "asInstanceOf", typeOf[String])
+ test(typeOf[Any], "2", "equals", "2")
+ test(typeOf[Any], "2", "getClass")
+ test(typeOf[Any], "2", "hashCode")
+ test(typeOf[Any], "2", "isInstanceOf")
+ test(typeOf[Any], "2", "isInstanceOf", typeOf[String])
+ test(typeOf[Any], "2", "toString")
+
+ println("============\nAnyVal")
+ println("it's important to print the list of AnyVal's members")
+ println("if some of them change (possibly, adding and/or removing magic symbols), we must update this test")
+ typeOf[AnyVal].declarations.toList.sortBy(key).foreach(sym => println(key(sym)))
+ test(typeOf[AnyVal], null, "<init>")
+ test(typeOf[AnyVal], 2, "getClass")
+
+ println("============\nAnyRef")
+ println("it's important to print the list of AnyRef's members")
+ println("if some of them change (possibly, adding and/or removing magic symbols), we must update this test")
+ typeOf[AnyRef].members.toList.sortBy(key).foreach(sym => println(key(sym)))
+ test(typeOf[AnyRef], "2", "!=", "2")
+ test(typeOf[AnyRef], "2", "##")
+ test(typeOf[AnyRef], "2", "$asInstanceOf")
+ test(typeOf[AnyRef], "2", "$asInstanceOf", typeOf[String])
+ test(typeOf[AnyRef], "2", "$isInstanceOf")
+ test(typeOf[AnyRef], "2", "$isInstanceOf", typeOf[String])
+ test(typeOf[AnyRef], "2", "==", "2")
+ test(typeOf[AnyRef], "2", "clone")
+ test(typeOf[AnyRef], "2", "eq", "2")
+ test(typeOf[AnyRef], "2", "equals", "2")
+ test(typeOf[AnyRef], "2", "finalize")
+ test(typeOf[AnyRef], "2", "getClass")
+ test(typeOf[AnyRef], "2", "hashCode")
+ test(typeOf[AnyRef], "2", "ne", "2")
+ test(typeOf[AnyRef], "2", "notify")
+ test(typeOf[AnyRef], "2", "notifyAll")
+ test(typeOf[AnyRef], "2", "synchronized", "2")
+ test(typeOf[AnyRef], "2", "toString")
+ println("TODO: also test AnyRef.wait overloads")
+
+ println("============\nArray")
+ println("it's important to print the list of Array's members")
+ println("if some of them change (possibly, adding and/or removing magic symbols), we must update this test")
+ ArrayClass.typeSignature.members.toList.sortBy(key).foreach(sym => println(key(sym)))
+ test(ArrayClass.typeSignature, Array(1, 2), "length")
+ test(ArrayClass.typeSignature, Array(1, 2), "apply", 0)
+ test(ArrayClass.typeSignature, Array(1, 2), "update", 0, 0)
+ test(ArrayClass.typeSignature, Array(1, 2), "clone")
+
+ println("============\nOther")
+ test(typeOf[String], "2", "+", 3)
+
+ println("============\nCTM")
+ test(PredefModule.moduleClass.typeSignature, Predef, "classOf")
+ test(PredefModule.moduleClass.typeSignature, Predef, "classOf", typeOf[String])
+ test(typeOf[scala.reflect.base.Universe], scala.reflect.runtime.universe, "reify", "2")
+} \ No newline at end of file