summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-08-23 14:23:48 +0200
committerJason Zaugg <jzaugg@gmail.com>2013-08-23 17:10:56 +0200
commit5dbc37dfbe0e9a039da6744e45012abc3034cdf5 (patch)
tree7d74c9c383d79ae101a1a7ff1073602f96a33683
parent7b351dca8458f599f5fafef4daa307351031ef06 (diff)
downloadscala-5dbc37dfbe0e9a039da6744e45012abc3034cdf5.tar.gz
scala-5dbc37dfbe0e9a039da6744e45012abc3034cdf5.tar.bz2
scala-5dbc37dfbe0e9a039da6744e45012abc3034cdf5.zip
SI-7779 Account for class name compactification in reflection
We have to assume that the classes we are reflecting on were compiled with the default value for -Xmax-classfile-name (255). With this assumption, we can apply the same name compactification as done in the regular compiler. The REPL is particularly prone to generating long class names with the '$iw' prefixes, so this is an important fix for runtime reflection. Also adds support for getting the runtime class of `O.type` if `O` is a module.
-rw-r--r--bincompat-backward.whitelist.conf4
-rw-r--r--bincompat-forward.whitelist.conf12
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala14
-rw-r--r--test/files/run/t7779.scala67
5 files changed, 98 insertions, 0 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf
index 08d972eee1..35b67a13ee 100644
--- a/bincompat-backward.whitelist.conf
+++ b/bincompat-backward.whitelist.conf
@@ -267,6 +267,10 @@ filter {
{
matchName="scala.reflect.internal.SymbolTable.scala$reflect$internal$Trees$$duplicator"
problemName=IncompatibleResultTypeProblem
+ },
+ {
+ matchName="scala.reflect.internal.StdNames.compactifyName"
+ problemName=MissingMethodProblem
}
]
}
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf
index 7fdd4329ea..20e5e30b68 100644
--- a/bincompat-forward.whitelist.conf
+++ b/bincompat-forward.whitelist.conf
@@ -571,6 +571,18 @@ filter {
{
matchName="scala.reflect.internal.SymbolTable.scala$reflect$internal$Trees$$duplicator"
problemName=IncompatibleResultTypeProblem
+ },
+ {
+ matchName="scala.reflect.runtime.JavaMirrors#JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$PackageAndClassPattern"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.internal.SymbolTable.compactifyName"
+ problemName=MissingMethodProblem
+ },
+ {
+ matchName="scala.reflect.internal.StdNames.compactifyName"
+ problemName=MissingMethodProblem
}
]
}
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index de7af4340d..c3b7f24a9d 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -44,6 +44,7 @@ trait StdNames {
}
}
+ private[reflect] def compactifyName(orig: String): String = compactify(orig)
private final object compactify extends (String => String) {
val md5 = MessageDigest.getInstance("MD5")
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 22fe7f098c..6fdb238462 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -1178,6 +1178,17 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
var fullNameOfJavaClass = ownerClazz.getName
if (childOfClass || childOfTopLevel) fullNameOfJavaClass += "$"
fullNameOfJavaClass += clazz.name
+
+ // compactify (see SI-7779)
+ fullNameOfJavaClass = fullNameOfJavaClass match {
+ case PackageAndClassPattern(pack, clazzName) =>
+ // in a package
+ pack + compactifyName(clazzName)
+ case _ =>
+ // in the empty package
+ compactifyName(fullNameOfJavaClass)
+ }
+
if (clazz.isModuleClass) fullNameOfJavaClass += "$"
// println(s"ownerChildren = ${ownerChildren.toList}")
@@ -1187,6 +1198,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
noClass
}
+ private val PackageAndClassPattern = """(.*\.)(.*)$""".r
+
private def expandedName(sym: Symbol): String =
if (sym.isPrivate) nme.expandedName(sym.name.toTermName, sym.owner).toString
else sym.name.toString
@@ -1241,6 +1254,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass)
case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias)
+ case SingleType(_, sym: ModuleSymbol) => classToJava(sym.moduleClass.asClass)
case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
}
}
diff --git a/test/files/run/t7779.scala b/test/files/run/t7779.scala
new file mode 100644
index 0000000000..db32cb751f
--- /dev/null
+++ b/test/files/run/t7779.scala
@@ -0,0 +1,67 @@
+// -Xmax-classfile-length doesn't compress top-level classes.
+// class :::::::::::::::::::::::::::::::::::::::::::::::::
+
+trait Marker
+
+class Short extends Marker
+
+// We just test with member classes
+object O {
+ object ::::::::::::::::::::::::::::::::::::::::::::::::: extends Marker
+}
+class C {
+ class D {
+ class ::::::::::::::::::::::::::::::::::::::::::::::::: extends Marker
+ }
+}
+
+package pack {
+ // abbreviates to: $colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon to $read$$iw$$iw$$colon$colon$colon$colon$colon$colon$colon$colon$$$$c39b3f245029fbed9732fc888d44231b$$$$on$colon$colon$colon$colon$colon$colon$colon$colon$colon$colon
+ // class :::::::::::::::::::::::::::::::::::::::::::::::::
+
+ class Short extends Marker
+
+ // We just test with member classes
+ object O {
+ object ::::::::::::::::::::::::::::::::::::::::::::::::: extends Marker
+ }
+ class C {
+ class D {
+ class ::::::::::::::::::::::::::::::::::::::::::::::::: extends Marker
+ }
+ }
+ package p2 {
+ class Short extends Marker
+
+ object O {
+ object ::::::::::::::::::::::::::::::::::::::::::::::::: extends Marker
+ }
+ class C {
+ class D {
+ class ::::::::::::::::::::::::::::::::::::::::::::::::: extends Marker
+ }
+ }
+ }
+}
+
+
+object Test extends App {
+ import reflect.runtime.universe._
+ def test[T: TypeTag] = {
+ val tt = typeTag[T]
+ val clz = tt.mirror.runtimeClass(tt.tpe)
+ assert(classOf[Marker].isAssignableFrom(clz), clz.toString)
+ }
+
+ test[Short]
+ test[O.:::::::::::::::::::::::::::::::::::::::::::::::::.type]
+ test[C#D#`:::::::::::::::::::::::::::::::::::::::::::::::::`]
+
+ test[pack.Short]
+ test[pack.O.:::::::::::::::::::::::::::::::::::::::::::::::::.type]
+ test[pack.C#D#`:::::::::::::::::::::::::::::::::::::::::::::::::`]
+
+ test[pack.p2.Short]
+ test[pack.p2.O.:::::::::::::::::::::::::::::::::::::::::::::::::.type]
+ test[pack.p2.C#D#`:::::::::::::::::::::::::::::::::::::::::::::::::`]
+}