diff options
author | Paul Phillips <paulp@improving.org> | 2011-08-23 21:15:20 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-08-23 21:15:20 +0000 |
commit | 3a1463cd833175bdaa7a31d96a41a0d926b0e9db (patch) | |
tree | d770316544eff5144e34ec54353b06d6cbe20fe5 /src | |
parent | e69822117c99a6c79a69a5b4dde3a82040400bb3 (diff) | |
download | scala-3a1463cd833175bdaa7a31d96a41a0d926b0e9db.tar.gz scala-3a1463cd833175bdaa7a31d96a41a0d926b0e9db.tar.bz2 scala-3a1463cd833175bdaa7a31d96a41a0d926b0e9db.zip |
Modified scala.reflect package object not to th...
Modified scala.reflect package object not to throw an exception at
initialization time if it can't instantiate the value in question.
Review by odersky.
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 */ - } |