From ce348c4aea934c3750b98fe0b5cb3486e6cb1f8d Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Thu, 26 Sep 2013 08:14:33 -0400 Subject: [PATCH] Minimal support for class file formats 51.0, 52.0 in incremental compiler. Fixes #842. It is not currently possible to use a newer class file format than the one for the jvm sbt is running in. --- .../main/scala/sbt/classfile/ClassFile.scala | 3 ++ .../src/main/scala/sbt/classfile/Parser.scala | 38 ++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/util/classfile/src/main/scala/sbt/classfile/ClassFile.scala b/util/classfile/src/main/scala/sbt/classfile/ClassFile.scala index df73acf9b..32bb131f0 100644 --- a/util/classfile/src/main/scala/sbt/classfile/ClassFile.scala +++ b/util/classfile/src/main/scala/sbt/classfile/ClassFile.scala @@ -62,5 +62,8 @@ private[sbt] object Constants final val ConstantMethod = 10 final val ConstantInterfaceMethod = 11 final val ConstantNameAndType = 12 + final val ConstantMethodHandle = 15 + final val ConstantMethodType = 16 + final val ConstantInvokeDynamic = 18 final val ClassDescriptor = 'L' } \ No newline at end of file diff --git a/util/classfile/src/main/scala/sbt/classfile/Parser.scala b/util/classfile/src/main/scala/sbt/classfile/Parser.scala index 26b753835..980b5aa7e 100644 --- a/util/classfile/src/main/scala/sbt/classfile/Parser.scala +++ b/util/classfile/src/main/scala/sbt/classfile/Parser.scala @@ -76,7 +76,7 @@ private[sbt] object Parser new AttributeInfo(name, value) } - def types = Set((fieldTypes ++ methodTypes ++ classConstantReferences) : _*) + def types = (classConstantReferences ++ fieldTypes ++ methodTypes).toSet private def getTypes(fieldsOrMethods: Array[FieldOrMethodInfo]) = fieldsOrMethods.flatMap { fieldOrMethod => @@ -114,8 +114,8 @@ private[sbt] object Parser next(1, Nil) } } - } - private def array[T : scala.reflect.Manifest](size: Int)(f: => T) = Array.tabulate(size)(_ => f) + } + private def array[T : scala.reflect.Manifest](size: Int)(f: => T) = Array.tabulate(size)(_ => f) private def parseConstantPool(in: DataInputStream) = { val constantPoolSize = in.readUnsignedShort() @@ -133,20 +133,32 @@ private[sbt] object Parser pool } - private def getConstant(in: DataInputStream): Constant = - { + private def getConstant(in: DataInputStream): Constant = + { val tag = in.readByte() - // No switch for byte scrutinees! Stupid compiler. - ((tag: Int): @switch) match { - case ConstantClass | ConstantString => new Constant(tag, in.readUnsignedShort()) - case ConstantField | ConstantMethod | ConstantInterfaceMethod | ConstantNameAndType => - new Constant(tag, in.readUnsignedShort(), in.readUnsignedShort()) - case ConstantInteger => new Constant(tag, new java.lang.Integer(in.readInt())) - case ConstantFloat => new Constant(tag, new java.lang.Float(in.readFloat())) - case ConstantLong => new Constant(tag, new java.lang.Long(in.readLong())) + // No switch for byte scrutinees! Stupid compiler. + ((tag: Int): @switch) match { + case ConstantClass | ConstantString => new Constant(tag, in.readUnsignedShort()) + case ConstantField | ConstantMethod | ConstantInterfaceMethod | ConstantNameAndType => + new Constant(tag, in.readUnsignedShort(), in.readUnsignedShort()) + case ConstantInteger => new Constant(tag, new java.lang.Integer(in.readInt())) + case ConstantFloat => new Constant(tag, new java.lang.Float(in.readFloat())) + case ConstantLong => new Constant(tag, new java.lang.Long(in.readLong())) case ConstantDouble => new Constant(tag, new java.lang.Double(in.readDouble())) case ConstantUTF8 => new Constant(tag, in.readUTF()) + // TODO: proper support + case ConstantMethodHandle => + val kind = in.readByte() + val ref = in.readUnsignedShort() + new Constant(tag, -1, -1, None) + case ConstantMethodType => + val descriptorIndex = in.readUnsignedShort() + new Constant(tag, -1, -1, None) + case ConstantInvokeDynamic => + val bootstrapIndex = in.readUnsignedShort() + val nameAndTypeIndex = in.readUnsignedShort() + new Constant(tag, -1, -1, None) case _ => sys.error("Unknown constant: " + tag) } }