From 02ed5fb3bc8d792872223ceecfd8fd0ae089d923 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Thu, 31 Jan 2013 11:49:19 +0100 Subject: SI-6989 privateWithin is now populated in reflect Runtime reflection in JavaMirrors previously forgot to fill in privateWithin when importing Java reflection artifacts. Now this is fixed. --- .../nsc/symtab/classfile/ClassfileParser.scala | 21 ++++--------------- .../scala/reflect/internal/PrivateWithin.scala | 23 +++++++++++++++++++++ .../scala/reflect/internal/SymbolTable.scala | 1 + .../scala/reflect/runtime/JavaMirrors.scala | 5 +++++ test/files/run/t6989.check | 24 ++++++++++++++++++++++ test/files/run/t6989/JavaClass_1.java | 7 +++++++ test/files/run/t6989/Test_2.scala | 23 +++++++++++++++++++++ 7 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 src/reflect/scala/reflect/internal/PrivateWithin.scala create mode 100644 test/files/run/t6989.check create mode 100644 test/files/run/t6989/JavaClass_1.java create mode 100644 test/files/run/t6989/Test_2.scala diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index a708a262e7..19b32dd5fb 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -548,8 +548,8 @@ abstract class ClassfileParser { skipMembers() // methods if (!isScala) { clazz setFlag sflags - setPrivateWithin(clazz, jflags) - setPrivateWithin(staticModule, jflags) + importPrivateWithinFromJavaFlags(clazz, jflags) + importPrivateWithinFromJavaFlags(staticModule, jflags) clazz.setInfo(classInfo) moduleClass setInfo staticInfo staticModule.setInfo(moduleClass.tpe) @@ -612,7 +612,7 @@ abstract class ClassfileParser { if (isEnum) ConstantType(Constant(sym)) else info } - setPrivateWithin(sym, jflags) + importPrivateWithinFromJavaFlags(sym, jflags) parseAttributes(sym, info) getScope(jflags).enter(sym) @@ -663,7 +663,7 @@ abstract class ClassfileParser { info = MethodType(newParams, clazz.tpe) } sym.setInfo(info) - setPrivateWithin(sym, jflags) + importPrivateWithinFromJavaFlags(sym, jflags) parseAttributes(sym, info) if ((jflags & JAVA_ACC_VARARGS) != 0) { sym.setInfo(arrayToRepeated(sym.info)) @@ -1263,19 +1263,6 @@ abstract class ClassfileParser { protected def getScope(flags: Int): Scope = if (isStatic(flags)) staticScope else instanceScope - private def setPrivateWithin(sym: Symbol, jflags: Int) { - if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0) - // See ticket #1687 for an example of when topLevelClass is NoSymbol: it - // apparently occurs when processing v45.3 bytecode. - if (sym.enclosingTopLevelClass != NoSymbol) - sym.privateWithin = sym.enclosingTopLevelClass.owner - - // protected in java means package protected. #3946 - if ((jflags & JAVA_ACC_PROTECTED) != 0) - if (sym.enclosingTopLevelClass != NoSymbol) - sym.privateWithin = sym.enclosingTopLevelClass.owner - } - private def isPrivate(flags: Int) = (flags & JAVA_ACC_PRIVATE) != 0 private def isStatic(flags: Int) = (flags & JAVA_ACC_STATIC) != 0 private def hasAnnotation(flags: Int) = (flags & JAVA_ACC_ANNOTATION) != 0 diff --git a/src/reflect/scala/reflect/internal/PrivateWithin.scala b/src/reflect/scala/reflect/internal/PrivateWithin.scala new file mode 100644 index 0000000000..9b99b94b41 --- /dev/null +++ b/src/reflect/scala/reflect/internal/PrivateWithin.scala @@ -0,0 +1,23 @@ +package scala.reflect +package internal + +import ClassfileConstants._ + +trait PrivateWithin { + self: SymbolTable => + + def importPrivateWithinFromJavaFlags(sym: Symbol, jflags: Int): Symbol = { + if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0) + // See ticket #1687 for an example of when topLevelClass is NoSymbol: it + // apparently occurs when processing v45.3 bytecode. + if (sym.enclosingTopLevelClass != NoSymbol) + sym.privateWithin = sym.enclosingTopLevelClass.owner + + // protected in java means package protected. #3946 + if ((jflags & JAVA_ACC_PROTECTED) != 0) + if (sym.enclosingTopLevelClass != NoSymbol) + sym.privateWithin = sym.enclosingTopLevelClass.owner + + sym + } +} \ No newline at end of file diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index 02ac59a461..f75855f1ec 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -38,6 +38,7 @@ abstract class SymbolTable extends macros.Universe with StdAttachments with StdCreators with BuildUtils + with PrivateWithin { val gen = new TreeGen { val global: SymbolTable.this.type = SymbolTable.this } diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala index 01e0634902..70d506ad95 100644 --- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala +++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala @@ -631,6 +631,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni /** used to avoid cycles while initializing classes */ private var parentsLevel = 0 private var pendingLoadActions: List[() => Unit] = Nil + private val relatedSymbols = clazz +: (if (module != NoSymbol) List(module, module.moduleClass) else Nil) override def load(sym: Symbol): Unit = { debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug @@ -642,6 +643,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni module.moduleClass setFlag (flags & PRIVATE | JAVA) } + relatedSymbols foreach (importPrivateWithinFromJavaFlags(_, jclazz.getModifiers)) copyAnnotations(clazz, jclazz) // to do: annotations to set also for module? @@ -1060,6 +1062,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni .newValue(newTermName(jfield.getName), NoPosition, toScalaFieldFlags(jfield.getModifiers)) .setInfo(typeToScala(jfield.getGenericType)) fieldCache enter (jfield, field) + importPrivateWithinFromJavaFlags(field, jfield.getModifiers) copyAnnotations(field, jfield) field } @@ -1085,6 +1088,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala val resulttpe = typeToScala(jmeth.getGenericReturnType) setMethType(meth, tparams, paramtpes, resulttpe) + importPrivateWithinFromJavaFlags(meth, jmeth.getModifiers) copyAnnotations(meth, jmeth) if ((jmeth.getModifiers & JAVA_ACC_VARARGS) != 0) meth.setInfo(arrayToRepeated(meth.info)) meth @@ -1108,6 +1112,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala setMethType(constr, tparams, paramtpes, clazz.tpe) constr setInfo GenPolyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe)) + importPrivateWithinFromJavaFlags(constr, jconstr.getModifiers) copyAnnotations(constr, jconstr) constr } diff --git a/test/files/run/t6989.check b/test/files/run/t6989.check new file mode 100644 index 0000000000..06bc3b7200 --- /dev/null +++ b/test/files/run/t6989.check @@ -0,0 +1,24 @@ +============ +class JavaClass_1 +isPrivate = false +isProtected = false +isPublic = false +privateWithin = package foo +============ +variable x +isPrivate = true +isProtected = false +isPublic = false +privateWithin = +============ +variable y +isPrivate = false +isProtected = true +isPublic = false +privateWithin = package foo +============ +variable z +isPrivate = false +isProtected = false +isPublic = true +privateWithin = diff --git a/test/files/run/t6989/JavaClass_1.java b/test/files/run/t6989/JavaClass_1.java new file mode 100644 index 0000000000..61253dfe6f --- /dev/null +++ b/test/files/run/t6989/JavaClass_1.java @@ -0,0 +1,7 @@ +package foo; + +class JavaClass_1 { + private int x = 0; + protected String y = ""; + public float z = 0.0f; +} \ No newline at end of file diff --git a/test/files/run/t6989/Test_2.scala b/test/files/run/t6989/Test_2.scala new file mode 100644 index 0000000000..ba88e5cce3 --- /dev/null +++ b/test/files/run/t6989/Test_2.scala @@ -0,0 +1,23 @@ +import scala.reflect.runtime.universe._ + +package object foo { + def test(sym: Symbol) = { + println("============") + println(sym) + println(s"isPrivate = ${sym.isPrivate}") + println(s"isProtected = ${sym.isProtected}") + println(s"isPublic = ${sym.isPublic}") + println(s"privateWithin = ${sym.privateWithin}") + } + + def testAll() = { + test(typeOf[foo.JavaClass_1].typeSymbol) + test(typeOf[foo.JavaClass_1].declaration(newTermName("x"))) + test(typeOf[foo.JavaClass_1].declaration(newTermName("y"))) + test(typeOf[foo.JavaClass_1].declaration(newTermName("z"))) + } +} + +object Test extends App { + foo.testAll() +} \ No newline at end of file -- cgit v1.2.3