diff options
Diffstat (limited to 'src/reflect/scala/reflect/api/Annotations.scala')
-rw-r--r-- | src/reflect/scala/reflect/api/Annotations.scala | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala index e19e0cefad..b880fad756 100644 --- a/src/reflect/scala/reflect/api/Annotations.scala +++ b/src/reflect/scala/reflect/api/Annotations.scala @@ -5,11 +5,11 @@ package api import scala.collection.immutable.ListMap /** - * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> + * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> * - * This trait provides annotation support for the reflection API. + * This trait provides annotation support for the reflection API. * - * The API distinguishes between two kinds of annotations: + * In Scala, annotations belong to one of the two categories: * * <ul> * <li>''Java annotations'': annotations on definitions produced by the Java compiler, i.e., subtypes of [[java.lang.annotation.Annotation]] @@ -22,16 +22,13 @@ import scala.collection.immutable.ListMap * it is stored as special attributes in the corresponding classfile, and not as a Java annotation. Note that subclassing * just [[scala.annotation.Annotation]] is not enough to have the corresponding metadata persisted for runtime reflection. * - * The distinction between Java and Scala annotations is manifested in the contract of [[scala.reflect.api.Annotations#Annotation]], which exposes - * both `scalaArgs` and `javaArgs`. For Scala or Java annotations extending [[scala.annotation.ClassfileAnnotation]] `scalaArgs` is empty - * and arguments are stored in `javaArgs`. For all other Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. + * Both Java and Scala annotations are represented as typed trees carrying constructor invocations corresponding + * to the annotation. For instance, the annotation in `@ann(1, 2) class C` is represented as `q"@new ann(1, 2)"`. * - * Arguments in `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases - * following the type-checker. Arguments in `javaArgs` are repesented as a map from [[scala.reflect.api.Names#Name]] to - * [[scala.reflect.api.Annotations#JavaArgument]]. Instances of `JavaArgument` represent different kinds of Java annotation arguments: - * - literals (primitive and string constants), - * - arrays and - * - nested annotations. + * Unlike Java reflection, Scala reflection does not support evaluation of constructor invocations stored in annotations + * into underlying objects. For instance it's impossible to go from `@ann(1, 2) class C` to `ann(1, 2)`, so one + * has to analyze trees representing annotation arguments to manually extract corresponding values. Towards that end, + * arguments of an annotation can be obtained via `annotation.tree.children.tail`. * * For more information about `Annotation`s, see the [[http://docs.scala-lang.org/overviews/reflection/annotations-names-scopes.html Reflection Guide: Annotations, Names, Scopes, and More]] * @@ -46,17 +43,22 @@ trait Annotations { self: Universe => */ type Annotation >: Null <: AnyRef with AnnotationApi - /** The constructor/extractor for `Annotation` instances. - * @group Extractors - */ - val Annotation: AnnotationExtractor + /** The constructor/extractor for `Annotation` instances. + * @group Extractors + */ + val Annotation: AnnotationExtractor /** An extractor class to create and pattern match with syntax `Annotation(tpe, scalaArgs, javaArgs)`. * Here, `tpe` is the annotation type, `scalaArgs` the payload of Scala annotations, and `javaArgs` the payload of Java annotations. * @group Extractors */ abstract class AnnotationExtractor { + def apply(tree: Tree): Annotation = treeToAnnotation(tree) + + @deprecated("Use `apply(tree: Tree): Annotation` instead", "2.11.0") def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation + + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])] } @@ -65,44 +67,64 @@ trait Annotations { self: Universe => * @group API */ trait AnnotationApi { + /** The tree underlying the annotation. */ + def tree: Tree = annotationToTree(this.asInstanceOf[Annotation]) + /** The type of the annotation. */ + @deprecated("Use `tree.tpe` instead", "2.11.0") def tpe: Type /** Payload of the Scala annotation: a list of abstract syntax trees that represent the argument. * Empty for Java annotations. */ + @deprecated("Use `tree.children.tail` instead", "2.11.0") def scalaArgs: List[Tree] /** Payload of the Java annotation: a list of name-value pairs. * Empty for Scala annotations. */ + @deprecated("Use `tree.children.tail` instead", "2.11.0") def javaArgs: ListMap[Name, JavaArgument] } + protected[scala] def annotationToTree(ann: Annotation): Tree + protected[scala] def treeToAnnotation(tree: Tree): Annotation + /** A Java annotation argument * @template * @group Annotations */ - type JavaArgument >: Null <: AnyRef + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + type JavaArgument >: Null <: AnyRef with JavaArgumentApi + /** Has no special methods. Is here to provides erased identity for `CompoundType`. + * @group API + */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + trait JavaArgumentApi /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")` * @template * @group Annotations */ - type LiteralArgument >: Null <: AnyRef with JavaArgument with LiteralArgumentApi + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + type LiteralArgument >: Null <: LiteralArgumentApi with JavaArgument /** The constructor/extractor for `LiteralArgument` instances. * @group Extractors */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") val LiteralArgument: LiteralArgumentExtractor /** An extractor class to create and pattern match with syntax `LiteralArgument(value)` * where `value` is the constant argument. * @group Extractors */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") abstract class LiteralArgumentExtractor { + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def apply(value: Constant): LiteralArgument + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(arg: LiteralArgument): Option[Constant] } @@ -110,8 +132,10 @@ trait Annotations { self: Universe => * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page. * @group API */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait LiteralArgumentApi { /** The underlying compile-time constant value. */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def value: Constant } @@ -119,19 +143,24 @@ trait Annotations { self: Universe => * @template * @group Annotations */ - type ArrayArgument >: Null <: AnyRef with JavaArgument with ArrayArgumentApi + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + type ArrayArgument >: Null <: ArrayArgumentApi with JavaArgument /** The constructor/extractor for `ArrayArgument` instances. * @group Extractors */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") val ArrayArgument: ArrayArgumentExtractor /** An extractor class to create and pattern match with syntax `ArrayArgument(args)` * where `args` is the argument array. * @group Extractors */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") abstract class ArrayArgumentExtractor { + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def apply(args: Array[JavaArgument]): ArrayArgument + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(arg: ArrayArgument): Option[Array[JavaArgument]] } @@ -139,8 +168,10 @@ trait Annotations { self: Universe => * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page. * @group API */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait ArrayArgumentApi { /** The underlying array of Java annotation arguments. */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def args: Array[JavaArgument] } @@ -148,19 +179,24 @@ trait Annotations { self: Universe => * @template * @group Annotations */ - type NestedArgument >: Null <: AnyRef with JavaArgument with NestedArgumentApi + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") + type NestedArgument >: Null <: NestedArgumentApi with JavaArgument /** The constructor/extractor for `NestedArgument` instances. * @group Extractors */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") val NestedArgument: NestedArgumentExtractor /** An extractor class to create and pattern match with syntax `NestedArgument(annotation)` * where `annotation` is the nested annotation. * @group Extractors */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") abstract class NestedArgumentExtractor { + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def apply(annotation: Annotation): NestedArgument + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def unapply(arg: NestedArgument): Option[Annotation] } @@ -168,8 +204,10 @@ trait Annotations { self: Universe => * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page. * @group API */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") trait NestedArgumentApi { /** The underlying nested annotation. */ + @deprecated("Use `Annotation.tree` to inspect annotation arguments", "2.11.0") def annotation: Annotation } } |