/* NSC -- new Scala compiler * Copyright 2007-2009 LAMP/EPFL * @author Martin Odersky */ // $Id: AnnotationInfos.scala 18387 2009-07-24 15:28:37Z odersky $ package scala.tools.nsc package symtab import scala.tools.nsc.transform.Reifiers import util._ /** AnnotationInfo and its helpers */ trait AnnotationInfos { self: SymbolTable => /** Arguments to classfile annotations (which are written to * bytecode as java annotations) are either: * <ul> * <li>constants</li> * <li>arrays of constants</li> * <li>or nested classfile annotations</li> * </ul> */ abstract class ClassfileAnnotArg /** Represents a compile-time Constant (Boolean, Byte, Short, * Char, Int, Long, Float, Double, String, java.lang.Class or * an instance of a Java enumeration value). */ case class LiteralAnnotArg(const: Constant) extends ClassfileAnnotArg { override def toString = const.escapedStringValue } /** Represents an array of classfile annotation arguments */ case class ArrayAnnotArg(args: Array[ClassfileAnnotArg]) extends ClassfileAnnotArg { override def toString = args.mkString("[", ", ", "]") } /** Represents a nested classfile annotation */ case class NestedAnnotArg(annInfo: AnnotationInfo) extends ClassfileAnnotArg { // The nested annotation should not have any Scala annotation arguments assert(annInfo.args.isEmpty, annInfo.args) override def toString = annInfo.toString } class AnnotationInfoBase /** <p> * Typed information about an annotation. It can be attached to * either a symbol or an annotated type. * </p> * <p> * Annotations are written to the classfile as java annotations * if <code>atp</code> conforms to <code>ClassfileAnnotation</code> * (the classfile parser adds this interface to any Java annotation * class). * </p> * <p> * Annotations are pickled (written to scala symbtab attribute * in the classfile) if <code>atp</code> inherits form * <code>StaticAnnotation</code>. * </p> * <p> * <code>args</code> stores arguments to Scala annotations, * represented as typed trees. Note that these trees are not * transformed by any phases following the type-checker. * </p> * <p> * <code>assocs</code> stores arguments to classfile annotations * as name-value pairs. * </p> */ case class AnnotationInfo(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]) extends AnnotationInfoBase { // Classfile annot: args empty. Scala annot: assocs empty. assert(args.isEmpty || assocs.isEmpty) override def toString: String = atp + (if (!args.isEmpty) args.mkString("(", ", ", ")") else "") + (if (!assocs.isEmpty) (assocs map { case (x, y) => x+" = "+y } mkString ("(", ", ", ")")) else "") /** Check whether the type or any of the arguments are erroneous */ def isErroneous = atp.isErroneous || args.exists(_.isErroneous) /** Check whether any of the arguments mention a symbol */ def refsSymbol(sym: Symbol) = args.exists(_.exists(_.symbol == sym)) /** Change all ident's with Symbol "from" to instead use symbol "to" */ def substIdentSyms(from: Symbol, to: Symbol) = { val subs = new TreeSymSubstituter(List(from), List(to)) AnnotationInfo(atp, args.map(subs(_)), assocs) } } /** Symbol annotations parsed in Namer (typeCompleter of * definitions) have to be lazy (#1782) */ case class LazyAnnotationInfo(annot: () => AnnotationInfo) extends AnnotationInfoBase }