diff options
author | mihaylov <mihaylov@epfl.ch> | 2006-06-12 14:28:49 +0000 |
---|---|---|
committer | mihaylov <mihaylov@epfl.ch> | 2006-06-12 14:28:49 +0000 |
commit | 333b75ec320375e4f8abf84b3d37608b3024295e (patch) | |
tree | 72cb57e2186754752dba27e55f25f3204702cd73 /src | |
parent | 1c43cfe216a0d759568a964a16345ea773f32211 (diff) | |
download | scala-333b75ec320375e4f8abf84b3d37608b3024295e.tar.gz scala-333b75ec320375e4f8abf84b3d37608b3024295e.tar.bz2 scala-333b75ec320375e4f8abf84b3d37608b3024295e.zip |
Extended Java annotations support
Diffstat (limited to 'src')
7 files changed, 95 insertions, 28 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index f428e13411..da734729b3 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -100,9 +100,21 @@ abstract class TreePrinters { } def printAttributes(attrs: List[AttrInfo]): unit = { - def attrToString(attr: AttrInfo): String = attr match { - case Pair(tp, List()) => tp.toString() - case Pair(tp, args) => tp.toString()+args.mkString("(", ",", ")") + def attrToString(attr: AttrInfo): String = { + val str = new StringBuffer() + attr match { + case Triple(tp, args, nvPairs) => + str.append(tp.toString()); + if (!args.isEmpty) + str.append(args.mkString("(", ",", ")")) + if (!nvPairs.isEmpty) + for (val Pair(Pair(sym, value), index) <- nvPairs.zipWithIndex) { + if (index > 0) + str.append(", ") + str.append(sym.name).append(" = ").append(value) + } + str.toString + } } if (!attrs.isEmpty) print(attrs.map(attrToString).mkString("[", ",", "]")) } diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index c475ece753..35396d22f4 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -307,7 +307,11 @@ trait Trees requires Global { case class Import(expr: Tree, selectors: List[Pair[Name, Name]]) extends SymTree; - /** Attribuetd definition */ + /** Attribute application (constructor arguments + name-value pairs) */ + case class Attribute(constr: Tree, elements: List[Tree]) + extends TermTree; + + /** Attributed definition */ case class Attributed(attribute: Tree, definition: Tree) extends Tree { override def symbol: Symbol = definition.symbol; @@ -553,6 +557,7 @@ trait Trees requires Global { case AliasTypeDef(mods, name, tparams, rhs) => (eliminated by erasure) case LabelDef(name, params, rhs) => case Import(expr, selectors) => (eliminated by typecheck) + case Attribute(constr, elements) => (eliminated by typecheck) case Attributed(attribute, definition) => (eliminated by typecheck) case DocDef(comment, definition) => (eliminated by typecheck) case Template(parents, body) => @@ -596,6 +601,7 @@ trait Trees requires Global { def AliasTypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], rhs: Tree): AliasTypeDef; def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef; def Import(tree: Tree, expr: Tree, selectors: List[Pair[Name, Name]]): Import; + def Attribute(tree: Tree, constr: Tree, elements: List[Tree]): Attribute; def Attributed(tree: Tree, attribute: Tree, definition: Tree): Attributed; def DocDef(tree: Tree, comment: String, definition: Tree): DocDef; def Template(tree: Tree, parents: List[Tree], body: List[Tree]): Template; @@ -648,6 +654,8 @@ trait Trees requires Global { new LabelDef(name, params, rhs).copyAttrs(tree); def Import(tree: Tree, expr: Tree, selectors: List[Pair[Name, Name]]) = new Import(expr, selectors).copyAttrs(tree); + def Attribute(tree: Tree, constr: Tree, elements: List[Tree]) = + new Attribute(constr, elements); def Attributed(tree: Tree, attribute: Tree, definition: Tree) = new Attributed(attribute, definition).copyAttrs(tree); def DocDef(tree: Tree, comment: String, definition: Tree) = @@ -759,6 +767,11 @@ trait Trees requires Global { if ((expr0 == expr) && (selectors0 == selectors)) => t case _ => copy.Import(tree, expr, selectors) } + def Attribute(tree: Tree, constr: Tree, elements: List[Tree]) = tree match { + case t @ Attribute(constr0, elements0) + if ((constr0 == constr) && (elements0 == elements)) => t + case _ => copy.Attribute(tree, constr, elements) + } def Attributed(tree: Tree, attribute: Tree, definition: Tree) = tree match { case t @ Attributed(attribute0, definition0) if ((attribute0 == attribute) && (definition0 == definition)) => t @@ -954,6 +967,8 @@ trait Trees requires Global { copy.LabelDef(tree, name, transformIdents(params), transform(rhs)) //bq: Martin, once, atOwner(...) works, also change `LamdaLifter.proxy' case Import(expr, selectors) => copy.Import(tree, transform(expr), selectors) + case Attribute(constr, elements) => + copy.Attribute(tree, transform(constr), transformTrees(elements)) case Attributed(attribute, definition) => copy.Attributed(tree, transform(attribute), transform(definition)) case DocDef(comment, definition) => @@ -1084,6 +1099,8 @@ trait Trees requires Global { traverseTrees(params); traverse(rhs) case Import(expr, selectors) => traverse(expr) + case Attribute(constr, elements) => + traverse(constr); traverseTrees(elements); case Attributed(attribute, definition) => traverse(attribute); traverse(definition) case DocDef(comment, definition) => diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 979f273529..c0eb751e06 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1791,12 +1791,29 @@ trait Parsers requires SyntaxAnalyzer { /** Attribute ::= StableId [TypeArgs] [`(' [Exprs] `)'] */ def attribute(): Tree = { + def nameValuePair(): Tree = { + var pos = in.currentPos; + val aname = atPos(pos) { Ident(ident()) } + accept(EQUALS); + atPos(pos) { Assign(aname, prefixExpr()) } + } val pos = in.currentPos; var t: Tree = convertToTypeId(stableId()); if (in.token == LBRACKET) t = atPos(in.currentPos)(AppliedTypeTree(t, typeArgs())); val args = if (in.token == LPAREN) argumentExprs() else List(); - atPos(pos) { New(t, List(args)) } + val nameValuePairs: List[Tree] = if (in.token == LBRACE) { + in.nextToken(); + val nvps = new ListBuffer[Tree] + nameValuePair(); + while (in.token == COMMA) { + in.nextToken(); + nvps += nameValuePair() + } + accept(RBRACE); + nvps.toList + } else List() + val constr = atPos(pos) { New(t, List(args)) } + atPos(pos) { Attribute(constr, nameValuePairs) } } def mixinAttribute(attrs: List[Tree]) = { diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 6a6239e3ea..69a008679d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -125,13 +125,13 @@ abstract class GenJVM extends SubComponent { parents = definitions.ObjectClass.tpe :: parents; c.symbol.attributes foreach { a => a match { - case Pair(SerializableAttr, _) if (!forCLDC) => + case Triple(SerializableAttr, _, _) if (!forCLDC) => parents = parents ::: List(definitions.SerializableClass.tpe); - case Pair(CloneableAttr, _) if (!forCLDC) => + case Triple(CloneableAttr, _, _) if (!forCLDC) => parents = parents ::: List(CloneableClass.tpe); - case Pair(SerialVersionUID, value :: _) if (!forCLDC) => + case Triple(SerialVersionUID, value :: _, _) if (!forCLDC) => serialVUID = Some(value.longValue); - case Pair(RemoteAttr, _) if (!forCLDC) => + case Triple(RemoteAttr, _, _) if (!forCLDC) => parents = parents ::: List(RemoteInterface.tpe); remoteClass = true; case _ => (); @@ -178,7 +178,7 @@ abstract class GenJVM extends SubComponent { def addExceptionsAttribute(jm: JMethod, throws: List[AttrInfo]): Unit = { if (throws.forall(a => a match { - case Pair(ThrowsAttr, _) => false + case Triple(ThrowsAttr, _, _) => false case _ => true })) return; @@ -189,7 +189,7 @@ abstract class GenJVM extends SubComponent { // put some radom value; the actual number is determined at the end buf.putShort(0xbaba.toShort) - for (val Pair(ThrowsAttr, List(exc)) <- throws) { + for (val Triple(ThrowsAttr, List(exc), _) <- throws) { buf.putShort(cpool.addClass(exc.typeValue.toString()).shortValue) nattr = nattr + 1; } @@ -215,13 +215,12 @@ abstract class GenJVM extends SubComponent { // 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)) { + for (val Triple(typ, consts, nvPairs) <- attributes; typ.symbol.hasFlag(Flags.JAVA)) { nattr = nattr + 1; val jtype = javaType(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); + assert(consts.length <= 1, consts.toString()) + buf.putShort((consts.length + nvPairs.length).toShort); def emitElement(const: Constant): Unit = const.tag match { case BooleanTag => buf.put('Z'.toByte) @@ -264,9 +263,13 @@ abstract class GenJVM extends SubComponent { for (val elem <- arr) emitElement(elem) //case NullTag => AllRefClass.tpe } - - for (val const <- consts) { - emitElement(const) + if (!consts.isEmpty) { + buf.putShort(cpool.addUtf8("value").toShort); + emitElement(consts.head); + } + for (val Pair(symbol, value) <- nvPairs) { + buf.putShort(cpool.addUtf8(symbol.name.toString()).toShort) + emitElement(value) } } if (nattr > 0) { @@ -298,8 +301,8 @@ abstract class GenJVM extends SubComponent { var attributes = 0; f.symbol.attributes foreach { a => a match { - case Pair(TransientAtt, _) => attributes = attributes | JAccessFlags.ACC_TRANSIENT; - case Pair(VolatileAttr, _) => attributes = attributes | JAccessFlags.ACC_VOLATILE; + case Triple(TransientAtt, _, _) => attributes = attributes | JAccessFlags.ACC_TRANSIENT; + case Triple(VolatileAttr, _, _) => attributes = attributes | JAccessFlags.ACC_VOLATILE; case _ => (); }} val jfield = diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 65606e591d..816df859ba 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -20,7 +20,7 @@ trait Symbols requires SymbolTable { var typeSymbolCount = 0 var classSymbolCount = 0 - type AttrInfo = Pair[Type, List[Constant]] + type AttrInfo = Triple[Type, List[Constant], List[Pair[Symbol,Constant]]] val emptySymbolArray = new Array[Symbol](0) @@ -133,7 +133,7 @@ trait Symbols requires SymbolTable { final def newAnonymousFunctionClass(pos: int) = { val anonfun = newClass(pos, nme.ANON_FUN_NAME.toTypeName) anonfun.attributes = - Pair(definitions.SerializableAttr.tpe, List()) :: anonfun.attributes + Triple(definitions.SerializableAttr.tpe, List(), List()) :: anonfun.attributes anonfun } final def newRefinementClass(pos: int) = diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index a5c6abb92a..6dfda34435 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -168,7 +168,7 @@ trait SyntheticMethods requires Analyzer { if (clazz hasFlag CASE) { // case classes are implicitly declared serializable - clazz.attributes = Pair(SerializableAttr.tpe, List()) :: clazz.attributes; + clazz.attributes = Triple(SerializableAttr.tpe, List(), List()) :: clazz.attributes; for (val stat <- templ.body) { if (stat.isDef && stat.symbol.isMethod && stat.symbol.hasFlag(CASEACCESSOR) && diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 33599ef7ab..6effca1c70 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1350,17 +1350,35 @@ trait Typers requires Analyzer { } typer1.typedLabelDef(ldef) - case Attributed(attr, defn) => - val attr1 = typed(attr, mode | CONSTmode, AttributeClass.tpe) - val attrInfo = attr1 match { + case Attributed(Attribute(constr, elements), defn) => + val constr1 = typed(constr, mode | CONSTmode, AttributeClass.tpe) + val attrInfo = constr1 match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => - Pair(tpt.tpe, args map { + val constrArgs = args map { case Literal(value) => value case arg => error(arg.pos, "attribute argument needs to be a constant; found: "+arg) null - }) + } + val nvPairs = elements map { + case Assign(Ident(name), rhs) => { + val sym = tpt.tpe.decls.lookupEntry(name).sym; + if (sym == NoSymbol) { + null + } else { + val rhs1 = typed(rhs, mode | CONSTmode, sym.tpe.resultType) + val value = rhs1 match { + case Literal(v) => v + case arg => + error(arg.pos, "attribute argument needs to be a constant; found: "+arg) + null + } + Pair(sym, value) + } + } + } + Triple(tpt.tpe, constrArgs, nvPairs) } if (attrInfo != null) { val attributed = |