summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2008-02-01 13:35:13 +0000
committerIulian Dragos <jaguarul@gmail.com>2008-02-01 13:35:13 +0000
commit1e00b1bd3b624efd8eac511d642d289715404bb6 (patch)
treeb425e45acbabb3a6c80f8af1f586fc1d8697b1af
parent222998874fb15354823e255384bf6ee6d1898d27 (diff)
downloadscala-1e00b1bd3b624efd8eac511d642d289715404bb6.tar.gz
scala-1e00b1bd3b624efd8eac511d642d289715404bb6.tar.bz2
scala-1e00b1bd3b624efd8eac511d642d289715404bb6.zip
Fixed #377.
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala41
-rw-r--r--test/files/jvm/throws-annot.check21
-rw-r--r--test/files/jvm/throws-annot.scala74
3 files changed, 122 insertions, 14 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index b7b2e9c754..570d13188b 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -279,13 +279,10 @@ abstract class GenJVM extends SubComponent {
informProgress("wrote BeanInfo " + outfile)
}
- def addExceptionsAttribute(sym: Symbol) {
- val (excs, others) = sym.attributes.partition((a => a match {
- case AnnotationInfo(tp, _, _) if tp.typeSymbol == ThrowsAttr => true
- case _ => false
- }))
- if (excs isEmpty) return;
- sym.attributes = others
+
+ /** Add the given 'throws' attributes to jmethod */
+ def addExceptionsAttribute(jmethod: JMethod, excs: List[AnnotationInfo]) {
+ if (excs.isEmpty) return
val cpool = jmethod.getConstantPool()
val buf: ByteBuffer = ByteBuffer.allocate(512)
@@ -313,8 +310,8 @@ abstract class GenJVM extends SubComponent {
annot.isConstant)
- private def emitAttributes(buf: ByteBuffer, attributes: List[AnnotationInfo]): Int = {
- val cpool = jclass.getConstantPool()
+ private def emitAttributes(cpool: JConstantPool, buf: ByteBuffer, attributes: List[AnnotationInfo]): Int = {
+// val cpool = jclass.getConstantPool()
def emitElement(const: Constant): Unit = const.tag match {
case BooleanTag =>
@@ -394,7 +391,7 @@ abstract class GenJVM extends SubComponent {
val buf: ByteBuffer = ByteBuffer.allocate(2048)
- emitAttributes(buf, toEmit)
+ emitAttributes(jmember.getConstantPool, buf, toEmit)
addAttribute(jmember, nme.RuntimeAnnotationATTR, buf)
}
@@ -411,7 +408,7 @@ abstract class GenJVM extends SubComponent {
// number of parameters
buf.put(attributes.length.toByte)
for (attrs <- attributes)
- emitAttributes(buf, attrs)
+ emitAttributes(jmethod.getConstantPool, buf, attrs)
addAttribute(jmethod, nme.RuntimeParamAnnotationATTR, buf)
}
@@ -555,12 +552,24 @@ abstract class GenJVM extends SubComponent {
genLocalVariableTable(m);
}
- addExceptionsAttribute(m.symbol)
- addAnnotations(jmethod, m.symbol.attributes)
+ val (excs, others) = splitAnnotations(m.symbol.attributes, ThrowsAttr)
+ addExceptionsAttribute(jmethod, excs)
+ addAnnotations(jmethod, others)
addParamAnnotations(m.params.map(_.sym.attributes))
}
- def isClosureApply(sym: Symbol): Boolean = {
+
+ /** Return a pair of lists of annotations, first one containing all
+ * annotations for the given symbol, and the rest.
+ */
+ private def splitAnnotations(annotations: List[AnnotationInfo], annotSym: Symbol): (List[AnnotationInfo], List[AnnotationInfo]) = {
+ annotations.partition { a => a match {
+ case AnnotationInfo(tp, _, _) if tp.typeSymbol == annotSym => true
+ case _ => false
+ }}
+ }
+
+ private def isClosureApply(sym: Symbol): Boolean = {
(sym.name == nme.apply) &&
sym.owner.hasFlag(Flags.SYNTHETIC) &&
sym.owner.tpe.parents.exists { t =>
@@ -647,6 +656,10 @@ abstract class GenJVM extends SubComponent {
mirrorCode.emitINVOKEVIRTUAL(moduleName, mirrorMethod.getName(), mirrorMethod.getType().asInstanceOf[JMethodType])
mirrorCode.emitRETURN(mirrorMethod.getReturnType())
+
+ val (throws, others) = splitAnnotations(m.attributes, ThrowsAttr)
+ addExceptionsAttribute(mirrorMethod, throws)
+ addAnnotations(mirrorMethod, others)
}
emitClass(mirrorClass, clasz.symbol)
}
diff --git a/test/files/jvm/throws-annot.check b/test/files/jvm/throws-annot.check
new file mode 100644
index 0000000000..a0ed82b106
--- /dev/null
+++ b/test/files/jvm/throws-annot.check
@@ -0,0 +1,21 @@
+read throws: class java.io.IOException
+read annotations:
+readWith2 throws: class java.lang.ClassCastException, class java.io.IOException
+readWith2 annotations:
+readMixed throws: class java.io.IOException, class java.lang.NullPointerException
+readMixed annotations: @java.lang.Deprecated()
+readMixed2 throws: class java.io.IOException, class java.lang.NullPointerException
+readMixed2 annotations: @java.lang.Deprecated()
+readNoEx throws:
+readNoEx annotations: @java.lang.Deprecated()
+Testing mirror class
+read throws: class java.io.IOException
+read annotations:
+readWith2 throws: class java.lang.ClassCastException, class java.io.IOException
+readWith2 annotations:
+readMixed throws: class java.io.IOException, class java.lang.NullPointerException
+readMixed annotations: @java.lang.Deprecated()
+readMixed2 throws: class java.io.IOException, class java.lang.NullPointerException
+readMixed2 annotations: @java.lang.Deprecated()
+readNoEx throws:
+readNoEx annotations: @java.lang.Deprecated()
diff --git a/test/files/jvm/throws-annot.scala b/test/files/jvm/throws-annot.scala
new file mode 100644
index 0000000000..5f4dac07e8
--- /dev/null
+++ b/test/files/jvm/throws-annot.scala
@@ -0,0 +1,74 @@
+/** Test the @throws annotation */
+import java.io.IOException
+
+object TestThrows {
+
+ abstract class Foo {
+
+ @throws(classOf[IOException])
+ def read(): Int
+
+ @throws(classOf[ClassCastException])
+ @throws(classOf[IOException])
+ def readWith2(): Int
+
+ @throws(classOf[IOException])
+ @Deprecated
+ @throws(classOf[NullPointerException])
+ def readMixed(): Int
+
+ @Deprecated
+ @throws(classOf[IOException])
+ @throws(classOf[NullPointerException])
+ def readMixed2(): Int
+
+ @Deprecated
+ def readNoEx(): Int
+ }
+
+ def checkMethod(cls: Class[_], name: String) {
+ val method = cls.getMethod(name, Array())
+ println(name + " throws: " + method.getExceptionTypes.mkString("", ", ", ""))
+ println(name + " annotations: " + method.getDeclaredAnnotations.mkString("", ", ", ""))
+ }
+
+ def run(cls: Class[_]) {
+ checkMethod(cls, "read")
+ checkMethod(cls, "readWith2")
+ checkMethod(cls, "readMixed")
+ checkMethod(cls, "readMixed2")
+ checkMethod(cls, "readNoEx")
+ }
+}
+
+/** Test the top-level mirror that is has the annotations. */
+object TL {
+
+ @throws(classOf[IOException])
+ def read(): Int = 0
+
+ @throws(classOf[ClassCastException])
+ @throws(classOf[IOException])
+ def readWith2(): Int = 0
+
+ @throws(classOf[IOException])
+ @Deprecated
+ @throws(classOf[NullPointerException])
+ def readMixed(): Int = 0
+
+ @Deprecated
+ @throws(classOf[IOException])
+ @throws(classOf[NullPointerException])
+ def readMixed2(): Int = 0
+
+ @Deprecated
+ def readNoEx(): Int = 0
+}
+
+object Test {
+ def main(args: Array[String]) {
+ TestThrows.run(classOf[TestThrows.Foo])
+ println("Testing mirror class")
+ TestThrows.run(Class.forName("TL"))
+ }
+}