From 54a84a36d5b435a787d93ca48d45399136c7e162 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 7 Dec 2012 15:45:14 +0100 Subject: 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. --- src/reflect/scala/reflect/runtime/JavaMirrors.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index ab93d7033a..9f29d9a230 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -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 } } /** -- cgit v1.2.3 From 0429f0fd9224499cd8b606490d04b1a8dcffbca8 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Fri, 7 Dec 2012 18:55:41 +0100 Subject: cosmetic renamings in runtime reflection initClassModule => initClassAndModule createClassModule => initAndEnterClassAndModule --- src/reflect/scala/reflect/runtime/JavaMirrors.scala | 4 ++-- src/reflect/scala/reflect/runtime/SymbolLoaders.scala | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/reflect') diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 9f29d9a230..4c154bb4b8 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -574,7 +574,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni case None => // class does not have a Scala signature; it's a Java class info("translating reflection info for Java " + jclazz) //debug - initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) + initClassAndModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz)) } } } catch { @@ -1043,7 +1043,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni val owner = sOwner(jclazz) val name = scalaSimpleName(jclazz) val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz) - createClassModule(owner, name, completer) match { case (clazz, module) => clazz } + initAndEnterClassAndModule(owner, name, completer)._1 } /** diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala index 61663f6181..311db64b91 100644 --- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala +++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala @@ -57,7 +57,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => * @param name The simple name of the newly created class * @param completer The completer to be used to set the info of the class and the module */ - protected def createClassModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = { + protected def initAndEnterClassAndModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = { assert(!(name.toString endsWith "[]"), name) val clazz = owner.newClass(name) val module = owner.newModule(name.toTermName) @@ -67,7 +67,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => owner.info.decls enter clazz owner.info.decls enter module } - initClassModule(clazz, module, completer(clazz, module)) + initClassAndModule(clazz, module, completer(clazz, module)) (clazz, module) } @@ -75,7 +75,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => List(clazz, module, module.moduleClass) foreach (_ setInfo info) } - protected def initClassModule(clazz: Symbol, module: Symbol, completer: LazyType) = + protected def initClassAndModule(clazz: Symbol, module: Symbol, completer: LazyType) = setAllInfos(clazz, module, completer) /** The type completer for packages. @@ -118,7 +118,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable => val loadingMirror = currentMirror.mirrorDefining(cls) val (clazz, module) = if (loadingMirror eq currentMirror) { - createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) + initAndEnterClassAndModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) } else { val origOwner = loadingMirror.packageNameToScala(pkgClass.fullName) val clazz = origOwner.info decl name.toTypeName -- cgit v1.2.3