summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-04-03 07:33:09 -0700
committerPaul Phillips <paulp@improving.org>2013-04-03 07:33:09 -0700
commit1ad75702a6b7e349b79bc7672034d42ecf34d8a1 (patch)
tree9d0043da9610e4664008b87fc0eef85d2299a202 /src
parentb575c1ed131a578a18239e3922c1ea8b7dd188a2 (diff)
parentda7e175b424610c6b416ee3c9f17a5d7cad20c15 (diff)
downloadscala-1ad75702a6b7e349b79bc7672034d42ecf34d8a1.tar.gz
scala-1ad75702a6b7e349b79bc7672034d42ecf34d8a1.tar.bz2
scala-1ad75702a6b7e349b79bc7672034d42ecf34d8a1.zip
Merge pull request #2341 from paulp/pr/java-acc-flags
ClassfileParser work.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala539
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala179
-rw-r--r--src/library/scala/reflect/package.scala14
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala8
-rw-r--r--src/reflect/scala/reflect/internal/JMethodOrConstructor.scala45
-rw-r--r--src/reflect/scala/reflect/internal/JavaAccFlags.scala83
-rw-r--r--src/reflect/scala/reflect/internal/PrivateWithin.scala33
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala185
8 files changed, 592 insertions, 494 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index bc7c129c20..a8a47205dd 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -12,9 +12,11 @@ import java.lang.Integer.toHexString
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.{ ListBuffer, ArrayBuffer }
import scala.annotation.switch
+import scala.reflect.internal.{ JavaAccFlags }
import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs}
import scala.tools.nsc.io.AbstractFile
+
/** This abstract class implements a class file parser.
*
* @author Martin Odersky
@@ -23,6 +25,7 @@ import scala.tools.nsc.io.AbstractFile
abstract class ClassfileParser {
val global: Global
import global._
+ import definitions._
import scala.reflect.internal.ClassfileConstants._
import Flags._
@@ -40,11 +43,31 @@ abstract class ClassfileParser {
protected var classTParams = Map[Name,Symbol]()
protected var srcfile0 : Option[AbstractFile] = None
protected def moduleClass: Symbol = staticModule.moduleClass
+ private var sawPrivateConstructor = false
+
+ private def ownerForFlags(jflags: JavaAccFlags) = if (jflags.isStatic) moduleClass else clazz
def srcfile = srcfile0
+ private def optimized = global.settings.optimise.value
private def currentIsTopLevel = !(currentClass.decodedName containsChar '$')
+ // u1, u2, and u4 are what these data types are called in the JVM spec.
+ // They are an unsigned byte, unsigned char, and unsigned int respectively.
+ // We bitmask u1 into an Int to make sure it's 0-255 (and u1 isn't used
+ // for much beyond tags) but leave u2 alone as it's already unsigned.
+ protected final def u1(): Int = in.nextByte & 0xFF
+ protected final def u2(): Char = in.nextChar
+ protected final def u4(): Int = in.nextInt
+
+ private def readInnerClassFlags() = readClassFlags()
+ private def readClassFlags() = JavaAccFlags classFlags u2
+ private def readMethodFlags() = JavaAccFlags methodFlags u2
+ private def readFieldFlags() = JavaAccFlags fieldFlags u2
+ private def readTypeName() = readName().toTypeName
+ private def readName() = pool getName u2
+ private def readType() = pool getType u2
+
private object unpickler extends scala.reflect.internal.pickling.UnPickler {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
}
@@ -106,68 +129,60 @@ abstract class ClassfileParser {
}
private def parseHeader() {
- val magic = in.nextInt
+ val magic = u4
if (magic != JAVA_MAGIC)
- throw new IOException("class file '" + in.file + "' "
- + "has wrong magic number 0x" + toHexString(magic)
- + ", should be 0x" + toHexString(JAVA_MAGIC))
- val minorVersion = in.nextChar.toInt
- val majorVersion = in.nextChar.toInt
- if ((majorVersion < JAVA_MAJOR_VERSION) ||
- ((majorVersion == JAVA_MAJOR_VERSION) &&
- (minorVersion < JAVA_MINOR_VERSION)))
- throw new IOException("class file '" + in.file + "' "
- + "has unknown version "
- + majorVersion + "." + minorVersion
- + ", should be at least "
- + JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION)
+ abort(s"class file ${in.file} has wrong magic number 0x${toHexString(magic)}")
+
+ val minor, major = u2
+ if (major < JAVA_MAJOR_VERSION || major == JAVA_MAJOR_VERSION && minor < JAVA_MINOR_VERSION)
+ abort(s"class file ${in.file} has unknown version $major.$minor, should be at least $JAVA_MAJOR_VERSION.$JAVA_MINOR_VERSION")
}
class ConstantPool {
- private val len = in.nextChar
- private val starts = new Array[Int](len)
- private val values = new Array[AnyRef](len)
+ private val len = u2
+ private val starts = new Array[Int](len)
+ private val values = new Array[AnyRef](len)
private val internalized = new Array[Name](len)
{ var i = 1
while (i < starts.length) {
starts(i) = in.bp
i += 1
- (in.nextByte.toInt: @switch) match {
- case CONSTANT_UTF8 | CONSTANT_UNICODE =>
- in.skip(in.nextChar)
- case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE=>
- in.skip(2)
- case CONSTANT_METHODHANDLE =>
- in.skip(3)
- case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF
- | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT
- | CONSTANT_INVOKEDYNAMIC =>
- in.skip(4)
- case CONSTANT_LONG | CONSTANT_DOUBLE =>
- in.skip(8)
- i += 1
- case _ =>
- errorBadTag(in.bp - 1)
+ (u1.toInt: @switch) match {
+ case CONSTANT_UTF8 | CONSTANT_UNICODE => in skip u2
+ case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE => in skip 2
+ case CONSTANT_METHODHANDLE => in skip 3
+ case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF => in skip 4
+ case CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT => in skip 4
+ case CONSTANT_INVOKEDYNAMIC => in skip 4
+ case CONSTANT_LONG | CONSTANT_DOUBLE => in skip 8 ; i += 1
+ case _ => errorBadTag(in.bp - 1)
}
}
}
- /** Return the name found at given index. */
- def getName(index: Int): Name = {
- if (index <= 0 || len <= index)
- errorBadIndex(index)
+ def recordAtIndex[T <: AnyRef](value: T, idx: Int): T = {
+ values(idx) = value
+ value
+ }
- values(index) match {
+ def firstExpecting(index: Int, expected: Int): Int = {
+ val start = starts(index)
+ val first = in.buf(start).toInt
+ if (first == expected) start + 1
+ else this errorBadTag start
+ }
+
+ /** Return the name found at given index. */
+ def getName(index: Int): Name = (
+ if (index <= 0 || len <= index) errorBadIndex(index)
+ else values(index) match {
case name: Name => name
- case null =>
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val name = newTermName(in.buf, start + 3, in.getChar(start + 1))
- values(index) = name
- name
+ case _ =>
+ val start = firstExpecting(index, CONSTANT_UTF8)
+ recordAtIndex(newTermName(in.buf, start + 2, in.getChar(start)), index)
}
- }
+ )
/** Return the name found at given index in the constant pool, with '/' replaced by '.'. */
def getExternalName(index: Int): Name = {
@@ -182,28 +197,23 @@ abstract class ClassfileParser {
def getClassSymbol(index: Int): Symbol = {
if (index <= 0 || len <= index) errorBadIndex(index)
- var c = values(index).asInstanceOf[Symbol]
- if (c eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
- val name = getExternalName(in.getChar(start + 1))
- if (nme.isModuleName(name))
- c = rootMirror.getModuleByName(name.dropModule)
- else
- c = classNameToSymbol(name)
-
- values(index) = c
+ values(index) match {
+ case sym: Symbol => sym
+ case _ =>
+ val result = getClassName(index) match {
+ case name if nme.isModuleName(name) => rootMirror getModuleByName name.dropModule
+ case name => classNameToSymbol(name)
+ }
+ recordAtIndex(result, index)
}
- c
}
/** Return the external name of the class info structure found at 'index'.
* Use 'getClassSymbol' if the class is sure to be a top-level class.
*/
def getClassName(index: Int): Name = {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
- getExternalName(in.getChar(start + 1))
+ val start = firstExpecting(index, CONSTANT_CLASS)
+ getExternalName(in getChar start)
}
/** Return the symbol of the class member at `index`.
@@ -279,94 +289,66 @@ abstract class ClassfileParser {
*/
private def getNameAndType(index: Int, ownerTpe: Type): (Name, Type) = {
if (index <= 0 || len <= index) errorBadIndex(index)
- var p = values(index).asInstanceOf[(Name, Type)]
- if (p eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_NAMEANDTYPE) errorBadTag(start)
- val name = getName(in.getChar(start + 1).toInt)
- // create a dummy symbol for method types
- val dummySym = ownerTpe.typeSymbol.newMethod(name.toTermName, ownerTpe.typeSymbol.pos)
- var tpe = getType(dummySym, in.getChar(start + 3).toInt)
-
- // fix the return type, which is blindly set to the class currently parsed
- if (name == nme.CONSTRUCTOR)
- tpe match {
- case MethodType(formals, restpe) =>
- tpe = MethodType(formals, ownerTpe)
+ (values(index): @unchecked) match {
+ case p: ((Name, Type)) => p
+ case _ =>
+ val start = firstExpecting(index, CONSTANT_NAMEANDTYPE)
+ val name = getName(in.getChar(start).toInt)
+ // create a dummy symbol for method types
+ val dummy = ownerTpe.typeSymbol.newMethod(name.toTermName, ownerTpe.typeSymbol.pos)
+ val tpe = getType(dummy, in.getChar(start + 2).toInt)
+ // fix the return type, which is blindly set to the class currently parsed
+ val restpe = tpe match {
+ case MethodType(formals, _) if name == nme.CONSTRUCTOR => MethodType(formals, ownerTpe)
+ case _ => tpe
}
-
- p = (name, tpe)
+ ((name, restpe))
}
- p
}
/** Return the type of a class constant entry. Since
* arrays are considered to be class types, they might
* appear as entries in 'newarray' or 'cast' opcodes.
*/
- def getClassOrArrayType(index: Int): Type = {
+ def getClassOrArrayType(index: Int): Type = (
if (index <= 0 || len <= index) errorBadIndex(index)
- val value = values(index)
- var c: Type = null
- if (value eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
- val name = getExternalName(in.getChar(start + 1))
- if (name.charAt(0) == ARRAY_TAG) {
- c = sigToType(null, name)
- values(index) = c
- } else {
- val sym = classNameToSymbol(name)
- /*if (name.endsWith("$")) definitions.getModule(name.subName(0, name.length - 1))
- else if (name.endsWith("$class")) definitions.getModule(name)
- else definitions.getClass(name)*/
- values(index) = sym
- c = sym.tpe
- }
- } else c = value match {
- case tp: Type => tp
- case cls: Symbol => cls.tpe
+ else values(index) match {
+ case tp: Type => tp
+ case cls: Symbol => cls.tpe_*
+ case _ =>
+ val name = getClassName(index)
+ name charAt 0 match {
+ case ARRAY_TAG => recordAtIndex(sigToType(null, name), index)
+ case _ => recordAtIndex(classNameToSymbol(name), index).tpe_*
+ }
}
- c
- }
-
- def getType(index: Int): Type = getType(null, index)
-
- def getType(sym: Symbol, index: Int): Type =
- sigToType(sym, getExternalName(index))
+ )
- def getSuperClass(index: Int): Symbol =
- if (index == 0) definitions.AnyClass else getClassSymbol(index)
+ def getType(index: Int): Type = getType(null, index)
+ def getType(sym: Symbol, index: Int): Type = sigToType(sym, getExternalName(index))
+ def getSuperClass(index: Int): Symbol = if (index == 0) AnyClass else getClassSymbol(index)
- def getConstant(index: Int): Constant = {
+ private def createConstant(index: Int): Constant = {
+ val start = starts(index)
+ Constant((in.buf(start).toInt: @switch) match {
+ case CONSTANT_STRING => getName(in.getChar(start + 1).toInt).toString
+ case CONSTANT_INTEGER => in.getInt(start + 1)
+ case CONSTANT_FLOAT => in.getFloat(start + 1)
+ case CONSTANT_LONG => in.getLong(start + 1)
+ case CONSTANT_DOUBLE => in.getDouble(start + 1)
+ case CONSTANT_CLASS => getClassOrArrayType(index).typeSymbol.tpe_* // !!! Is this necessary or desirable?
+ case _ => errorBadTag(start)
+ })
+ }
+ def getConstant(index: Int): Constant = (
if (index <= 0 || len <= index) errorBadIndex(index)
- var value = values(index)
- if (value eq null) {
- val start = starts(index)
- value = (in.buf(start).toInt: @switch) match {
- case CONSTANT_STRING =>
- Constant(getName(in.getChar(start + 1).toInt).toString)
- case CONSTANT_INTEGER =>
- Constant(in.getInt(start + 1))
- case CONSTANT_FLOAT =>
- Constant(in.getFloat(start + 1))
- case CONSTANT_LONG =>
- Constant(in.getLong(start + 1))
- case CONSTANT_DOUBLE =>
- Constant(in.getDouble(start + 1))
- case CONSTANT_CLASS =>
- getClassOrArrayType(index).typeSymbol
- case _ =>
- errorBadTag(start)
- }
- values(index) = value
- }
- value match {
- case ct: Constant => ct
- case cls: Symbol => Constant(cls.tpe_*)
- case arr: Type => Constant(arr)
+ else values(index) match {
+ case const: Constant => const
+ case sym: Symbol => Constant(sym.tpe_*)
+ case tpe: Type => Constant(tpe)
+ case _ => recordAtIndex(createConstant(index), index)
}
- }
+ )
private def getSubArray(bytes: Array[Byte]): Array[Byte] = {
val decodedLength = ByteCodecs.decode(bytes)
@@ -375,46 +357,41 @@ abstract class ClassfileParser {
arr
}
- def getBytes(index: Int): Array[Byte] = {
+ def getBytes(index: Int): Array[Byte] = (
if (index <= 0 || len <= index) errorBadIndex(index)
- var value = values(index).asInstanceOf[Array[Byte]]
- if (value eq null) {
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val len = in.getChar(start + 1)
- val bytes = new Array[Byte](len)
- System.arraycopy(in.buf, start + 3, bytes, 0, len)
- value = getSubArray(bytes)
- values(index) = value
+ else values(index) match {
+ case xs: Array[Byte] => xs
+ case _ =>
+ val start = firstExpecting(index, CONSTANT_UTF8)
+ val len = in getChar start
+ val bytes = new Array[Byte](len)
+ System.arraycopy(in.buf, start + 2, bytes, 0, len)
+ recordAtIndex(getSubArray(bytes), index)
}
- value
- }
+ )
def getBytes(indices: List[Int]): Array[Byte] = {
- assert(!indices.isEmpty, indices)
- var value = values(indices.head).asInstanceOf[Array[Byte]]
- if (value eq null) {
- val bytesBuffer = ArrayBuffer.empty[Byte]
- for (index <- indices) {
- if (index <= 0 || ConstantPool.this.len <= index) errorBadIndex(index)
- val start = starts(index)
- if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start)
- val len = in.getChar(start + 1)
- bytesBuffer ++= in.buf.view(start + 3, start + 3 + len)
- }
- value = getSubArray(bytesBuffer.toArray)
- values(indices.head) = value
+ val head = indices.head
+ values(head) match {
+ case xs: Array[Byte] => xs
+ case _ =>
+ val arr: Array[Byte] = indices.toArray flatMap { index =>
+ if (index <= 0 || ConstantPool.this.len <= index) errorBadIndex(index)
+ val start = firstExpecting(index, CONSTANT_UTF8)
+ val len = in getChar start
+ in.buf drop start + 2 take len
+ }
+ recordAtIndex(getSubArray(arr), head)
}
- value
}
/** Throws an exception signaling a bad constant index. */
private def errorBadIndex(index: Int) =
- throw new RuntimeException("bad constant pool index: " + index + " at pos: " + in.bp)
+ abort(s"bad constant pool index: $index at pos: ${in.bp}")
/** Throws an exception signaling a bad tag at given address. */
private def errorBadTag(start: Int) =
- throw new RuntimeException("bad constant pool tag " + in.buf(start) + " at byte " + start)
+ abort("bad constant pool tag ${in.buf(start)} at byte $start")
}
/** Try to force the chain of enclosing classes for the given name. Otherwise
@@ -493,30 +470,27 @@ abstract class ClassfileParser {
catch { case _: FatalError => loadClassSymbol(name) }
}
- var sawPrivateConstructor = false
-
def parseClass() {
- val jflags = in.nextChar
- val isAnnotation = hasAnnotation(jflags)
- val sflags = toScalaClassFlags(jflags)
- val nameIdx = in.nextChar
- currentClass = pool.getClassName(nameIdx)
+ val jflags = readClassFlags()
+ val sflags = jflags.toScalaFlags
+ val nameIdx = u2
+ currentClass = pool.getClassName(nameIdx)
/* Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled.
* Updates the read pointer of 'in'. */
def parseParents: List[Type] = {
if (isScala) {
- in.nextChar // skip superclass
- val ifaces = in.nextChar
- in.bp += ifaces * 2 // .. and iface count interfaces
- List(definitions.AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information
+ u2 // skip superclass
+ val ifaces = u2
+ in.bp += ifaces * 2 // .. and iface count interfaces
+ List(AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information
}
else raiseLoaderLevel {
- val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
- else pool.getSuperClass(in.nextChar).tpe_*
- val ifaceCount = in.nextChar
- var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe_*
- if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
+ val superType = if (jflags.isAnnotation) { u2; AnnotationClass.tpe }
+ else pool.getSuperClass(u2).tpe_*
+ val ifaceCount = u2
+ var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(u2).tpe_*
+ if (jflags.isAnnotation) ifaces ::= ClassfileAnnotationClass.tpe
superType :: ifaces
}
}
@@ -546,21 +520,20 @@ abstract class ClassfileParser {
skipMembers() // methods
if (!isScala) {
clazz setFlag sflags
- importPrivateWithinFromJavaFlags(clazz, jflags)
- importPrivateWithinFromJavaFlags(staticModule, jflags)
- clazz.setInfo(classInfo)
+ propagatePackageBoundary(jflags, clazz, staticModule)
+ clazz setInfo classInfo
moduleClass setInfo staticInfo
- staticModule.setInfo(moduleClass.tpe)
- staticModule.setFlag(JAVA)
- staticModule.moduleClass.setFlag(JAVA)
+ staticModule setInfo moduleClass.tpe
+ staticModule setFlag JAVA
+ staticModule.moduleClass setFlag JAVA
// attributes now depend on having infos set already
parseAttributes(clazz, classInfo)
def queueLoad() {
in.bp = curbp
- 0 until in.nextChar foreach (_ => parseField())
+ 0 until u2 foreach (_ => parseField())
sawPrivateConstructor = false
- 0 until in.nextChar foreach (_ => parseMethod())
+ 0 until u2 foreach (_ => parseMethod())
val needsConstructor = (
!sawPrivateConstructor
&& !(instanceScope containsName nme.CONSTRUCTOR)
@@ -596,28 +569,28 @@ abstract class ClassfileParser {
}
def parseField() {
- val jflags = in.nextChar
- val sflags = toScalaFieldFlags(jflags)
- if ((sflags & PRIVATE) != 0L && !global.settings.optimise) {
+ val jflags = readFieldFlags()
+ val sflags = jflags.toScalaFlags
+
+ if ((sflags & PRIVATE) != 0L && !optimized) {
in.skip(4); skipAttributes()
} else {
- val name = pool.getName(in.nextChar)
- val info = pool.getType(in.nextChar)
- val sym = getOwner(jflags).newValue(name.toTermName, NoPosition, sflags)
- val isEnum = (jflags & JAVA_ACC_ENUM) != 0
+ val name = readName()
+ val info = readType()
+ val sym = ownerForFlags(jflags).newValue(name.toTermName, NoPosition, sflags)
// Note: the info may be overrwritten later with a generic signature
// parsed from SignatureATTR
sym setInfo {
- if (isEnum) ConstantType(Constant(sym))
+ if (jflags.isEnum) ConstantType(Constant(sym))
else info
}
- importPrivateWithinFromJavaFlags(sym, jflags)
+ propagatePackageBoundary(jflags, sym)
parseAttributes(sym, info)
- getScope(jflags).enter(sym)
+ getScope(jflags) enter sym
// sealed java enums
- if (isEnum) {
+ if (jflags.isEnum) {
val enumClass = sym.owner.linkedClassOfClass
if (!enumClass.isSealed)
enumClass setFlag (SEALED | ABSTRACT)
@@ -628,26 +601,27 @@ abstract class ClassfileParser {
}
def parseMethod() {
- val jflags = in.nextChar.toInt
- val sflags = toScalaMethodFlags(jflags)
- if (isPrivate(jflags) && !global.settings.optimise) {
- val name = pool.getName(in.nextChar)
+ val jflags = readMethodFlags()
+ val sflags = jflags.toScalaFlags
+ if (jflags.isPrivate && !optimized) {
+ val name = readName()
if (name == nme.CONSTRUCTOR)
sawPrivateConstructor = true
in.skip(2); skipAttributes()
- } else {
- if ((sflags & PRIVATE) != 0L && global.settings.optimise) {
+ }
+ else {
+ if ((sflags & PRIVATE) != 0L && optimized) {
in.skip(4); skipAttributes()
} else {
- val name = pool.getName(in.nextChar)
- val sym = getOwner(jflags).newMethod(name.toTermName, NoPosition, sflags)
- var info = pool.getType(sym, (in.nextChar))
+ val name = readName()
+ val sym = ownerForFlags(jflags).newMethod(name.toTermName, NoPosition, sflags)
+ var info = pool.getType(sym, u2)
if (name == nme.CONSTRUCTOR)
info match {
case MethodType(params, restpe) =>
// if this is a non-static inner class, remove the explicit outer parameter
val newParams = innerClasses getEntry currentClass match {
- case Some(entry) if !isScalaRaw && !isStatic(entry.jflags) =>
+ case Some(entry) if !isScalaRaw && !entry.jflags.isStatic =>
/* About `clazz.owner.isPackage` below: SI-5957
* For every nested java class A$B, there are two symbols in the scala compiler.
* 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package
@@ -664,13 +638,13 @@ abstract class ClassfileParser {
}
// Note: the info may be overrwritten later with a generic signature
// parsed from SignatureATTR
- sym.setInfo(info)
- importPrivateWithinFromJavaFlags(sym, jflags)
+ sym setInfo info
+ propagatePackageBoundary(jflags, sym)
parseAttributes(sym, info)
- if ((jflags & JAVA_ACC_VARARGS) != 0) {
- sym.setInfo(arrayToRepeated(sym.info))
- }
- getScope(jflags).enter(sym)
+ if (jflags.isVarargs)
+ sym modifyInfo arrayToRepeated
+
+ getScope(jflags) enter sym
}
}
}
@@ -690,15 +664,15 @@ abstract class ClassfileParser {
def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean): Type = {
val tag = sig.charAt(index); index += 1
tag match {
- case BYTE_TAG => definitions.ByteClass.tpe
- case CHAR_TAG => definitions.CharClass.tpe
- case DOUBLE_TAG => definitions.DoubleClass.tpe
- case FLOAT_TAG => definitions.FloatClass.tpe
- case INT_TAG => definitions.IntClass.tpe
- case LONG_TAG => definitions.LongClass.tpe
- case SHORT_TAG => definitions.ShortClass.tpe
- case VOID_TAG => definitions.UnitClass.tpe
- case BOOL_TAG => definitions.BooleanClass.tpe
+ case BYTE_TAG => ByteClass.tpe
+ case CHAR_TAG => CharClass.tpe
+ case DOUBLE_TAG => DoubleClass.tpe
+ case FLOAT_TAG => FloatClass.tpe
+ case INT_TAG => IntClass.tpe
+ case LONG_TAG => LongClass.tpe
+ case SHORT_TAG => ShortClass.tpe
+ case VOID_TAG => UnitClass.tpe
+ case BOOL_TAG => BooleanClass.tpe
case 'L' =>
def processInner(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) if (!sym.isStatic) =>
@@ -723,7 +697,7 @@ abstract class ClassfileParser {
val tp = sig2type(tparams, skiptvs)
// sig2type seems to return AnyClass regardless of the situation:
// we don't want Any as a LOWER bound.
- if (tp.typeSymbol == definitions.AnyClass) TypeBounds.empty
+ if (tp.typeSymbol == AnyClass) TypeBounds.empty
else TypeBounds.lower(tp)
case '*' => TypeBounds.empty
}
@@ -744,7 +718,7 @@ abstract class ClassfileParser {
// or we'll create a boatload of needless existentials.
else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) tp
// raw type - existentially quantify all type parameters
- else logResult(s"raw type from $classSym")(definitions.unsafeClassExistentialType(classSym))
+ else logResult(s"raw type from $classSym")(unsafeClassExistentialType(classSym))
case tp =>
assert(sig.charAt(index) != '<', s"sig=$sig, index=$index, tp=$tp")
tp
@@ -772,11 +746,11 @@ abstract class ClassfileParser {
// NOTE that the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object
// if the bound is exactly Object, it will have been converted to Any, and the comparison will fail
// see also RestrictJavaArraysMap (when compiling java sources directly)
- if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) {
- elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe))
+ if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< ObjectClass.tpe)) {
+ elemtp = intersectionType(List(elemtp, ObjectClass.tpe))
}
- definitions.arrayType(elemtp)
+ arrayType(elemtp)
case '(' =>
// we need a method symbol. given in line 486 by calling getType(methodSym, ..)
assert(sym ne null, sig)
@@ -794,7 +768,7 @@ abstract class ClassfileParser {
case 'T' =>
val n = subName(';'.==).toTypeName
index += 1
- if (skiptvs) definitions.AnyClass.tpe
+ if (skiptvs) AnyClass.tpe
else tparams(n).typeConstructor
}
} // sig2type(tparams, skiptvs)
@@ -847,24 +821,20 @@ abstract class ClassfileParser {
GenPolyType(ownTypeParams, tpe)
} // sigToType
- class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter {
- override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
- }
-
def parseAttributes(sym: Symbol, symtype: Type) {
def convertTo(c: Constant, pt: Type): Constant = {
- if (pt.typeSymbol == definitions.BooleanClass && c.tag == IntTag)
+ if (pt.typeSymbol == BooleanClass && c.tag == IntTag)
Constant(c.value != 0)
else
c convertTo pt
}
def parseAttribute() {
- val attrName = pool.getName(in.nextChar).toTypeName
- val attrLen = in.nextInt
+ val attrName = readTypeName()
+ val attrLen = u4
attrName match {
case tpnme.SignatureATTR =>
if (!isScala && !isScalaRaw) {
- val sig = pool.getExternalName(in.nextChar)
+ val sig = pool.getExternalName(u2)
val newType = sigToType(sym, sig)
sym.setInfo(newType)
if (settings.debug && settings.verbose)
@@ -879,10 +849,10 @@ abstract class ClassfileParser {
in.skip(attrLen)
case tpnme.DeprecatedATTR =>
val arg = Literal(Constant("see corresponding Javadoc for more information."))
- sym.addAnnotation(definitions.DeprecatedAttr, arg, Literal(Constant("")))
+ sym.addAnnotation(DeprecatedAttr, arg, Literal(Constant("")))
in.skip(attrLen)
case tpnme.ConstantValueATTR =>
- val c = pool.getConstant(in.nextChar)
+ val c = pool.getConstant(u2)
val c1 = convertTo(c, symtype)
if (c1 ne null) sym.setInfo(ConstantType(c1))
else println("failure to convert " + c + " to " + symtype); //debug
@@ -896,7 +866,7 @@ abstract class ClassfileParser {
isScalaRaw = true
// Attribute on methods of java annotation classes when that method has a default
case tpnme.AnnotationDefaultATTR =>
- sym.addAnnotation(definitions.AnnotationDefaultAttr)
+ sym.addAnnotation(AnnotationDefaultAttr)
in.skip(attrLen)
// Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME
case tpnme.RuntimeAnnotationATTR =>
@@ -926,7 +896,7 @@ abstract class ClassfileParser {
parseExceptions(attrLen)
case tpnme.SourceFileATTR =>
- val srcfileLeaf = pool.getName(in.nextChar).toString.trim
+ val srcfileLeaf = readName().toString.trim
val srcpath = sym.enclosingPackage match {
case NoSymbol => srcfileLeaf
case rootMirror.EmptyPackage => srcfileLeaf
@@ -939,8 +909,8 @@ abstract class ClassfileParser {
}
def parseAnnotArg: Option[ClassfileAnnotArg] = {
- val tag = in.nextByte.toChar
- val index = in.nextChar
+ val tag = u1
+ val index = u2
tag match {
case STRING_TAG =>
Some(LiteralAnnotArg(Constant(pool.getName(index).toString)))
@@ -951,7 +921,7 @@ abstract class ClassfileParser {
Some(LiteralAnnotArg(Constant(pool.getType(index))))
case ENUM_TAG =>
val t = pool.getType(index)
- val n = pool.getName(in.nextChar)
+ val n = readName()
val s = t.typeSymbol.companionModule.info.decls.lookup(n)
assert(s != NoSymbol, t)
Some(LiteralAnnotArg(Constant(s)))
@@ -971,20 +941,20 @@ abstract class ClassfileParser {
}
def parseScalaSigBytes: Option[ScalaSigBytes] = {
- val tag = in.nextByte.toChar
+ val tag = u1
assert(tag == STRING_TAG, tag)
- Some(ScalaSigBytes(pool getBytes in.nextChar))
+ Some(ScalaSigBytes(pool getBytes u2))
}
def parseScalaLongSigBytes: Option[ScalaSigBytes] = {
- val tag = in.nextByte.toChar
+ val tag = u1
assert(tag == ARRAY_TAG, tag)
- val stringCount = in.nextChar
+ val stringCount = u2
val entries =
for (i <- 0 until stringCount) yield {
- val stag = in.nextByte.toChar
+ val stag = u1
assert(stag == STRING_TAG, stag)
- in.nextChar.toInt
+ u2.toInt
}
Some(ScalaSigBytes(pool.getBytes(entries.toList)))
}
@@ -994,20 +964,20 @@ abstract class ClassfileParser {
*/
def parseAnnotation(attrNameIndex: Char): Option[AnnotationInfo] = try {
val attrType = pool.getType(attrNameIndex)
- val nargs = in.nextChar
+ val nargs = u2
val nvpairs = new ListBuffer[(Name, ClassfileAnnotArg)]
var hasError = false
for (i <- 0 until nargs) {
- val name = pool.getName(in.nextChar)
+ val name = readName()
// The "bytes: String" argument of the ScalaSignature attribute is parsed specially so that it is
// available as an array of bytes (the pickled Scala signature) instead of as a string. The pickled signature
// is encoded as a string because of limitations in the Java class file format.
- if ((attrType == definitions.ScalaSignatureAnnotation.tpe) && (name == nme.bytes))
+ if ((attrType == ScalaSignatureAnnotation.tpe) && (name == nme.bytes))
parseScalaSigBytes match {
case Some(c) => nvpairs += ((name, c))
case None => hasError = true
}
- else if ((attrType == definitions.ScalaLongSignatureAnnotation.tpe) && (name == nme.bytes))
+ else if ((attrType == ScalaLongSignatureAnnotation.tpe) && (name == nme.bytes))
parseScalaLongSigBytes match {
case Some(c) => nvpairs += ((name, c))
case None => hasError = true
@@ -1040,10 +1010,10 @@ abstract class ClassfileParser {
* thrown by a method.
*/
def parseExceptions(len: Int) {
- val nClasses = in.nextChar
+ val nClasses = u2
for (n <- 0 until nClasses) {
// FIXME: this performs an equivalent of getExceptionTypes instead of getGenericExceptionTypes (SI-7065)
- val cls = pool.getClassSymbol(in.nextChar.toInt)
+ val cls = pool.getClassSymbol(u2)
// we call initialize due to the fact that we call Symbol.isMonomorphicType in addThrowsAnnotation
// and that method requires Symbol to be forced to give the right answers, see SI-7107 for details
cls.initialize
@@ -1054,13 +1024,13 @@ abstract class ClassfileParser {
/* Parse a sequence of annotations and attaches them to the
* current symbol sym, except for the ScalaSignature annotation that it returns, if it is available. */
def parseAnnotations(len: Int): Option[AnnotationInfo] = {
- val nAttr = in.nextChar
+ val nAttr = u2
var scalaSigAnnot: Option[AnnotationInfo] = None
for (n <- 0 until nAttr)
- parseAnnotation(in.nextChar) match {
- case Some(scalaSig) if (scalaSig.atp == definitions.ScalaSignatureAnnotation.tpe) =>
+ parseAnnotation(u2) match {
+ case Some(scalaSig) if (scalaSig.atp == ScalaSignatureAnnotation.tpe) =>
scalaSigAnnot = Some(scalaSig)
- case Some(scalaSig) if (scalaSig.atp == definitions.ScalaLongSignatureAnnotation.tpe) =>
+ case Some(scalaSig) if (scalaSig.atp == ScalaLongSignatureAnnotation.tpe) =>
scalaSigAnnot = Some(scalaSig)
case Some(annot) =>
sym.addAnnotation(annot)
@@ -1070,7 +1040,7 @@ abstract class ClassfileParser {
}
// begin parseAttributes
- for (i <- 0 until in.nextChar) parseAttribute()
+ for (i <- 0 until u2) parseAttribute()
}
/** Enter own inner classes in the right scope. It needs the scopes to be set up,
@@ -1080,11 +1050,12 @@ abstract class ClassfileParser {
def className(name: Name): Name =
name.subName(name.lastPos('.') + 1, name.length)
- def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) {
+ def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile) {
+ def jflags = entry.jflags
val completer = new global.loaders.ClassfileLoader(file)
val name = entry.originalName
- val sflags = toScalaClassFlags(jflags)
- val owner = getOwner(jflags)
+ val sflags = jflags.toScalaFlags
+ val owner = ownerForFlags(jflags)
val scope = getScope(jflags)
val innerClass = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer
val innerModule = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer
@@ -1113,7 +1084,7 @@ abstract class ClassfileParser {
val file = global.classPath.findSourceFile(entry.externalName.toString) getOrElse {
throw new AssertionError(entry.externalName)
}
- enterClassAndModule(entry, file, entry.jflags)
+ enterClassAndModule(entry, file)
}
}
}
@@ -1126,10 +1097,10 @@ abstract class ClassfileParser {
skipSuperclasses()
skipMembers() // fields
skipMembers() // methods
- val attrs = in.nextChar
+ val attrs = u2
for (i <- 0 until attrs) {
- val attrName = pool.getName(in.nextChar).toTypeName
- val attrLen = in.nextInt
+ val attrName = readTypeName()
+ val attrLen = u4
attrName match {
case tpnme.SignatureATTR =>
in.skip(attrLen)
@@ -1143,9 +1114,10 @@ abstract class ClassfileParser {
case tpnme.ScalaATTR =>
isScalaRaw = true
case tpnme.InnerClassesATTR if !isScala =>
- val entries = in.nextChar.toInt
+ val entries = u2
for (i <- 0 until entries) {
- val innerIndex, outerIndex, nameIndex, jflags = in.nextChar.toInt
+ val innerIndex, outerIndex, nameIndex = u2
+ val jflags = readInnerClassFlags()
if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0)
innerClasses add InnerClassEntry(innerIndex, outerIndex, nameIndex, jflags)
}
@@ -1157,14 +1129,13 @@ abstract class ClassfileParser {
}
/** An entry in the InnerClasses attribute of this class file. */
- case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: Int) {
+ case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: JavaAccFlags) {
def externalName = pool getClassName external
def outerName = pool getClassName outer
def originalName = pool getName name
- def isStatic = ClassfileParser.this.isStatic(jflags)
def isModule = originalName.isTermName
- def scope = if (isStatic) staticScope else instanceScope
- def enclosing = if (isStatic) enclModule else enclClass
+ def scope = if (jflags.isStatic) staticScope else instanceScope
+ def enclosing = if (jflags.isStatic) enclModule else enclClass
// The name of the outer class, without its trailing $ if it has one.
private def strippedOuter = nme stripModuleSuffix outerName
@@ -1216,6 +1187,9 @@ abstract class ClassfileParser {
}
}
+ class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter {
+ override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
+ }
class LazyAliasType(alias: Symbol) extends LazyType with FlagAgnosticCompleter {
override def complete(sym: Symbol) {
sym setInfo createFromClonedSymbols(alias.initialize.typeParams, alias.tpe)(typeFun)
@@ -1223,16 +1197,16 @@ abstract class ClassfileParser {
}
def skipAttributes() {
- var attrCount: Int = in.nextChar
+ var attrCount: Int = u2
while (attrCount > 0) {
in skip 2
- in skip in.nextInt
+ in skip u4
attrCount -= 1
}
}
def skipMembers() {
- var memberCount: Int = in.nextChar
+ var memberCount: Int = u2
while (memberCount > 0) {
in skip 6
skipAttributes()
@@ -1242,17 +1216,10 @@ abstract class ClassfileParser {
def skipSuperclasses() {
in.skip(2) // superclass
- val ifaces = in.nextChar
+ val ifaces = u2
in.skip(2 * ifaces)
}
- protected def getOwner(flags: Int): Symbol =
- if (isStatic(flags)) moduleClass else clazz
-
- protected def getScope(flags: Int): Scope =
- if (isStatic(flags)) staticScope else instanceScope
-
- 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
+ protected def getScope(flags: JavaAccFlags): Scope =
+ if (flags.isStatic) staticScope else instanceScope
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 80a810703c..50487ad123 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -10,6 +10,7 @@ package classfile
import scala.collection.{ mutable, immutable }
import mutable.ListBuffer
import ClassfileConstants._
+import scala.reflect.internal.JavaAccFlags
/** ICode reader from Java bytecode.
*
@@ -45,26 +46,19 @@ abstract class ICodeReader extends ClassfileParser {
(staticCode, instanceCode)
}
- /** If we're parsing a scala module, the owner of members is always
- * the module symbol.
- */
- override def getOwner(jflags: Int): Symbol =
- if (isScalaModule) this.staticModule
- else super.getOwner(jflags)
-
override def parseClass() {
this.instanceCode = new IClass(clazz)
this.staticCode = new IClass(staticModule)
- in.nextChar
- pool getClassSymbol in.nextChar
+ u2
+ pool getClassSymbol u2
parseInnerClasses()
in.skip(2) // super class
- in.skip(2 * in.nextChar) // interfaces
- val fieldCount = in.nextChar
+ in.skip(2 * u2) // interfaces
+ val fieldCount = u2
for (i <- 0 until fieldCount) parseField()
- val methodCount = in.nextChar
+ val methodCount = u2
for (i <- 0 until methodCount) parseMethod()
instanceCode.methods = instanceCode.methods.reverse
staticCode.methods = staticCode.methods.reverse
@@ -76,25 +70,31 @@ abstract class ICodeReader extends ClassfileParser {
skipAttributes()
}
- private def parseMember(field: Boolean): (Int, Symbol) = {
- val jflags = in.nextChar
- val name = pool getName in.nextChar
- val owner = getOwner(jflags)
- val dummySym = owner.newMethod(name.toTermName, owner.pos, toScalaMethodFlags(jflags))
+ private def parseMember(field: Boolean): (JavaAccFlags, Symbol) = {
+ val jflags = JavaAccFlags(u2)
+ val name = pool getName u2
+ /** If we're parsing a scala module, the owner of members is always
+ * the module symbol.
+ */
+ val owner = (
+ if (isScalaModule) staticModule
+ else if (jflags.isStatic) moduleClass
+ else clazz
+ )
+ val dummySym = owner.newMethod(name.toTermName, owner.pos, jflags.toScalaFlags)
try {
- val ch = in.nextChar
+ val ch = u2
val tpe = pool.getType(dummySym, ch)
if ("<clinit>" == name.toString)
(jflags, NoSymbol)
else {
- val owner = getOwner(jflags)
var sym = owner.info.findMember(name, 0, 0, stableOnly = false).suchThat(old => sameType(old.tpe, tpe))
if (sym == NoSymbol)
sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe)
if (sym == NoSymbol) {
- sym = if (field) owner.newValue(name.toTermName, owner.pos, toScalaFieldFlags(jflags)) else dummySym
+ sym = if (field) owner.newValue(name.toTermName, owner.pos, jflags.toScalaFlags) else dummySym
sym setInfoAndEnter tpe
log(s"ICodeReader could not locate ${name.decode} in $owner. Created ${sym.defString}.")
}
@@ -126,9 +126,9 @@ abstract class ICodeReader extends ClassfileParser {
this.method = new IMethod(sym)
this.method.returnType = toTypeKind(sym.tpe.resultType)
getCode(jflags).addMethod(this.method)
- if ((jflags & JAVA_ACC_NATIVE) != 0)
+ if (jflags.isNative)
this.method.native = true
- val attributeCount = in.nextChar
+ val attributeCount = u2
for (i <- 0 until attributeCount) parseAttribute()
} else {
debuglog("Skipping non-existent method.")
@@ -142,8 +142,8 @@ abstract class ICodeReader extends ClassfileParser {
}
def parseAttribute() {
- val attrName = pool.getName(in.nextChar).toTypeName
- val attrLen = in.nextInt
+ val attrName = pool.getName(u2).toTypeName
+ val attrLen = u4
attrName match {
case tpnme.CodeATTR =>
parseByteCode()
@@ -187,9 +187,9 @@ abstract class ICodeReader extends ClassfileParser {
/** Parse java bytecode into ICode */
def parseByteCode() {
- maxStack = in.nextChar
- maxLocals = in.nextChar
- val codeLength = in.nextInt
+ maxStack = u2
+ maxLocals = u2
+ val codeLength = u4
val code = new LinearCode
def parseInstruction() {
@@ -200,7 +200,7 @@ abstract class ICodeReader extends ClassfileParser {
/* Parse 16 bit jump target. */
def parseJumpTarget = {
size += 2
- val offset = in.nextChar.toShort
+ val offset = u2.toShort
val target = pc + offset
assert(target >= 0 && target < codeLength, "Illegal jump target: " + target)
target
@@ -209,14 +209,13 @@ abstract class ICodeReader extends ClassfileParser {
/* Parse 32 bit jump target. */
def parseJumpTargetW: Int = {
size += 4
- val offset = in.nextInt
+ val offset = u4
val target = pc + offset
assert(target >= 0 && target < codeLength, "Illegal jump target: " + target + "pc: " + pc + " offset: " + offset)
target
}
- val instr = toUnsignedByte(in.nextByte)
- instr match {
+ u1 match {
case JVM.nop => parseInstruction()
case JVM.aconst_null => code emit CONSTANT(Constant(null))
case JVM.iconst_m1 => code emit CONSTANT(Constant(-1))
@@ -235,17 +234,17 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.dconst_0 => code emit CONSTANT(Constant(0.0))
case JVM.dconst_1 => code emit CONSTANT(Constant(1.0))
- case JVM.bipush => code.emit(CONSTANT(Constant(in.nextByte))); size += 1
- case JVM.sipush => code.emit(CONSTANT(Constant(in.nextChar))); size += 2
- case JVM.ldc => code.emit(CONSTANT(pool.getConstant(toUnsignedByte(in.nextByte)))); size += 1
- case JVM.ldc_w => code.emit(CONSTANT(pool.getConstant(in.nextChar))); size += 2
- case JVM.ldc2_w => code.emit(CONSTANT(pool.getConstant(in.nextChar))); size += 2
- case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, INT))); size += 1
- case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, LONG))); size += 1
- case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, FLOAT))); size += 1
- case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, DOUBLE))); size += 1
+ case JVM.bipush => code.emit(CONSTANT(Constant(u1))); size += 1
+ case JVM.sipush => code.emit(CONSTANT(Constant(u2))); size += 2
+ case JVM.ldc => code.emit(CONSTANT(pool.getConstant(u1))); size += 1
+ case JVM.ldc_w => code.emit(CONSTANT(pool.getConstant(u2))); size += 2
+ case JVM.ldc2_w => code.emit(CONSTANT(pool.getConstant(u2))); size += 2
+ case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(u1, INT))); size += 1
+ case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(u1, LONG))); size += 1
+ case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(u1, FLOAT))); size += 1
+ case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(u1, DOUBLE))); size += 1
case JVM.aload =>
- val local = in.nextByte.toInt; size += 1
+ val local = u1.toInt; size += 1
if (local == 0 && !method.isStatic)
code.emit(THIS(method.symbol.owner))
else
@@ -285,11 +284,11 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.caload => code.emit(LOAD_ARRAY_ITEM(CHAR))
case JVM.saload => code.emit(LOAD_ARRAY_ITEM(SHORT))
- case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, INT))); size += 1
- case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, LONG))); size += 1
- case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, FLOAT))); size += 1
- case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, DOUBLE))); size += 1
- case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, ObjectReference))); size += 1
+ case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(u1, INT))); size += 1
+ case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(u1, LONG))); size += 1
+ case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(u1, FLOAT))); size += 1
+ case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(u1, DOUBLE))); size += 1
+ case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(u1, ObjectReference))); size += 1
case JVM.istore_0 => code.emit(STORE_LOCAL(code.getLocal(0, INT)))
case JVM.istore_1 => code.emit(STORE_LOCAL(code.getLocal(1, INT)))
case JVM.istore_2 => code.emit(STORE_LOCAL(code.getLocal(2, INT)))
@@ -373,9 +372,9 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.lxor => code.emit(CALL_PRIMITIVE(Logical(XOR, LONG)))
case JVM.iinc =>
size += 2
- val local = code.getLocal(in.nextByte, INT)
+ val local = code.getLocal(u1, INT)
code.emit(LOAD_LOCAL(local))
- code.emit(CONSTANT(Constant(in.nextByte)))
+ code.emit(CONSTANT(Constant(u1)))
code.emit(CALL_PRIMITIVE(Arithmetic(ADD, INT)))
code.emit(STORE_LOCAL(local))
@@ -425,14 +424,14 @@ abstract class ICodeReader extends ClassfileParser {
size += padding
in.bp += padding
assert((pc + size % 4) != 0, pc)
-/* var byte1 = in.nextByte; size += 1;
- while (byte1 == 0) { byte1 = in.nextByte; size += 1; }
- val default = byte1 << 24 | in.nextByte << 16 | in.nextByte << 8 | in.nextByte;
+/* var byte1 = u1; size += 1;
+ while (byte1 == 0) { byte1 = u1; size += 1; }
+ val default = byte1 << 24 | u1 << 16 | u1 << 8 | u1;
size = size + 3
*/
- val default = pc + in.nextInt; size += 4
- val low = in.nextInt
- val high = in.nextInt
+ val default = pc + u4; size += 4
+ val low = u4
+ val high = u4
size += 8
assert(low <= high, "Value low not <= high for tableswitch.")
@@ -445,13 +444,13 @@ abstract class ICodeReader extends ClassfileParser {
size += padding
in.bp += padding
assert((pc + size % 4) != 0, pc)
- val default = pc + in.nextInt; size += 4
- val npairs = in.nextInt; size += 4
+ val default = pc + u4; size += 4
+ val npairs = u4; size += 4
var tags: List[List[Int]] = Nil
var targets: List[Int] = Nil
var i = 0
while (i < npairs) {
- tags = List(in.nextInt) :: tags; size += 4
+ tags = List(u4) :: tags; size += 4
targets = parseJumpTargetW :: targets; // parseJumpTargetW updates 'size' itself
i += 1
}
@@ -466,35 +465,35 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.return_ => code.emit(RETURN(UNIT))
case JVM.getstatic =>
- val field = pool.getMemberSymbol(in.nextChar, static = true); size += 2
+ val field = pool.getMemberSymbol(u2, static = true); size += 2
if (field.hasModuleFlag)
code emit LOAD_MODULE(field)
else
code emit LOAD_FIELD(field, isStatic = true)
case JVM.putstatic =>
- val field = pool.getMemberSymbol(in.nextChar, static = true); size += 2
+ val field = pool.getMemberSymbol(u2, static = true); size += 2
code.emit(STORE_FIELD(field, isStatic = true))
case JVM.getfield =>
- val field = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val field = pool.getMemberSymbol(u2, static = false); size += 2
code.emit(LOAD_FIELD(field, isStatic = false))
case JVM.putfield =>
- val field = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val field = pool.getMemberSymbol(u2, static = false); size += 2
code.emit(STORE_FIELD(field, isStatic = false))
case JVM.invokevirtual =>
- val m = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val m = pool.getMemberSymbol(u2, static = false); size += 2
code.emit(CALL_METHOD(m, Dynamic))
case JVM.invokeinterface =>
- val m = pool.getMemberSymbol(in.nextChar, static = false); size += 4
+ val m = pool.getMemberSymbol(u2, static = false); size += 4
in.skip(2)
code.emit(CALL_METHOD(m, Dynamic))
case JVM.invokespecial =>
- val m = pool.getMemberSymbol(in.nextChar, static = false); size += 2
+ val m = pool.getMemberSymbol(u2, static = false); size += 2
val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(onInstance = true)
else SuperCall(m.owner.name)
code.emit(CALL_METHOD(m, style))
case JVM.invokestatic =>
- val m = pool.getMemberSymbol(in.nextChar, static = true); size += 2
+ val m = pool.getMemberSymbol(u2, static = true); size += 2
if (isBox(m))
code.emit(BOX(toTypeKind(m.info.paramTypes.head)))
else if (isUnbox(m))
@@ -510,10 +509,10 @@ abstract class ICodeReader extends ClassfileParser {
code.emit(INVOKE_DYNAMIC(poolEntry))
case JVM.new_ =>
- code.emit(NEW(REFERENCE(pool.getClassSymbol(in.nextChar))))
+ code.emit(NEW(REFERENCE(pool.getClassSymbol(u2))))
size += 2
case JVM.newarray =>
- val kind = in.nextByte match {
+ val kind = u1 match {
case T_BOOLEAN => BOOL
case T_CHAR => CHAR
case T_FLOAT => FLOAT
@@ -527,35 +526,35 @@ abstract class ICodeReader extends ClassfileParser {
code.emit(CREATE_ARRAY(kind, 1))
case JVM.anewarray =>
- val tpe = pool.getClassOrArrayType(in.nextChar); size += 2
+ val tpe = pool.getClassOrArrayType(u2); size += 2
code.emit(CREATE_ARRAY(toTypeKind(tpe), 1))
case JVM.arraylength => code.emit(CALL_PRIMITIVE(ArrayLength(ObjectReference))); // the kind does not matter
case JVM.athrow => code.emit(THROW(definitions.ThrowableClass))
case JVM.checkcast =>
- code.emit(CHECK_CAST(toTypeKind(pool.getClassOrArrayType(in.nextChar)))); size += 2
+ code.emit(CHECK_CAST(toTypeKind(pool.getClassOrArrayType(u2)))); size += 2
case JVM.instanceof =>
- code.emit(IS_INSTANCE(toTypeKind(pool.getClassOrArrayType(in.nextChar)))); size += 2
+ code.emit(IS_INSTANCE(toTypeKind(pool.getClassOrArrayType(u2)))); size += 2
case JVM.monitorenter => code.emit(MONITOR_ENTER())
case JVM.monitorexit => code.emit(MONITOR_EXIT())
case JVM.wide =>
size += 1
- toUnsignedByte(in.nextByte) match {
- case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, INT))); size += 2
- case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, LONG))); size += 2
- case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, FLOAT))); size += 2
- case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, DOUBLE))); size += 2
- case JVM.aload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, ObjectReference))); size += 2
- case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, INT))); size += 2
- case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, LONG))); size += 2
- case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, FLOAT))); size += 2
- case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, DOUBLE))); size += 2
- case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, ObjectReference))); size += 2
+ u1 match {
+ case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(u2, INT))); size += 2
+ case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(u2, LONG))); size += 2
+ case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(u2, FLOAT))); size += 2
+ case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(u2, DOUBLE))); size += 2
+ case JVM.aload => code.emit(LOAD_LOCAL(code.getLocal(u2, ObjectReference))); size += 2
+ case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(u2, INT))); size += 2
+ case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(u2, LONG))); size += 2
+ case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(u2, FLOAT))); size += 2
+ case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(u2, DOUBLE))); size += 2
+ case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(u2, ObjectReference))); size += 2
case JVM.ret => sys.error("Cannot handle jsr/ret")
case JVM.iinc =>
size += 4
- val local = code.getLocal(in.nextChar, INT)
- code.emit(CONSTANT(Constant(in.nextChar)))
+ val local = code.getLocal(u2, INT)
+ code.emit(CONSTANT(Constant(u2)))
code.emit(CALL_PRIMITIVE(Arithmetic(ADD, INT)))
code.emit(STORE_LOCAL(local))
case _ => sys.error("Invalid 'wide' operand")
@@ -563,8 +562,8 @@ abstract class ICodeReader extends ClassfileParser {
case JVM.multianewarray =>
size += 3
- val tpe = toTypeKind(pool getClassOrArrayType in.nextChar)
- val dim = in.nextByte
+ val tpe = toTypeKind(pool getClassOrArrayType u2)
+ val dim = u1
// assert(dim == 1, "Cannot handle multidimensional arrays yet.")
code emit CREATE_ARRAY(tpe, dim)
@@ -590,14 +589,14 @@ abstract class ICodeReader extends ClassfileParser {
pc = 0
while (pc < codeLength) parseInstruction()
- val exceptionEntries = in.nextChar.toInt
+ val exceptionEntries = u2.toInt
code.containsEHs = (exceptionEntries != 0)
var i = 0
while (i < exceptionEntries) {
// skip start end PC
in.skip(4)
// read the handler PC
- code.jmpTargets += in.nextChar
+ code.jmpTargets += u2
// skip the exception type
in.skip(2)
i += 1
@@ -633,10 +632,8 @@ abstract class ICodeReader extends ClassfileParser {
/** Return the icode class that should include members with the given flags.
* There are two possible classes, the static part and the instance part.
*/
- def getCode(flags: Int): IClass =
- if (isScalaModule) staticCode
- else if ((flags & JAVA_ACC_STATIC) != 0) staticCode
- else instanceCode
+ def getCode(flags: JavaAccFlags): IClass =
+ if (isScalaModule || flags.isStatic) staticCode else instanceCode
class LinearCode {
val instrs: ListBuffer[(Int, Instruction)] = new ListBuffer
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 10e6d7d9a4..97d7da3f2d 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -1,5 +1,7 @@
package scala
+import java.lang.reflect.{ AccessibleObject => jAccessibleObject }
+
package object reflect {
// in the new scheme of things ClassManifests are aliased to ClassTags
@@ -42,6 +44,18 @@ package object reflect {
def classTag[T](implicit ctag: ClassTag[T]) = ctag
+ /** Make a java reflection object accessible, if it is not already
+ * and it is possible to do so. If a SecurityException is thrown in the
+ * attempt, it is caught and discarded.
+ */
+ def ensureAccessible[T <: jAccessibleObject](m: T): T = {
+ if (!m.isAccessible) {
+ try m setAccessible true
+ catch { case _: SecurityException => } // does nothing
+ }
+ m
+ }
+
// anchor for the class tag materialization macro emitted during tag materialization in Implicits.scala
// implementation is hardwired into `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 753dd0205e..ea1f392e2b 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -158,13 +158,7 @@ object ScalaRunTime {
// Java bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4071957
// More background at ticket #2318.
- def ensureAccessible(m: JMethod): JMethod = {
- if (!m.isAccessible) {
- try m setAccessible true
- catch { case _: SecurityException => () }
- }
- m
- }
+ def ensureAccessible(m: JMethod): JMethod = scala.reflect.ensureAccessible(m)
def checkInitialized[T <: AnyRef](x: T): T =
if (x == null) throw new UninitializedError else x
diff --git a/src/reflect/scala/reflect/internal/JMethodOrConstructor.scala b/src/reflect/scala/reflect/internal/JMethodOrConstructor.scala
new file mode 100644
index 0000000000..3d1d1bf451
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/JMethodOrConstructor.scala
@@ -0,0 +1,45 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.reflect
+package internal
+
+import java.lang.{ Class => jClass }
+import java.lang.annotation.{ Annotation => jAnnotation }
+import java.lang.reflect.{
+ Member => jMember, Constructor => jConstructor, Method => jMethod,
+ AnnotatedElement => jAnnotatedElement, Type => jType,
+ TypeVariable => jTypeVariable
+}
+
+/** This class tries to abstract over some of the duplication
+ * in java.lang.reflect.{ Method, Constructor }.
+ */
+class JMethodOrConstructor(val member: jMember with jAnnotatedElement) {
+ def isVarArgs: Boolean = member match {
+ case m: jMethod => m.isVarArgs
+ case m: jConstructor[_] => m.isVarArgs
+ }
+ def typeParams: Array[_ <: jTypeVariable[_]] = member match {
+ case m: jMethod => m.getTypeParameters
+ case m: jConstructor[_] => m.getTypeParameters
+ }
+ def paramTypes: Array[jType] = member match {
+ case m: jMethod => m.getGenericParameterTypes
+ case m: jConstructor[_] => m.getGenericParameterTypes
+ }
+ def paramAnnotations: Array[Array[jAnnotation]] = member match {
+ case m: jMethod => m.getParameterAnnotations
+ case m: jConstructor[_] => m.getParameterAnnotations
+ }
+ def resultType: jType = member match {
+ case m: jMethod => m.getGenericReturnType
+ case m: jConstructor[_] => classOf[Unit]
+ }
+}
+
+object JMethodOrConstructor {
+ implicit def liftMethodToJmoc(m: jMethod): JMethodOrConstructor = new JMethodOrConstructor(m)
+ implicit def liftConstructorToJmoc(m: jConstructor[_]): JMethodOrConstructor = new JMethodOrConstructor(m)
+}
diff --git a/src/reflect/scala/reflect/internal/JavaAccFlags.scala b/src/reflect/scala/reflect/internal/JavaAccFlags.scala
new file mode 100644
index 0000000000..4be1f828d3
--- /dev/null
+++ b/src/reflect/scala/reflect/internal/JavaAccFlags.scala
@@ -0,0 +1,83 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Paul Phillips
+ */
+package scala.reflect
+package internal
+
+import java.lang.{ Class => jClass }
+import java.lang.reflect.{ Member => jMember, Constructor => jConstructor, Field => jField, Method => jMethod }
+import JavaAccFlags._
+import ClassfileConstants._
+
+/** A value class which encodes the access_flags (JVMS 4.1)
+ * for a field, method, or class. The low 16 bits are the same
+ * as those returned by java.lang.reflect.Member#getModifiers
+ * and found in the bytecode.
+ *
+ * The high bits encode whether the access flags are directly
+ * associated with a class, constructor, field, or method.
+ */
+final class JavaAccFlags private (val coded: Int) extends AnyVal {
+ private def has(mask: Int) = (flags & mask) != 0
+ private def flagCarrierId = coded >>> 16
+ private def flags = coded & 0xFFFF
+
+ def isAbstract = has(JAVA_ACC_ABSTRACT)
+ def isAnnotation = has(JAVA_ACC_ANNOTATION)
+ def isBridge = has(JAVA_ACC_BRIDGE)
+ def isEnum = has(JAVA_ACC_ENUM)
+ def isFinal = has(JAVA_ACC_FINAL)
+ def isInterface = has(JAVA_ACC_INTERFACE)
+ def isNative = has(JAVA_ACC_NATIVE)
+ def isPrivate = has(JAVA_ACC_PRIVATE)
+ def isProtected = has(JAVA_ACC_PROTECTED)
+ def isPublic = has(JAVA_ACC_PUBLIC)
+ def isStatic = has(JAVA_ACC_STATIC)
+ def isStrictFp = has(JAVA_ACC_STRICT)
+ def isSuper = has(JAVA_ACC_SUPER)
+ def isSynchronized = has(JAVA_ACC_SYNCHRONIZED)
+ def isSynthetic = has(JAVA_ACC_SYNTHETIC)
+ def isTransient = has(JAVA_ACC_TRANSIENT)
+ def isVarargs = has(JAVA_ACC_VARARGS)
+ def isVolatile = has(JAVA_ACC_VOLATILE)
+
+ /** Do these flags describe a member which has either protected or package access?
+ * Such access in java is encoded in scala as protected[foo] or private[foo], where
+ * `foo` is the defining package.
+ */
+ def hasPackageAccessBoundary = !has(JAVA_ACC_PRIVATE | JAVA_ACC_PUBLIC) // equivalently, allows protected or package level access
+ def isPackageProtected = !has(JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)
+
+ def toJavaFlags: Int = flags
+ def toScalaFlags: Long = flagCarrierId match {
+ case Method | Constructor => FlagTranslation methodFlags flags
+ case Class => FlagTranslation classFlags flags
+ case _ => FlagTranslation fieldFlags flags
+ }
+}
+
+object JavaAccFlags {
+ private val Unknown = 0
+ private val Class = 1
+ private val Field = 2
+ private val Method = 3
+ private val Constructor = 4
+
+ private def create(flagCarrier: Int, access_flags: Int): JavaAccFlags =
+ new JavaAccFlags((flagCarrier << 16) | (access_flags & 0xFFFF))
+
+ def classFlags(flags: Int): JavaAccFlags = create(Class, flags)
+ def methodFlags(flags: Int): JavaAccFlags = create(Method, flags)
+ def fieldFlags(flags: Int): JavaAccFlags = create(Field, flags)
+ def constructorFlags(flags: Int): JavaAccFlags = create(Constructor, flags)
+
+ def apply(access_flags: Int): JavaAccFlags = create(Unknown, access_flags)
+ def apply(clazz: jClass[_]): JavaAccFlags = classFlags(clazz.getModifiers)
+ def apply(member: jMember): JavaAccFlags = member match {
+ case x: jConstructor[_] => constructorFlags(x.getModifiers)
+ case x: jMethod => methodFlags(x.getModifiers)
+ case x: jField => fieldFlags(x.getModifiers)
+ case _ => apply(member.getModifiers)
+ }
+}
diff --git a/src/reflect/scala/reflect/internal/PrivateWithin.scala b/src/reflect/scala/reflect/internal/PrivateWithin.scala
index 9b99b94b41..5646ac82ae 100644
--- a/src/reflect/scala/reflect/internal/PrivateWithin.scala
+++ b/src/reflect/scala/reflect/internal/PrivateWithin.scala
@@ -1,23 +1,26 @@
package scala.reflect
package internal
-import ClassfileConstants._
+import java.lang.{ Class => jClass }
+import java.lang.reflect.{ Member => jMember }
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
+ def propagatePackageBoundary(c: jClass[_], syms: Symbol*): Unit =
+ propagatePackageBoundary(JavaAccFlags(c), syms: _*)
+ def propagatePackageBoundary(m: jMember, syms: Symbol*): Unit =
+ propagatePackageBoundary(JavaAccFlags(m), syms: _*)
+ def propagatePackageBoundary(jflags: JavaAccFlags, syms: Symbol*) {
+ if (jflags.hasPackageAccessBoundary)
+ syms foreach setPackageAccessBoundary
}
-} \ No newline at end of file
+
+ // protected in java means package protected. #3946
+ // See ticket #1687 for an example of when the enclosing top level class is NoSymbol;
+ // it apparently occurs when processing v45.3 bytecode.
+ def setPackageAccessBoundary(sym: Symbol): Symbol = (
+ if (sym.enclosingTopLevelClass eq NoSymbol) sym
+ else sym setPrivateWithin sym.enclosingTopLevelClass.owner
+ )
+}
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index f324f5145a..3211bb7919 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -6,12 +6,14 @@ import scala.collection.mutable.WeakHashMap
import java.lang.{Class => jClass, Package => jPackage}
import java.lang.reflect.{
- Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField,
+ Method => jMethod, Constructor => jConstructor, Field => jField,
Member => jMember, Type => jType, TypeVariable => jTypeVariable, Array => jArray,
+ AccessibleObject => jAccessibleObject,
GenericDeclaration, GenericArrayType, ParameterizedType, WildcardType, AnnotatedElement }
import java.lang.annotation.{Annotation => jAnnotation}
import java.io.IOException
-import internal.MissingRequirementError
+import scala.reflect.internal.{ MissingRequirementError, JavaAccFlags, JMethodOrConstructor }
+import JavaAccFlags._
import internal.pickling.ByteCodecs
import internal.ClassfileConstants._
import internal.pickling.UnPickler
@@ -88,12 +90,12 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
// ----------- Caching ------------------------------------------------------------------
- private val classCache = new TwoWayCache[jClass[_], ClassSymbol]
- private val packageCache = new TwoWayCache[Package, ModuleSymbol]
- private val methodCache = new TwoWayCache[jMethod, MethodSymbol]
+ private val classCache = new TwoWayCache[jClass[_], ClassSymbol]
+ private val packageCache = new TwoWayCache[Package, ModuleSymbol]
+ private val methodCache = new TwoWayCache[jMethod, MethodSymbol]
private val constructorCache = new TwoWayCache[jConstructor[_], MethodSymbol]
- private val fieldCache = new TwoWayCache[jField, TermSymbol]
- private val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol]
+ private val fieldCache = new TwoWayCache[jField, TermSymbol]
+ private val tparamCache = new TwoWayCache[jTypeVariable[_ <: GenericDeclaration], TypeSymbol]
private[runtime] def toScala[J: HasJavaClass, S](cache: TwoWayCache[J, S], key: J)(body: (JavaMirror, J) => S): S =
cache.toScala(key){
@@ -101,38 +103,36 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
body(mirrorDefining(jclazz), key)
}
- private implicit val classHasJavaClass: HasJavaClass[jClass[_]] =
- new HasJavaClass(identity)
- private implicit val methHasJavaClass: HasJavaClass[jMethod]
- = new HasJavaClass(_.getDeclaringClass)
- private implicit val fieldHasJavaClass: HasJavaClass[jField] =
- new HasJavaClass(_.getDeclaringClass)
- private implicit val constrHasJavaClass: HasJavaClass[jConstructor[_]] =
- new HasJavaClass(_.getDeclaringClass)
+ private implicit val classHasJavaClass: HasJavaClass[jClass[_]] = new HasJavaClass(identity)
+ private implicit val methHasJavaClass: HasJavaClass[jMethod] = new HasJavaClass(_.getDeclaringClass)
+ private implicit val fieldHasJavaClass: HasJavaClass[jField] = new HasJavaClass(_.getDeclaringClass)
+ private implicit val constrHasJavaClass: HasJavaClass[jConstructor[_]] = new HasJavaClass(_.getDeclaringClass)
private implicit val tparamHasJavaClass: HasJavaClass[jTypeVariable[_ <: GenericDeclaration]] =
new HasJavaClass ( (tparam: jTypeVariable[_ <: GenericDeclaration]) => {
tparam.getGenericDeclaration match {
- case jclazz: jClass[_] => jclazz
- case jmeth: jMethod => jmeth.getDeclaringClass
+ case jclazz: jClass[_] => jclazz
+ case jmeth: jMethod => jmeth.getDeclaringClass
case jconstr: jConstructor[_] => jconstr.getDeclaringClass
}
})
// ----------- Implementations of mirror operations and classes -------------------
- private def ErrorInnerClass(sym: Symbol) = throw new ScalaReflectionException(s"$sym is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
- private def ErrorInnerModule(sym: Symbol) = throw new ScalaReflectionException(s"$sym is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
- private def ErrorStaticClass(sym: Symbol) = throw new ScalaReflectionException(s"$sym is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
- private def ErrorStaticModule(sym: Symbol) = throw new ScalaReflectionException(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
- private def ErrorNotMember(sym: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}")
- private def ErrorNotField(sym: Symbol) = throw new ScalaReflectionException(s"expected a field or an accessor method symbol, you provided $sym")
- private def ErrorNonExistentField(sym: Symbol) = throw new ScalaReflectionException(
+ private def abort(msg: String) = throw new ScalaReflectionException(msg)
+
+ private def ErrorInnerClass(sym: Symbol) = abort(s"$sym is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror")
+ private def ErrorInnerModule(sym: Symbol) = abort(s"$sym is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror")
+ private def ErrorStaticClass(sym: Symbol) = abort(s"$sym is a static class, use reflectClass on a RuntimeMirror to obtain its ClassMirror")
+ private def ErrorStaticModule(sym: Symbol) = abort(s"$sym is a static module, use reflectModule on a RuntimeMirror to obtain its ModuleMirror")
+ private def ErrorNotMember(sym: Symbol, owner: Symbol) = abort(s"expected a member of $owner, you provided ${sym.kindString} ${sym.fullName}")
+ private def ErrorNotField(sym: Symbol) = abort(s"expected a field or an accessor method symbol, you provided $sym")
+ private def ErrorSetImmutableField(sym: Symbol) = abort(s"cannot set an immutable field ${sym.name}")
+ private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = abort(s"expected a constructor of $owner, you provided $sym")
+ private def ErrorFree(member: Symbol, freeType: Symbol) = abort(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}")
+ private def ErrorNonExistentField(sym: Symbol) = abort(
sm"""Scala field ${sym.name} isn't represented as a Java field, neither it has a Java accessor method
|note that private parameters of class constructors don't get mapped onto fields and/or accessors,
|unless they are used outside of their declaring constructors.""")
- private def ErrorSetImmutableField(sym: Symbol) = throw new ScalaReflectionException(s"cannot set an immutable field ${sym.name}")
- private def ErrorNotConstructor(sym: Symbol, owner: Symbol) = throw new ScalaReflectionException(s"expected a constructor of $owner, you provided $sym")
- private def ErrorFree(member: Symbol, freeType: Symbol) = throw new ScalaReflectionException(s"cannot reflect ${member.kindString} ${member.name}, because it's a member of a weak type ${freeType.name}")
/** Helper functions for extracting typed values from a (Class[_], Any)
* representing an annotation argument.
@@ -210,7 +210,6 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
case _ => body
}
}
-
private def checkMemberOf(sym: Symbol, owner: ClassSymbol) {
if (sym.owner == AnyClass || sym.owner == AnyRefClass || sym.owner == ObjectClass) {
// do nothing
@@ -236,8 +235,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
if (staticClazz.isPrimitive) staticClazz else dynamicClazz
}
- private class JavaInstanceMirror[T: ClassTag](val instance: T)
- extends InstanceMirror {
+ private class JavaInstanceMirror[T: ClassTag](val instance: T) extends InstanceMirror {
def symbol = thisMirror.classSymbol(preciseClass(instance))
def reflectField(field: TermSymbol): FieldMirror = {
checkMemberOf(field, symbol)
@@ -269,12 +267,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private class JavaFieldMirror(val receiver: Any, val symbol: TermSymbol)
extends FieldMirror {
- lazy val jfield = {
- val jfield = fieldToJava(symbol)
- if (!jfield.isAccessible) jfield.setAccessible(true)
- jfield
- }
- def get = jfield.get(receiver)
+ lazy val jfield = ensureAccessible(fieldToJava(symbol))
+ def get = jfield get receiver
def set(value: Any) = {
if (!symbol.isMutable) ErrorSetImmutableField(symbol)
jfield.set(receiver, value)
@@ -338,15 +332,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
}
}
-
- private abstract class JavaMethodMirror(val symbol: MethodSymbol)
- extends MethodMirror {
- lazy val jmeth = {
- val jmeth = methodToJava(symbol)
- if (!jmeth.isAccessible) jmeth.setAccessible(true)
- jmeth
- }
-
+ private abstract class JavaMethodMirror(val symbol: MethodSymbol) extends MethodMirror {
+ lazy val jmeth = ensureAccessible(methodToJava(symbol))
def jinvokeraw(jmeth: jMethod, receiver: Any, args: Seq[Any]) = jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
def jinvoke(jmeth: jMethod, receiver: Any, args: Seq[Any]): Any = {
@@ -418,13 +405,13 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
if (!perfectMatch && !varargMatch) {
val n_arguments = if (isVarArgsList(params)) s"${params.length - 1} or more" else s"${params.length}"
val s_arguments = if (params.length == 1 && !isVarArgsList(params)) "argument" else "arguments"
- throw new ScalaReflectionException(s"${showMethodSig(symbol)} takes $n_arguments $s_arguments")
+ abort(s"${showMethodSig(symbol)} takes $n_arguments $s_arguments")
}
def objReceiver = receiver.asInstanceOf[AnyRef]
def objArg0 = args(0).asInstanceOf[AnyRef]
def objArgs = args.asInstanceOf[Seq[AnyRef]]
- def fail(msg: String) = throw new ScalaReflectionException(msg + ", it cannot be invoked with mirrors")
+ def fail(msg: String) = abort(msg + ", it cannot be invoked with mirrors")
def invokePrimitiveMethod = {
val jmeths = classOf[BoxesRunTime].getDeclaredMethods.filter(_.getName == nme.primitiveMethodName(symbol.name).toString)
@@ -464,14 +451,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
extends MethodMirror {
def bind(newReceiver: Any) = new JavaConstructorMirror(newReceiver.asInstanceOf[AnyRef], symbol)
override val receiver = outer
- lazy val jconstr = {
- val jconstr = constructorToJava(symbol)
- if (!jconstr.isAccessible) jconstr.setAccessible(true)
- jconstr
- }
+ lazy val jconstr = ensureAccessible(constructorToJava(symbol))
def apply(args: Any*): Any = {
if (symbol.owner == ArrayClass)
- throw new ScalaReflectionException("Cannot instantiate arrays with mirrors. Consider using `scala.reflect.ClassTag(<class of element>).newArray(<length>)` instead")
+ abort("Cannot instantiate arrays with mirrors. Consider using `scala.reflect.ClassTag(<class of element>).newArray(<length>)` instead")
val effectiveArgs =
if (outer == null) args.asInstanceOf[Seq[AnyRef]]
@@ -532,7 +515,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
}
def javaClass(path: String): jClass[_] =
- Class.forName(path, true, classLoader)
+ jClass.forName(path, true, classLoader)
/** Does `path` correspond to a Java class with that fully qualified name in the current class loader? */
def tryJavaClass(path: String): Option[jClass[_]] = (
@@ -655,13 +638,22 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
sym setAnnotations (jann.getAnnotations map JavaAnnotationProxy).toList
// SI-7065: we're not using getGenericExceptionTypes here to be consistent with ClassfileParser
val jexTpes = jann match {
- case jm: jMethod => jm.getExceptionTypes.toList
+ case jm: jMethod => jm.getExceptionTypes.toList
case jconstr: jConstructor[_] => jconstr.getExceptionTypes.toList
- case _ => Nil
+ case _ => Nil
}
jexTpes foreach (jexTpe => sym.addThrowsAnnotation(classSymbol(jexTpe)))
}
+ private implicit class jClassOps(val clazz: jClass[_]) {
+ def javaFlags: JavaAccFlags = JavaAccFlags(clazz)
+ def scalaFlags: Long = javaFlags.toScalaFlags
+ }
+ private implicit class jMemberOps(val member: jMember) {
+ def javaFlags: JavaAccFlags = JavaAccFlags(member)
+ def scalaFlags: Long = javaFlags.toScalaFlags
+ }
+
/**
* A completer that fills in the types of a Scala class and its companion object
* by copying corresponding type info from a Java class. This completer is used
@@ -681,14 +673,14 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
override def load(sym: Symbol): Unit = {
debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug
assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym)
- val flags = toScalaClassFlags(jclazz.getModifiers)
+ val flags = jclazz.scalaFlags
clazz setFlag (flags | JAVA)
if (module != NoSymbol) {
module setFlag (flags & PRIVATE | JAVA)
module.moduleClass setFlag (flags & PRIVATE | JAVA)
}
- relatedSymbols foreach (importPrivateWithinFromJavaFlags(_, jclazz.getModifiers))
+ propagatePackageBoundary(jclazz, relatedSymbols: _*)
copyAnnotations(clazz, jclazz)
// to do: annotations to set also for module?
@@ -720,28 +712,21 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
}
- def enter(sym: Symbol, mods: Int) =
- (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym
+ def enter(sym: Symbol, mods: JavaAccFlags) =
+ ( if (mods.isStatic) module.moduleClass else clazz ).info.decls enter sym
for (jinner <- jclazz.getDeclaredClasses)
jclassAsScala(jinner) // inner class is entered as a side-effect
// no need to call enter explicitly
- pendingLoadActions = { () =>
-
- for (jfield <- jclazz.getDeclaredFields)
- enter(jfieldAsScala(jfield), jfield.getModifiers)
-
- for (jmeth <- jclazz.getDeclaredMethods)
- enter(jmethodAsScala(jmeth), jmeth.getModifiers)
-
- for (jconstr <- jclazz.getConstructors)
- enter(jconstrAsScala(jconstr), jconstr.getModifiers)
-
- } :: pendingLoadActions
+ pendingLoadActions ::= { () =>
+ jclazz.getDeclaredFields foreach (f => enter(jfieldAsScala(f), f.javaFlags))
+ jclazz.getDeclaredMethods foreach (m => enter(jmethodAsScala(m), m.javaFlags))
+ jclazz.getConstructors foreach (c => enter(jconstrAsScala(c), c.javaFlags))
+ }
if (parentsLevel == 0) {
- while (!pendingLoadActions.isEmpty) {
+ while (pendingLoadActions.nonEmpty) {
val item = pendingLoadActions.head
pendingLoadActions = pendingLoadActions.tail
item()
@@ -760,8 +745,8 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* If Java modifiers `mods` contain STATIC, return the module class
* of the companion module of `clazz`, otherwise the class `clazz` itself.
*/
- private def followStatic(clazz: Symbol, mods: Int) =
- if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz
+ private def followStatic(clazz: Symbol, mods: JavaAccFlags) =
+ if (mods.isStatic) clazz.companionModule.moduleClass else clazz
/** Methods which need to be treated with care
* because they either are getSimpleName or call getSimpleName:
@@ -797,7 +782,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
if (jclazz.isMemberClass) {
val jEnclosingClass = jclazz.getEnclosingClass
val sEnclosingClass = classToScala(jEnclosingClass)
- followStatic(sEnclosingClass, jclazz.getModifiers)
+ followStatic(sEnclosingClass, jclazz.javaFlags)
} else if (jclazz.isLocalClass0) {
val jEnclosingMethod = jclazz.getEnclosingMethod
if (jEnclosingMethod != null) {
@@ -825,7 +810,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* The Scala owner of the Scala symbol corresponding to the Java member `jmember`
*/
private def sOwner(jmember: jMember): Symbol = {
- followStatic(classToScala(jmember.getDeclaringClass), jmember.getModifiers)
+ followStatic(classToScala(jmember.getDeclaringClass), jmember.javaFlags)
}
/**
@@ -866,7 +851,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def methodToScala1(jmeth: jMethod): MethodSymbol = {
val jOwner = jmeth.getDeclaringClass
val preOwner = classToScala(jOwner)
- val owner = followStatic(preOwner, jmeth.getModifiers)
+ val owner = followStatic(preOwner, jmeth.javaFlags)
(lookup(owner, jmeth.getName) suchThat (erasesTo(_, jmeth)) orElse jmethodAsScala(jmeth))
.asMethod
}
@@ -880,7 +865,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
toScala(constructorCache, jconstr)(_ constructorToScala1 _)
private def constructorToScala1(jconstr: jConstructor[_]): MethodSymbol = {
- val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.getModifiers)
+ val owner = followStatic(classToScala(jconstr.getDeclaringClass), jconstr.javaFlags)
(lookup(owner, jconstr.getName) suchThat (erasesTo(_, jconstr)) orElse jconstrAsScala(jconstr))
.asMethod
}
@@ -1018,6 +1003,10 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
case jmeth: jMethod => methodToScala(jmeth)
case jconstr: jConstructor[_] => constructorToScala(jconstr)
}
+ def reflectMemberToScala(m: jMember): Symbol = m match {
+ case x: GenericDeclaration => genericDeclarationToScala(x)
+ case x: jField => jfieldAsScala(x)
+ }
/**
* Given some Java type arguments, a corresponding list of Scala types, plus potentially
@@ -1092,10 +1081,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def jfieldAsScala1(jfield: jField): TermSymbol = {
val field = sOwner(jfield)
- .newValue(newTermName(jfield.getName), NoPosition, toScalaFieldFlags(jfield.getModifiers))
+ .newValue(newTermName(jfield.getName), NoPosition, jfield.scalaFlags)
.setInfo(typeToScala(jfield.getGenericType))
- fieldCache enter (jfield, field)
- importPrivateWithinFromJavaFlags(field, jfield.getModifiers)
+
+ fieldCache.enter(jfield, field)
+ propagatePackageBoundary(jfield, field)
copyAnnotations(field, jfield)
field
}
@@ -1115,16 +1105,19 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def jmethodAsScala1(jmeth: jMethod): MethodSymbol = {
val clazz = sOwner(jmeth)
- val meth = clazz.newMethod(newTermName(jmeth.getName), NoPosition, toScalaMethodFlags(jmeth.getModifiers))
+ val meth = clazz.newMethod(newTermName(jmeth.getName), NoPosition, jmeth.scalaFlags)
methodCache enter (jmeth, meth)
val tparams = jmeth.getTypeParameters.toList map createTypeParameter
val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala
val resulttpe = typeToScala(jmeth.getGenericReturnType)
setMethType(meth, tparams, paramtpes, resulttpe)
- importPrivateWithinFromJavaFlags(meth, jmeth.getModifiers)
+ propagatePackageBoundary(jmeth.javaFlags, meth)
copyAnnotations(meth, jmeth)
- if ((jmeth.getModifiers & JAVA_ACC_VARARGS) != 0) meth.setInfo(arrayToRepeated(meth.info))
- meth
+
+ if (jmeth.javaFlags.isVarargs)
+ meth modifyInfo arrayToRepeated
+ else
+ meth
}
/**
@@ -1139,13 +1132,13 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
private def jconstrAsScala1(jconstr: jConstructor[_]): MethodSymbol = {
// [Martin] Note: I know there's a lot of duplication wrt jmethodAsScala, but don't think it's worth it to factor this out.
val clazz = sOwner(jconstr)
- val constr = clazz.newConstructor(NoPosition, toScalaMethodFlags(jconstr.getModifiers))
+ val constr = clazz.newConstructor(NoPosition, jconstr.scalaFlags)
constructorCache enter (jconstr, constr)
val tparams = jconstr.getTypeParameters.toList map createTypeParameter
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)
+ propagatePackageBoundary(jconstr.javaFlags, constr)
copyAnnotations(constr, jconstr)
constr
}
@@ -1170,13 +1163,15 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
else if (clazz.isTopLevel)
javaClass(clazz.javaClassName)
else if (clazz.owner.isClass) {
- val childOfClass = !clazz.owner.isModuleClass
- val childOfTopLevel = clazz.owner.isTopLevel
+ val childOfClass = !clazz.owner.isModuleClass
+ val childOfTopLevel = clazz.owner.isTopLevel
val childOfTopLevelObject = clazz.owner.isModuleClass && childOfTopLevel
// suggested in https://issues.scala-lang.org/browse/SI-4023?focusedCommentId=54759#comment-54759
var ownerClazz = classToJava(clazz.owner.asClass)
- if (childOfTopLevelObject) ownerClazz = Class.forName(ownerClazz.getName stripSuffix "$", true, ownerClazz.getClassLoader)
+ if (childOfTopLevelObject)
+ ownerClazz = jClass.forName(ownerClazz.getName stripSuffix "$", true, ownerClazz.getClassLoader)
+
val ownerChildren = ownerClazz.getDeclaredClasses
var fullNameOfJavaClass = ownerClazz.getName
@@ -1241,11 +1236,11 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
* Pre: Scala type is already transformed to Java level.
*/
def typeToJavaClass(tpe: Type): jClass[_] = tpe match {
- case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
- case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
- case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass)
+ case ExistentialType(_, rtpe) => typeToJavaClass(rtpe)
+ case TypeRef(_, ArrayClass, List(elemtpe)) => jArrayClass(typeToJavaClass(elemtpe))
+ case TypeRef(_, sym: ClassSymbol, _) => classToJava(sym.asClass)
case tpe @ TypeRef(_, sym: AliasTypeSymbol, _) => typeToJavaClass(tpe.dealias)
- case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
+ case _ => throw new NoClassDefFoundError("no Java class corresponding to "+tpe+" found")
}
}