diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/library/scala/reflect/ReflectionUtils.scala | 37 | ||||
-rw-r--r-- | src/library/scala/reflect/package.scala | 16 |
2 files changed, 46 insertions, 7 deletions
diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/library/scala/reflect/ReflectionUtils.scala new file mode 100644 index 0000000000..c2f89102cb --- /dev/null +++ b/src/library/scala/reflect/ReflectionUtils.scala @@ -0,0 +1,37 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.reflect + +import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException } + +/** A few java-reflection oriented utility functions useful during reflection bootstrapping. + */ +trait ReflectionUtils { + // Unwraps some chained exceptions which arise during reflective calls. + def unwrapThrowable(x: Throwable): Throwable = x match { + case _: InvocationTargetException | // thrown by reflectively invoked method or constructor + _: ExceptionInInitializerError | // thrown when running a static initializer (e.g. a scala module constructor) + _: UndeclaredThrowableException | // invocation on a proxy instance if its invocation handler's `invoke` throws an exception + _: ClassNotFoundException | // no definition for a class instantiated by name + _: NoClassDefFoundError // the definition existed when the executing class was compiled, but can no longer be found + if x.getCause != null => + unwrapThrowable(x.getCause) + case _ => x + } + // Transforms an exception handler into one which will only receive the unwrapped + // exceptions (for the values of wrap covered in unwrapThrowable.) + def unwrapForHandler[T](pf: PartialFunction[Throwable, T]): PartialFunction[Throwable, T] = { + case ex if pf isDefinedAt unwrapThrowable(ex) => pf(unwrapThrowable(ex)) + } + + // Retrieves the MODULE$ field for the given class name. + def singletonInstance(className: String, cl: ClassLoader = getClass.getClassLoader): Option[AnyRef] = { + val name = if (className endsWith "$") className else className + "$" + + try Some(java.lang.Class.forName(name, true, cl) getField "MODULE$" get null) + catch { case _: ClassNotFoundException => None } + } +} diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala index eac4adcffe..ad541ce46e 100644 --- a/src/library/scala/reflect/package.scala +++ b/src/library/scala/reflect/package.scala @@ -1,18 +1,20 @@ package scala -package object reflect { - - val mirror: api.Mirror = try { +package object reflect extends ReflectionUtils { + // !!! This was a val; we can't throw exceptions that aggressively without breaking + // non-standard environments, e.g. google app engine. I made it a lazy val, but + // I think it would be better yet to throw the exception somewhere else - not during + // initialization, but in response to a doomed attempt to utilize it. + lazy val mirror: api.Mirror = { // we use (Java) reflection here so that we can keep reflect.runtime and reflect.internals in a seperate jar - (java.lang.Class forName "scala.reflect.runtime.Mirror$" getField "MODULE$" get null).asInstanceOf[api.Mirror] - } catch { - case ex: NoClassDefFoundError => + singletonInstance("scala.reflect.runtime.Mirror") collect { case x: api.Mirror => x } getOrElse { throw new UnsupportedOperationException("Scala reflection not available on this platform") + } } + /** Uncomment once we got rid of the old Symbols, Types, Trees type Symbol = mirror.Symbol type Type = mirror.Type type Tree = mirror.Tree */ - } |