summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2014-01-28 19:37:59 +0300
committerEugene Burmako <xeno.by@gmail.com>2014-02-14 14:19:44 +0100
commit0268e03cb461b0c7e8ae2082894988395fc0994a (patch)
tree7dec4c177aad62a2209601a0f5327e243c3340b2
parentc7fd03900b7023967f22932f1f32b98d57983e9b (diff)
downloadscala-0268e03cb461b0c7e8ae2082894988395fc0994a.tar.gz
scala-0268e03cb461b0c7e8ae2082894988395fc0994a.tar.bz2
scala-0268e03cb461b0c7e8ae2082894988395fc0994a.zip
SI-8118 simplifies Annotation down to a plain Tree
As per https://groups.google.com/forum/#!topic/scala-internals/8v2UL-LR9yY, annotations don’t have to be represented as AnnotationInfos and can be reduced to plain Trees. Due to compatibility reasons and because of the limitations of the cake pattern used in implementing current version of Reflection, we can’t just say `type Annotation = Tree`, however what we can definitely do is to deprecate all the methods on Annotation and expose `tree: Tree` instead.
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala17
-rw-r--r--src/reflect/scala/reflect/api/Annotations.scala58
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala61
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--test/files/run/macro-vampire-false-warning/Macros_1.scala4
-rw-r--r--test/files/run/reflection-java-annotations.check3
-rw-r--r--test/files/run/reflection-java-annotations/Test_2.scala2
-rw-r--r--test/files/run/reflection-scala-annotations.check7
-rw-r--r--test/files/run/reflection-scala-annotations.scala16
-rw-r--r--test/files/run/t6860.scala2
-rw-r--r--test/files/run/t8190.check4
-rw-r--r--test/files/run/t8190.scala12
12 files changed, 147 insertions, 41 deletions
diff --git a/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala
index bd60faf4cd..ce26232e5f 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenAnnotationInfos.scala
@@ -38,19 +38,10 @@ trait GenAnnotationInfos {
}
}
- def reifyClassfileAnnotArg(arg: ClassfileAnnotArg): Tree = arg match {
- case LiteralAnnotArg(const) =>
- mirrorFactoryCall(nme.LiteralAnnotArg, reifyProduct(const))
- case ArrayAnnotArg(args) =>
- mirrorFactoryCall(nme.ArrayAnnotArg, scalaFactoryCall(nme.Array, args map reifyClassfileAnnotArg: _*))
- case NestedAnnotArg(ann) =>
- mirrorFactoryCall(nme.NestedAnnotArg, reifyAnnotationInfo(ann))
- case _ =>
- sys.error(s"Don't know what to do with $arg")
- }
-
// if you reify originals of anns, you get SO when trying to reify AnnotatedTypes, so screw it - after all, it's not that important
- val reifiedAssocs = ann.assocs map (assoc => scalaFactoryCall(nme.Tuple2, reify(assoc._1), reifyClassfileAnnotArg(assoc._2)))
- mirrorFactoryCall(nme.Annotation, reify(ann.atp), mkList(reifiedArgs), mkListMap(reifiedAssocs))
+ val Apply(Select(New(tpt), name), args) = annotationToTree(ann)
+ val reifiedAtp = mirrorCall(nme.Select, mirrorCall(nme.New, mirrorCall(nme.TypeTree, reifyType(tpt.tpe))), reify(name))
+ val reifiedAnnRepr = mirrorCall(nme.Apply, reifiedAtp, reifyList(args))
+ mirrorFactoryCall(nme.Annotation, reifiedAnnRepr)
}
}
diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala
index 5171a2e047..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]]
*
@@ -56,7 +53,12 @@ trait Annotations { self: Universe =>
* @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,48 +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
*/
+ @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
*/
+ @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]
}
@@ -114,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
}
@@ -123,19 +143,24 @@ trait Annotations { self: Universe =>
* @template
* @group Annotations
*/
+ @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]]
}
@@ -143,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]
}
@@ -152,19 +179,24 @@ trait Annotations { self: Universe =>
* @template
* @group Annotations
*/
+ @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]
}
@@ -172,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
}
}
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index f42e0c44c9..19e9eef851 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -10,10 +10,12 @@ package internal
import pickling.ByteCodecs
import scala.annotation.tailrec
import scala.collection.immutable.ListMap
+import scala.language.postfixOps
/** AnnotationInfo and its helpers */
trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
- import definitions.{ ThrowsClass, ThrowableClass, StaticAnnotationClass, isMetaAnnotation }
+ import definitions._
+ import treeInfo._
// Common annotation code between Symbol and Type.
// For methods altering the annotation list, on Symbol it mutates
@@ -344,6 +346,63 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
}
implicit val AnnotationTag = ClassTag[AnnotationInfo](classOf[AnnotationInfo])
+ protected[scala] def annotationToTree(ann: Annotation): Tree = {
+ def reverseEngineerArgs(): List[Tree] = {
+ def reverseEngineerArg(jarg: ClassfileAnnotArg): Tree = jarg match {
+ case LiteralAnnotArg(const) =>
+ val tpe = if (const.tag == UnitTag) UnitTpe else ConstantType(const)
+ Literal(const) setType tpe
+ case ArrayAnnotArg(jargs) =>
+ val args = jargs map reverseEngineerArg
+ // TODO: I think it would be a good idea to typecheck Java annotations using a more traditional algorithm
+ // sure, we can't typecheck them as is using the `new jann(foo = bar)` syntax (because jann is going to be an @interface)
+ // however we can do better than `typedAnnotation` by desugaring the aforementioned expression to
+ // something like `new jann() { override def annotatedType() = ...; override def foo = bar }`
+ // and then using the results of that typecheck to produce a Java-compatible classfile entry
+ // in that case we're going to have correctly typed Array.apply calls, however that's 2.12 territory
+ // and for 2.11 exposing an untyped call to ArrayModule should suffice
+ Apply(Ident(ArrayModule), args.toList)
+ case NestedAnnotArg(ann: Annotation) =>
+ annotationToTree(ann)
+ case _ =>
+ EmptyTree
+ }
+ def reverseEngineerArgs(jargs: List[(Name, ClassfileAnnotArg)]): List[Tree] = jargs match {
+ case (name, jarg) :: rest => AssignOrNamedArg(Ident(name), reverseEngineerArg(jarg)) :: reverseEngineerArgs(rest)
+ case Nil => Nil
+ }
+ if (ann.javaArgs.isEmpty) ann.scalaArgs
+ else reverseEngineerArgs(ann.javaArgs.toList)
+ }
+
+ // TODO: at the moment, constructor selection is unattributed, because AnnotationInfos lack necessary information
+ // later on, in 2.12, for every annotation we could save an entire tree instead of just bits and pieces
+ // but for 2.11 the current situation will have to do
+ val ctorSelection = Select(New(TypeTree(ann.atp)), nme.CONSTRUCTOR)
+ Apply(ctorSelection, reverseEngineerArgs()) setType ann.atp
+ }
+
+ protected[scala] def treeToAnnotation(tree: Tree): Annotation = tree match {
+ case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
+ def encodeJavaArg(arg: Tree): ClassfileAnnotArg = arg match {
+ case Literal(const) => LiteralAnnotArg(const)
+ case Apply(ArrayModule, args) => ArrayAnnotArg(args map encodeJavaArg toArray)
+ case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => NestedAnnotArg(treeToAnnotation(arg))
+ case _ => throw new Exception("unexpected java argument shape $arg: literals, arrays and nested annotations are supported")
+ }
+ def encodeJavaArgs(args: List[Tree]): List[(Name, ClassfileAnnotArg)] = args match {
+ case AssignOrNamedArg(Ident(name), arg) :: rest => (name, encodeJavaArg(arg)) :: encodeJavaArgs(rest)
+ case arg :: rest => throw new Exception("unexpected java argument shape $arg: only AssignOrNamedArg trees are supported")
+ case Nil => Nil
+ }
+ val atp = tpt.tpe
+ if (atp != null && (atp.typeSymbol isNonBottomSubClass StaticAnnotationClass)) AnnotationInfo(atp, args, Nil)
+ else if (atp != null && (atp.typeSymbol isNonBottomSubClass ClassfileAnnotationClass)) AnnotationInfo(atp, Nil, encodeJavaArgs(args))
+ else throw new Exception(s"unexpected annotation type $atp: only subclasses of StaticAnnotation and ClassfileAnnotation are supported")
+ case _ =>
+ throw new Exception("""unexpected tree shape: only q"new $annType(..$args)" is supported""")
+ }
+
object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil)
object ErroneousAnnotation extends CompleteAnnotationInfo(ErrorType, Nil, Nil)
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 71c4009a62..01df1d6003 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -575,6 +575,7 @@ trait StdNames {
val Annotation: NameType = "Annotation"
val Any: NameType = "Any"
val AnyVal: NameType = "AnyVal"
+ val Apply: NameType = "Apply"
val ArrayAnnotArg: NameType = "ArrayAnnotArg"
val ConstantType: NameType = "ConstantType"
val EmptyPackage: NameType = "EmptyPackage"
@@ -588,6 +589,7 @@ trait StdNames {
val LiteralAnnotArg: NameType = "LiteralAnnotArg"
val Modifiers: NameType = "Modifiers"
val NestedAnnotArg: NameType = "NestedAnnotArg"
+ val New: NameType = "New"
val NoFlags: NameType = "NoFlags"
val NoSymbol: NameType = "NoSymbol"
val NoMods: NameType = "NoMods"
diff --git a/test/files/run/macro-vampire-false-warning/Macros_1.scala b/test/files/run/macro-vampire-false-warning/Macros_1.scala
index 0912bfba0c..51869d214f 100644
--- a/test/files/run/macro-vampire-false-warning/Macros_1.scala
+++ b/test/files/run/macro-vampire-false-warning/Macros_1.scala
@@ -10,8 +10,8 @@ object Macros {
def selFieldImpl(c: Context) = {
import c.universe._
val field = c.macroApplication.symbol
- val bodyAnn = field.annotations.filter(_.tpe <:< typeOf[body]).head
- c.Expr[Any](bodyAnn.scalaArgs.head)
+ val bodyAnn = field.annotations.filter(_.tree.tpe <:< typeOf[body]).head
+ c.Expr[Any](bodyAnn.tree.children(1))
}
def mkObjectImpl(c: Context)(xs: c.Expr[Any]*) = {
diff --git a/test/files/run/reflection-java-annotations.check b/test/files/run/reflection-java-annotations.check
index 2d37fff1f4..72d40989fe 100644
--- a/test/files/run/reflection-java-annotations.check
+++ b/test/files/run/reflection-java-annotations.check
@@ -1 +1,4 @@
+warning: there were 1 deprecation warning(s); re-run with -deprecation for details
List(JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = [101, 101], v102 = [102, 102], v103 = ['g', 'g'], v104 = [104, 104], v105 = [105L, 105L], v106 = [106.0, 106.0], v107 = [107.0, 107.0], v108 = [false, true], v11 = classOf[JavaAnnottee_1], v110 = ["hello", "world"], v111 = [classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]], v112 = [FOO, BAR], v113 = [JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\027', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)], v12 = FOO, v13 = JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\03', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false))
+=======
+new JavaComplexAnnotation_1(v1 = 1, v10 = "hello", v101 = Array(101, 101), v102 = Array(102, 102), v103 = Array('g', 'g'), v104 = Array(104, 104), v105 = Array(105L, 105L), v106 = Array(106.0, 106.0), v107 = Array(107.0, 107.0), v108 = Array(false, true), v11 = classOf[JavaAnnottee_1], v110 = Array("hello", "world"), v111 = Array(classOf[JavaSimpleAnnotation_1], classOf[JavaComplexAnnotation_1]), v112 = Array(FOO, BAR), v113 = Array(new JavaSimpleAnnotation_1(v1 = 21, v10 = "world2", v11 = classOf[JavaComplexAnnotation_1], v12 = BAR, v2 = 22, v3 = '\027', v4 = 24, v5 = 25L, v6 = 26.0, v7 = 27.0, v8 = false)), v12 = FOO, v13 = new JavaSimpleAnnotation_1(v1 = 11, v10 = "world1", v11 = classOf[JavaSimpleAnnotation_1], v12 = FOO, v2 = 12, v3 = '\r', v4 = 14, v5 = 15L, v6 = 16.0, v7 = 17.0, v8 = false), v2 = 2, v3 = '\03', v4 = 4, v5 = 5L, v6 = 6.0, v7 = 7.0, v8 = false)
diff --git a/test/files/run/reflection-java-annotations/Test_2.scala b/test/files/run/reflection-java-annotations/Test_2.scala
index d2c3157071..5c9e9afdb7 100644
--- a/test/files/run/reflection-java-annotations/Test_2.scala
+++ b/test/files/run/reflection-java-annotations/Test_2.scala
@@ -4,4 +4,6 @@ object Test extends App {
sym.typeSignature
sym.annotations foreach (_.javaArgs)
println(sym.annotations)
+ println("=======")
+ sym.annotations.map(_.tree).map(println)
} \ No newline at end of file
diff --git a/test/files/run/reflection-scala-annotations.check b/test/files/run/reflection-scala-annotations.check
new file mode 100644
index 0000000000..5bc2786161
--- /dev/null
+++ b/test/files/run/reflection-scala-annotations.check
@@ -0,0 +1,7 @@
+reflection-scala-annotations.scala:5: warning: Implementation restriction: subclassing Classfile does not
+make your annotation visible at runtime. If that is what
+you want, you must write the annotation class in Java.
+class jann(x: Int, y: Array[Int]) extends ClassfileAnnotation
+ ^
+new sann(1, immutable.this.List.apply[Int](1, 2))
+new jann(y = Array(1, 2), x = 2)
diff --git a/test/files/run/reflection-scala-annotations.scala b/test/files/run/reflection-scala-annotations.scala
new file mode 100644
index 0000000000..f6a6895ee0
--- /dev/null
+++ b/test/files/run/reflection-scala-annotations.scala
@@ -0,0 +1,16 @@
+import scala.reflect.runtime.universe._
+import scala.annotation._
+
+class sann(x: Int, y: List[Int]) extends StaticAnnotation
+class jann(x: Int, y: Array[Int]) extends ClassfileAnnotation
+
+@sann(1, List(1, 2))
+class S
+
+@jann(y = Array(1, 2), x = 2)
+class J
+
+object Test extends App {
+ println(symbolOf[S].annotations.head.tree)
+ println(symbolOf[J].annotations.head.tree)
+}
diff --git a/test/files/run/t6860.scala b/test/files/run/t6860.scala
index 2dcc2a67f7..1391af3430 100644
--- a/test/files/run/t6860.scala
+++ b/test/files/run/t6860.scala
@@ -13,7 +13,7 @@ object Test {
def main(args: Array[String]): Unit = {
val members = typeOf[A].declarations.toList
- val tpes = members flatMap (_.annotations) map (_.tpe)
+ val tpes = members flatMap (_.annotations) map (_.tree.tpe)
tpes.map(_.toString).sorted foreach println
}
diff --git a/test/files/run/t8190.check b/test/files/run/t8190.check
index 2362af7320..d117bf3294 100644
--- a/test/files/run/t8190.check
+++ b/test/files/run/t8190.check
@@ -1,8 +1,4 @@
Annotation
-JavaArgument
-LiteralArgument
-ArrayArgument
-NestedArgument
Constant
Mirror
Name
diff --git a/test/files/run/t8190.scala b/test/files/run/t8190.scala
index f8abb73f15..012d0ad347 100644
--- a/test/files/run/t8190.scala
+++ b/test/files/run/t8190.scala
@@ -4,10 +4,6 @@ trait Overloads {
// makes sure noone erases to Any or AnyRef
def test(x: AnyRef) = "AnyRef"
def test(x: Annotation) = "Annotation"
- def test(x: JavaArgument) = "JavaArgument"
- def test(x: LiteralArgument) = "LiteralArgument"
- def test(x: ArrayArgument) = "ArrayArgument"
- def test(x: NestedArgument) = "NestedArgument"
def test(x: Constant) = "Constant"
def test(x: Mirror) = "Mirror"
def test(x: Name) = "Name"
@@ -110,14 +106,14 @@ object Test extends App with Overloads {
types = types.filter(_ != "ModifiersCreator") // type ModifiersCreator = ModifiersExtractor
types = types.filter(_ != "FlagSet") // type FlagSet
types = types.filter(_ != "RuntimeClass") // type RuntimeClass = java.lang.Class[_]
+ types = types.filter(_ != "JavaArgument") // deprecated
+ types = types.filter(_ != "LiteralArgument") // deprecated
+ types = types.filter(_ != "ArrayArgument") // deprecated
+ types = types.filter(_ != "NestedArgument") // deprecated
val diff = types.toList diff buf.toList
println("uncovered type members: " + diff)
}
record(test(null: Annotation))
- record(test(null: JavaArgument))
- record(test(null: LiteralArgument))
- record(test(null: ArrayArgument))
- record(test(null: NestedArgument))
record(test(null: Constant))
record(test(null: Mirror))
record(test(null: Name))