Permalink
Browse files

SI-6548 reflection now correctly enters jinners

When completing Java classes, runtime reflection enumerates their
fields, methods, constructors and inner classes, loads them and
enters them into either the instance part (ClassSymbol) or the
static part (ModuleSymbol).

However unlike fields, methods and constructors, inner classes don't
need to be entered explicitly - they are entered implicitly when
being loaded.

This patch fixes the double-enter problem, make sure that enter-on-load
uses the correct owner, and also hardens jclassAsScala against double
enters that can occur in a different scenario.

Since the fix is about Java-compiled classes, the test needs *.class
artifacts produced by javac. Therefore I updated javac-artifacts.jar to
include the new artifacts along with their source code.
  • Loading branch information...
1 parent 5896985 commit 54a84a36d5b435a787d93ca48d45399136c7e162 @xeno-by xeno-by committed Dec 7, 2012
@@ -676,9 +676,9 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
def enter(sym: Symbol, mods: Int) =
(if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym
- for (jinner <- jclazz.getDeclaredClasses) {
- enter(jclassAsScala(jinner, clazz), jinner.getModifiers)
- }
+ for (jinner <- jclazz.getDeclaredClasses)
+ jclassAsScala(jinner) // inner class is entered as a side-effect
+ // no need to call enter explicitly
pendingLoadActions = { () =>
@@ -1036,14 +1036,14 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* @param jclazz The Java class
* @return A Scala class symbol that wraps all reflection info of `jclazz`
*/
- private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz))
+ private def jclassAsScala(jclazz: jClass[_]): ClassSymbol =
+ toScala(classCache, jclazz)(_ jclassAsScala1 _)
- private def jclassAsScala(jclazz: jClass[_], owner: Symbol): ClassSymbol = {
+ private def jclassAsScala1(jclazz: jClass[_]): ClassSymbol = {
+ val owner = sOwner(jclazz)
val name = scalaSimpleName(jclazz)
val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz)
- val (clazz, module) = createClassModule(owner, name, completer)
- classCache enter (jclazz, clazz)
- clazz
+ createClassModule(owner, name, completer) match { case (clazz, module) => clazz }
}
/**
@@ -1 +1 @@
-c5788c5e518eb267445c5a995fd98b2210f90a58 ?javac-artifacts.jar
+61931a51bb1a2d308d214b96d06e9a8808515dcf ?javac-artifacts.jar
@@ -0,0 +1,2 @@
+false
+List(JavaAnnotationWithNestedEnum(value = VALUE))
View
@@ -0,0 +1,12 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+
+class Bean {
+ @JavaAnnotationWithNestedEnum(JavaAnnotationWithNestedEnum.Value.VALUE)
+ def value = 1
+}
+
+object Test extends App {
+ println(cm.staticClass("Bean").isCaseClass)
+ println(typeOf[Bean].declaration(newTermName("value")).annotations)
+}

0 comments on commit 54a84a3

Please sign in to comment.