scala.tools.nsc.symtab.AnnotationInfos.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.scala-compiler
Show all versions of org.apache.servicemix.bundles.scala-compiler
This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.
/* NSC -- new Scala compiler
* Copyright 2007-2011 LAMP/EPFL
* @author Martin Odersky
*/
package scala.tools.nsc
package symtab
import scala.tools.nsc.transform.Reifiers
import util._
/** AnnotationInfo and its helpers */
trait AnnotationInfos extends reflect.generic.AnnotationInfos { self: SymbolTable =>
/** Arguments to classfile annotations (which are written to
* bytecode as java annotations) are either:
*
* - constants
* - arrays of constants
* - or nested classfile annotations
*/
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
}
object LiteralAnnotArg extends LiteralAnnotArgExtractor
/** Represents an array of classfile annotation arguments */
case class ArrayAnnotArg(args: Array[ClassfileAnnotArg])
extends ClassfileAnnotArg {
override def toString = args.mkString("[", ", ", "]")
}
object ArrayAnnotArg extends ArrayAnnotArgExtractor
/** A specific annotation argument that encodes an array of bytes as an
* array of `Long`. The type of the argument declared in the annotation
* must be `String`. This specialised class is used to encode Scala
* signatures for reasons of efficiency, both in term of class-file size
* and in term of compiler performance.
*/
case class ScalaSigBytes(bytes: Array[Byte]) extends ClassfileAnnotArg {
override def toString = (bytes map { byte => (byte & 0xff).toHexString }).mkString("[ ", " ", " ]")
lazy val encodedBytes =
reflect.generic.ByteCodecs.encode(bytes)
def isLong: Boolean = (encodedBytes.length > 65535)
def sigAnnot: Type =
if (this.isLong)
definitions.ScalaLongSignatureAnnotation.tpe
else
definitions.ScalaSignatureAnnotation.tpe
}
/** 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
}
object NestedAnnotArg extends NestedAnnotArgExtractor
class AnnotationInfoBase
/** Typed information about an annotation. It can be attached to either
* a symbol or an annotated type.
*
* Annotations are written to the classfile as Java annotations
* if `atp` conforms to `ClassfileAnnotation` (the classfile parser adds
* this interface to any Java annotation class).
*
* Annotations are pickled (written to scala symtab attribute in the
* classfile) if `atp` inherits form `StaticAnnotation`.
*
* `args` stores arguments to Scala annotations, represented as typed
* trees. Note that these trees are not transformed by any phases
* following the type-checker.
*
* `assocs` stores arguments to classfile annotations as name-value pairs.
*/
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)
private var rawpos: Position = NoPosition
def pos = rawpos
def setPos(pos: Position): this.type = {
rawpos = pos
this
}
lazy val isTrivial: Boolean = atp.isTrivial && !(args exists (_.exists(_.isInstanceOf[This]))) // see annotationArgRewriter
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).setPos(pos)
}
// !!! when annotation arguments are not literal strings, but any sort of
// assembly of strings, there is a fair chance they will turn up here not as
// Literal(const) but some arbitrary AST.
def stringArg(index: Int): Option[String] = if(args.size > index) Some(args(index) match {
case Literal(const) => const.stringValue
case x => x.toString // should not be necessary, but better than silently ignoring an issue
}) else None
def intArg(index: Int): Option[Int] = if(args.size > index) Some(args(index)) collect {
case Literal(Constant(x: Int)) => x
} else None
}
object AnnotationInfo extends AnnotationInfoExtractor
lazy val classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] =
reflect.ClassManifest.classType(classOf[ClassfileAnnotArg])
/** Symbol annotations parsed in `Namer` (typeCompleter of
* definitions) have to be lazy (#1782)
*/
case class LazyAnnotationInfo(annot: () => AnnotationInfo)
extends AnnotationInfoBase
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy