summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormihaylov <mihaylov@epfl.ch>2006-05-17 08:43:54 +0000
committermihaylov <mihaylov@epfl.ch>2006-05-17 08:43:54 +0000
commitc98f8ec7425435ab10af3b3ff6031924ba51b171 (patch)
treeac46cc769093b64c226470680591e1867fff6700
parent98e286c19736adf7b70ae4c89c0d545e09a28dc2 (diff)
downloadscala-c98f8ec7425435ab10af3b3ff6031924ba51b171.tar.gz
scala-c98f8ec7425435ab10af3b3ff6031924ba51b171.tar.bz2
scala-c98f8ec7425435ab10af3b3ff6031924ba51b171.zip
Added support for emitting Java annotations int...
Added support for emitting Java annotations into classfiles
-rw-r--r--lib/fjbg.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala86
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala33
4 files changed, 107 insertions, 15 deletions
diff --git a/lib/fjbg.jar.desired.sha1 b/lib/fjbg.jar.desired.sha1
index 992da0b168..872a94f9b0 100644
--- a/lib/fjbg.jar.desired.sha1
+++ b/lib/fjbg.jar.desired.sha1
@@ -1 +1 @@
-020a429f8adc3e7230fb8dab88c38619123eeafa ?fjbg.jar
+6c45acb11cf51afe1d734eea4ccd9d55cf41d271 ?fjbg.jar
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index c49854e277..4d73965840 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -8,6 +8,7 @@
package scala.tools.nsc.backend.jvm;
import java.io.File;
+import java.nio.ByteBuffer;
import scala.collection.mutable.{Map, HashMap};
import scala.tools.nsc.symtab._;
@@ -169,9 +170,79 @@ abstract class GenJVM extends SubComponent {
clasz.fields foreach genField;
clasz.methods foreach genMethod;
+ addAttributes(jclass, c.symbol.attributes);
+
emitClass(jclass, c.symbol)
}
+
+ def addAttributes(jmember: JMember, attributes: List[AttrInfo]): Unit = {
+ if (attributes.isEmpty) return;
+
+ val cpool = jmember.getConstantPool();
+ val buf: ByteBuffer = ByteBuffer.allocate(2048);
+ var nattr = 0;
+
+ // put some radom value; the actual number is determined at the end
+ buf.putShort(0xbaba.toShort)
+
+ for (val Pair(typ, consts) <- attributes; typ.symbol.hasFlag(Flags.JAVA)) {
+ nattr = nattr + 1;
+ val jtype = javaType(toTypeKind(typ));
+ buf.putShort(cpool.addUtf8(jtype.getSignature()).toShort);
+ assert(consts.length == 1, consts.toString())
+ buf.putShort(1.toShort); // for now only 1 constructor parameter
+ buf.putShort(cpool.addUtf8("value").toShort);
+ for (val const <- consts) {
+ const.tag match {
+ case BooleanTag =>
+ buf.put('Z'.toByte)
+ buf.putShort(cpool.addInteger(if(const.booleanValue) 1 else 0).toShort)
+ case ByteTag =>
+ buf.put('B'.toByte)
+ buf.putShort(cpool.addInteger(const.byteValue).toShort)
+ case ShortTag =>
+ buf.put('S'.toByte)
+ buf.putShort(cpool.addInteger(const.shortValue).toShort)
+ case CharTag =>
+ buf.put('C'.toByte)
+ buf.putShort(cpool.addInteger(const.charValue).toShort)
+ case IntTag =>
+ buf.put('I'.toByte)
+ buf.putShort(cpool.addInteger(const.intValue).toShort)
+ case LongTag =>
+ buf.put('J'.toByte)
+ buf.putShort(cpool.addLong(const.longValue).toShort)
+ case FloatTag =>
+ buf.put('F'.toByte)
+ buf.putShort(cpool.addFloat(const.floatValue).toShort)
+ case DoubleTag =>
+ buf.put('D'.toByte)
+ buf.putShort(cpool.addDouble(const.doubleValue).toShort)
+ case StringTag =>
+ buf.put('s'.toByte);
+ buf.putShort(cpool.addUtf8(const.stringValue).toShort)
+ case ClassTag =>
+ buf.put('c'.toByte);
+ buf.putShort(cpool.addUtf8(javaType(toTypeKind(const.typeValue)).getSignature()).toShort)
+ //case NullTag => AllRefClass.tpe
+ }
+ }
+ }
+ if (nattr > 0) {
+ val length = buf.position();
+ buf.putShort(0, nattr.toShort)
+ val arr = buf.array().subArray(0, length);
+
+ val attr = jmember.getContext().JOtherAttribute(jmember.getJClass(),
+ jmember,
+ nme.RuntimeAnnotationATTR.toString(),
+ arr,
+ length)
+ jmember.addAttribute(attr)
+ }
+ }
+
def isTopLevelModule(sym: Symbol): Boolean =
atPhase (currentRun.refchecksPhase) {
sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass
@@ -191,9 +262,12 @@ abstract class GenJVM extends SubComponent {
case Pair(VolatileAttr, _) => attributes = attributes | JAccessFlags.ACC_VOLATILE;
case _ => ();
}}
- jclass.addNewField(javaFlags(f.symbol) | attributes,
- javaName(f.symbol),
- javaType(toTypeKind(f.symbol.tpe)));
+ val jfield =
+ jclass.addNewField(javaFlags(f.symbol) | attributes,
+ javaName(f.symbol),
+ javaType(toTypeKind(f.symbol.tpe)));
+
+ addAttributes(jfield, f.symbol.attributes)
}
def genMethod(m: IMethod): Unit = {
@@ -231,7 +305,7 @@ abstract class GenJVM extends SubComponent {
// }
val cp = jclass.getConstantPool();
val reInx = cp.addClass(JAVA_RMI_REMOTEEXCEPTION);
- val contents = java.nio.ByteBuffer.allocate(4); // u2 + u2[1]
+ val contents = ByteBuffer.allocate(4); // u2 + u2[1]
contents.putShort(1.asInstanceOf[Short]);
contents.putShort(reInx.asInstanceOf[Short]);
if (settings.debug.value)
@@ -251,6 +325,8 @@ abstract class GenJVM extends SubComponent {
genCode(m);
genLocalVariableTable;
}
+
+ addAttributes(jmethod, m.symbol.attributes)
}
def addModuleInstanceField: Unit = {
@@ -1075,7 +1151,7 @@ abstract class GenJVM extends SubComponent {
val pc = jcode.getPC();
var anonCounter = 0;
- val lvTab = java.nio.ByteBuffer.allocate(2 + 10 * vars.length);
+ val lvTab = ByteBuffer.allocate(2 + 10 * vars.length);
lvTab.putShort(vars.length.asInstanceOf[Short]);
for (val lv <- vars) {
val name = if (lv.getName() == null) {
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 549d2dac23..deecaeb63c 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -284,6 +284,7 @@ trait StdNames requires SymbolTable {
val tag = newTermName("$tag");
val wait_ = newTermName("wait");
val lift_ = newTermName("lift")
+ val value = newTermName("value");
val ZNOT = encode("!");
val ZAND = encode("&&");
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 489502910c..0bd20198a4 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -242,12 +242,14 @@ abstract class ClassfileParser {
def parseClass(): unit = {
val jflags = in.nextChar;
+ val isAttribute = (jflags & JAVA_ACC_ANNOTATION) != 0;
var sflags = transFlags(jflags);
if ((sflags & DEFERRED) != 0) sflags = sflags & ~DEFERRED | ABSTRACT;
val c = pool.getClassSymbol(in.nextChar);
if (c != clazz)
throw new IOException("class file '" + in.file + "' contains wrong " + clazz);
- val superType = pool.getSuperClass(in.nextChar).tpe;
+ val superType = if (isAttribute) { in.nextChar; definitions.AttributeClass.tpe }
+ else pool.getSuperClass(in.nextChar).tpe;
val ifaceCount = in.nextChar;
val parents = (superType ::
(for (val i <- List.range(0, ifaceCount))
@@ -276,12 +278,24 @@ abstract class ClassfileParser {
for (val i <- Iterator.range(0, fieldCount)) parseField();
val methodCount = in.nextChar;
for (val i <- Iterator.range(0, methodCount)) parseMethod();
- if (instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol && (sflags & INTERFACE) == 0) {
- //System.out.println("adding constructor to " + clazz);//DEBUG
- instanceDefs.enter(
- clazz.newConstructor(Position.NOPOS)
- .setFlag(clazz.flags & ConstrFlags).setInfo(MethodType(List(), clazz.tpe)));
- }
+ if ((instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol
+ && (sflags & INTERFACE) == 0) ||
+ isAttribute)
+ {
+ //System.out.println("adding constructor to " + clazz);//DEBUG
+ val constrParamTypes =
+ if (isAttribute) {
+ val value = instanceDefs.lookup(nme.value)
+ if (value == NoSymbol) List ()
+ else List(value.tpe.resultType)
+ //System.out.println("" + value + " : " + value.tpe)
+ }
+ else List()
+ instanceDefs.enter(
+ clazz.newConstructor(Position.NOPOS)
+ .setFlag(clazz.flags & ConstrFlags)
+ .setInfo(MethodType(constrParamTypes, clazz.tpe)));
+ }
}
}
@@ -600,11 +614,12 @@ abstract class ClassfileParser {
res = res | PRIVATE
else if ((flags & JAVA_ACC_PROTECTED) != 0)
res = res | PROTECTED
- if ((flags & JAVA_ACC_ABSTRACT) != 0)
+ if ((flags & JAVA_ACC_ABSTRACT) != 0 && (flags & JAVA_ACC_ANNOTATION) == 0)
res = res | DEFERRED;
if ((flags & JAVA_ACC_FINAL) != 0)
res = res | FINAL;
- if ((flags & JAVA_ACC_INTERFACE) != 0)
+ if (((flags & JAVA_ACC_INTERFACE) != 0) &&
+ ((flags & JAVA_ACC_ANNOTATION) == 0))
res = res | TRAIT | INTERFACE | ABSTRACT;
if ((flags & JAVA_ACC_SYNTHETIC) != 0)
res = res | SYNTHETIC;