summaryrefslogtreecommitdiff
path: root/test/files
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-02-12 23:07:30 +0100
committerEugene Burmako <xeno.by@gmail.com>2012-02-12 23:07:33 +0100
commit6548dcf12d83e327df2f90048140fb95346b7e95 (patch)
treee20b3b6ce697af665983c3cc510d763a926650c6 /test/files
parent6b56405cb39b979dccbadd06110e283a254b6150 (diff)
downloadscala-6548dcf12d83e327df2f90048140fb95346b7e95.tar.gz
scala-6548dcf12d83e327df2f90048140fb95346b7e95.tar.bz2
scala-6548dcf12d83e327df2f90048140fb95346b7e95.zip
reifyAnnotations
Annotations are now supported by the reifier: * AnnotationInfos from symbols get transformed back into mods. * AnnotatedTypes are retained and are reified along with AnnotationInfos. Reification is no magic, and reification of annotations especially: * Annotations cannot refer to symbols defined inside the quasiquote. This restriction is due to the fact that we need to erase locally defined symbols before reifying to make subsequent reflective compilations succeed. However, while doing that, we also need to make sure that we don't make resulting ASTs non-compilable by removing essential information. This is tricky, and it more or less works for TypeTrees, but not for annotations that can contain arbitrary ASTs. For more details look into the comments to Reifiers.scala. * Classfile annotations that contain array arguments and are applied to types, i.e. the ones that generate AnnotatedTypes, cannot be reified. This is because of limitations of manifest infrastructure. Typechecking "Array(mirror.LiteralAnnotArg(...))" would require the compiler to produce a manifest for a path-dependent type, which cannot be done now. Review by @odersky.
Diffstat (limited to 'test/files')
-rw-r--r--test/files/neg/reify_ann2a.check4
-rw-r--r--test/files/neg/reify_ann2a.scala30
-rw-r--r--test/files/neg/reify_ann2b.check7
-rw-r--r--test/files/neg/reify_ann2b.scala30
-rw-r--r--test/files/run/reify_ann1a.check30
-rw-r--r--test/files/run/reify_ann1a.scala30
-rw-r--r--test/files/run/reify_ann1b.check30
-rw-r--r--test/files/run/reify_ann1b.scala30
-rw-r--r--test/files/run/reify_classfileann_a.check18
-rw-r--r--test/files/run/reify_classfileann_a.scala24
-rw-r--r--test/files/run/t5224.check9
-rw-r--r--test/files/run/t5224.scala9
-rw-r--r--test/files/run/t5225_1.check4
-rw-r--r--test/files/run/t5225_1.scala7
-rw-r--r--test/files/run/t5225_2.check4
-rw-r--r--test/files/run/t5225_2.scala7
-rw-r--r--test/files/run/t5419.check1
-rw-r--r--test/files/run/t5419.scala9
18 files changed, 283 insertions, 0 deletions
diff --git a/test/files/neg/reify_ann2a.check b/test/files/neg/reify_ann2a.check
new file mode 100644
index 0000000000..2afe37e1d8
--- /dev/null
+++ b/test/files/neg/reify_ann2a.check
@@ -0,0 +1,4 @@
+reify_ann2a.scala:9: error: exception during macro expansion: implementation restriction: cannot reify annotation @ann(immutable.this.List.apply[String]("1a")) which involves a symbol declared inside the block being reified
+ val tree = scala.reflect.Code.lift{
+ ^
+one error found
diff --git a/test/files/neg/reify_ann2a.scala b/test/files/neg/reify_ann2a.scala
new file mode 100644
index 0000000000..071919eb76
--- /dev/null
+++ b/test/files/neg/reify_ann2a.scala
@@ -0,0 +1,30 @@
+import scala.reflect._
+import scala.reflect.api._
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ // test 1: reify
+ val tree = scala.reflect.Code.lift{
+ class ann(bar: List[String]) extends StaticAnnotation
+
+ @ann(bar=List("1a")) @ann(bar=List("1b")) class C[@ann(bar=List("2a")) @ann(bar=List("2b")) T](@ann(bar=List("3a")) @ann(bar=List("3b")) x: T @ann(bar=List("4a")) @ann(bar=List("4b"))) {
+ @ann(bar=List("5a")) @ann(bar=List("5b")) def f(x: Int @ann(bar=List("6a")) @ann(bar=List("6b"))) = {
+ @ann(bar=List("7a")) @ann(bar=List("7b")) val r = (x + 3): @ann(bar=List("8a")) @ann(bar=List("8b"))
+ val s = 4: Int @ann(bar=List("9a")) @ann(bar=List("9b"))
+ r + s
+ }
+ }
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(ttree)
+} \ No newline at end of file
diff --git a/test/files/neg/reify_ann2b.check b/test/files/neg/reify_ann2b.check
new file mode 100644
index 0000000000..ceb70689f1
--- /dev/null
+++ b/test/files/neg/reify_ann2b.check
@@ -0,0 +1,7 @@
+reify_ann2b.scala:10: error: inner classes cannot be classfile annotations
+ class ann(bar: String) extends ClassfileAnnotation
+ ^
+reify_ann2b.scala:9: error: exception during macro expansion: implementation restriction: cannot reify annotation @ann(bar = "1a") which involves a symbol declared inside the block being reified
+ val tree = scala.reflect.Code.lift{
+ ^
+two errors found
diff --git a/test/files/neg/reify_ann2b.scala b/test/files/neg/reify_ann2b.scala
new file mode 100644
index 0000000000..74273ad6ec
--- /dev/null
+++ b/test/files/neg/reify_ann2b.scala
@@ -0,0 +1,30 @@
+import scala.reflect._
+import scala.reflect.api._
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+object Test extends App {
+ // test 1: reify
+ val tree = scala.reflect.Code.lift{
+ class ann(bar: String) extends ClassfileAnnotation
+
+ @ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) {
+ @ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = {
+ @ann(bar="7a") @ann(bar="7b") val r = (x + 3): @ann(bar="8a") @ann(bar="8b")
+ val s = 4: Int @ann(bar="9a") @ann(bar="9b")
+ r + s
+ }
+ }
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(ttree)
+} \ No newline at end of file
diff --git a/test/files/run/reify_ann1a.check b/test/files/run/reify_ann1a.check
new file mode 100644
index 0000000000..2822238706
--- /dev/null
+++ b/test/files/run/reify_ann1a.check
@@ -0,0 +1,30 @@
+{
+ @new ann(immutable.this.List.apply[String]("1a")) @new ann(immutable.this.List.apply[String]("1b")) class C[@new ann(immutable.this.List.apply[String]("2a")) @new ann(immutable.this.List.apply[String]("2b")) T>: Nothing <: Any] extends Object with ScalaObject {
+ @new ann(immutable.this.List.apply[String]("3a")) @new ann(immutable.this.List.apply[String]("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply[String]("4a")) @ann(immutable.this.List.apply[String]("4b")) = _;
+ def <init>(@new ann(immutable.this.List.apply[String]("3a")) @new ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4a")) @ann(immutable.this.List.apply[String]("4b"))) = {
+ super.<init>();
+ ()
+ };
+ @new ann(immutable.this.List.apply[String]("5a")) @new ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = {
+ @new ann(immutable.this.List.apply[String]("7a")) @new ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.$plus(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")));
+ val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")));
+ r.$plus(s)
+ }
+ };
+ ()
+}
+{
+ @ann(immutable.this.List.apply[String]("1a")) @ann(immutable.this.List.apply[String]("1b")) class C[@ann(immutable.this.List.apply[String]("2a")) @ann(immutable.this.List.apply[String]("2b")) T>: Nothing <: Any] extends Object with ScalaObject {
+ @ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a")) = _;
+ def <init>(@ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a"))): C[T] = {
+ C.super.<init>();
+ ()
+ };
+ @ann(immutable.this.List.apply[String]("5a")) @ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = {
+ @ann(immutable.this.List.apply[String]("7a")) @ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.+(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")));
+ val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")));
+ r.+(s)
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_ann1a.scala b/test/files/run/reify_ann1a.scala
new file mode 100644
index 0000000000..933ea21b20
--- /dev/null
+++ b/test/files/run/reify_ann1a.scala
@@ -0,0 +1,30 @@
+import scala.reflect._
+import scala.reflect.api._
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+class ann(bar: List[String]) extends StaticAnnotation
+
+object Test extends App {
+ // test 1: reify
+ val tree = scala.reflect.Code.lift{
+ @ann(bar=List("1a")) @ann(bar=List("1b")) class C[@ann(bar=List("2a")) @ann(bar=List("2b")) T](@ann(bar=List("3a")) @ann(bar=List("3b")) x: T @ann(bar=List("4a")) @ann(bar=List("4b"))) {
+ @ann(bar=List("5a")) @ann(bar=List("5b")) def f(x: Int @ann(bar=List("6a")) @ann(bar=List("6b"))) = {
+ @ann(bar=List("7a")) @ann(bar=List("7b")) val r = (x + 3): @ann(bar=List("8a")) @ann(bar=List("8b"))
+ val s = 4: Int @ann(bar=List("9a")) @ann(bar=List("9b"))
+ r + s
+ }
+ }
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(ttree)
+} \ No newline at end of file
diff --git a/test/files/run/reify_ann1b.check b/test/files/run/reify_ann1b.check
new file mode 100644
index 0000000000..e240e1e0ce
--- /dev/null
+++ b/test/files/run/reify_ann1b.check
@@ -0,0 +1,30 @@
+{
+ @new ann(bar = "1a") @new ann(bar = "1b") class C[@new ann(bar = "2a") @new ann(bar = "2b") T>: Nothing <: Any] extends Object with ScalaObject {
+ @new ann(bar = "3a") @new ann(bar = "3b") <paramaccessor> private[this] val x: T @ann(bar = "4a") @ann(bar = "4b") = _;
+ def <init>(@new ann(bar = "3a") @new ann(bar = "3b") x: T @ann(bar = "4a") @ann(bar = "4b")) = {
+ super.<init>();
+ ()
+ };
+ @new ann(bar = "5a") @new ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = {
+ @new ann(bar = "7a") @new ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.$plus(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a"));
+ val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a"));
+ r.$plus(s)
+ }
+ };
+ ()
+}
+{
+ @ann(bar = "1a") @ann(bar = "1b") class C[@ann(bar = "2a") @ann(bar = "2b") T>: Nothing <: Any] extends Object with ScalaObject {
+ @ann(bar = "3a") @ann(bar = "3b") <paramaccessor> private[this] val x: T @ann(bar = "4b") @ann(bar = "4a") = _;
+ def <init>(@ann(bar = "3a") @ann(bar = "3b") x: T @ann(bar = "4b") @ann(bar = "4a")): C[T] = {
+ C.super.<init>();
+ ()
+ };
+ @ann(bar = "5a") @ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = {
+ @ann(bar = "7a") @ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.+(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a"));
+ val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a"));
+ r.+(s)
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_ann1b.scala b/test/files/run/reify_ann1b.scala
new file mode 100644
index 0000000000..53dfe08086
--- /dev/null
+++ b/test/files/run/reify_ann1b.scala
@@ -0,0 +1,30 @@
+import scala.reflect._
+import scala.reflect.api._
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+class ann(bar: String) extends ClassfileAnnotation
+
+object Test extends App {
+ // test 1: reify
+ val tree = scala.reflect.Code.lift{
+ @ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) {
+ @ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = {
+ @ann(bar="7a") @ann(bar="7b") val r = (x + 3): @ann(bar="8a") @ann(bar="8b")
+ val s = 4: Int @ann(bar="9a") @ann(bar="9b")
+ r + s
+ }
+ }
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(ttree)
+} \ No newline at end of file
diff --git a/test/files/run/reify_classfileann_a.check b/test/files/run/reify_classfileann_a.check
new file mode 100644
index 0000000000..1773263a94
--- /dev/null
+++ b/test/files/run/reify_classfileann_a.check
@@ -0,0 +1,18 @@
+{
+ @new ann(bar = "1", quux = Array("2", "3"), baz = new ann(bar = "4")) class C extends Object with ScalaObject {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
+{
+ @ann(bar = "1", quux = ["2", "3"], baz = ann(bar = "4")) class C extends Object with ScalaObject {
+ def <init>(): C = {
+ C.super.<init>();
+ ()
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_classfileann_a.scala b/test/files/run/reify_classfileann_a.scala
new file mode 100644
index 0000000000..6bf4750bbc
--- /dev/null
+++ b/test/files/run/reify_classfileann_a.scala
@@ -0,0 +1,24 @@
+import scala.reflect._
+import scala.reflect.api._
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.Settings
+import reflect.runtime.Mirror.ToolBox
+
+class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends ClassfileAnnotation
+
+object Test extends App {
+ // test 1: reify
+ val tree = scala.reflect.Code.lift{
+ @ann(bar="1", quux=Array("2", "3"), baz = new ann(bar = "4")) class C
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val reporter = new ConsoleReporter(new Settings)
+ val toolbox = new ToolBox(reporter)
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(ttree)
+} \ No newline at end of file
diff --git a/test/files/run/t5224.check b/test/files/run/t5224.check
new file mode 100644
index 0000000000..5bead91b36
--- /dev/null
+++ b/test/files/run/t5224.check
@@ -0,0 +1,9 @@
+{
+ @new Foo(bar = "qwe") class C extends Object with ScalaObject {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
diff --git a/test/files/run/t5224.scala b/test/files/run/t5224.scala
new file mode 100644
index 0000000000..2226a69a05
--- /dev/null
+++ b/test/files/run/t5224.scala
@@ -0,0 +1,9 @@
+import scala.reflect._
+import scala.reflect.api._
+
+class Foo(bar: String) extends ClassfileAnnotation
+
+object Test extends App {
+ val tree = scala.reflect.Code.lift{@Foo(bar = "qwe") class C}.tree
+ println(tree.toString)
+} \ No newline at end of file
diff --git a/test/files/run/t5225_1.check b/test/files/run/t5225_1.check
new file mode 100644
index 0000000000..719da572c7
--- /dev/null
+++ b/test/files/run/t5225_1.check
@@ -0,0 +1,4 @@
+{
+ @new transient() @new volatile() var x: Int = 2;
+ ()
+}
diff --git a/test/files/run/t5225_1.scala b/test/files/run/t5225_1.scala
new file mode 100644
index 0000000000..a655b7dd71
--- /dev/null
+++ b/test/files/run/t5225_1.scala
@@ -0,0 +1,7 @@
+import scala.reflect._
+import scala.reflect.api._
+
+object Test extends App {
+ val tree = scala.reflect.Code.lift{@transient @volatile var x = 2}.tree
+ println(tree.toString)
+} \ No newline at end of file
diff --git a/test/files/run/t5225_2.check b/test/files/run/t5225_2.check
new file mode 100644
index 0000000000..c4f6b4761e
--- /dev/null
+++ b/test/files/run/t5225_2.check
@@ -0,0 +1,4 @@
+{
+ def foo(@new cloneable() x: Int): String = "";
+ ()
+}
diff --git a/test/files/run/t5225_2.scala b/test/files/run/t5225_2.scala
new file mode 100644
index 0000000000..65ea9b2f73
--- /dev/null
+++ b/test/files/run/t5225_2.scala
@@ -0,0 +1,7 @@
+import scala.reflect._
+import scala.reflect.api._
+
+object Test extends App {
+ val tree = scala.reflect.Code.lift{def foo(@cloneable x: Int) = ""}.tree
+ println(tree.toString)
+} \ No newline at end of file
diff --git a/test/files/run/t5419.check b/test/files/run/t5419.check
new file mode 100644
index 0000000000..7e6d739354
--- /dev/null
+++ b/test/files/run/t5419.check
@@ -0,0 +1 @@
+(5: Int(5) @Foo)
diff --git a/test/files/run/t5419.scala b/test/files/run/t5419.scala
new file mode 100644
index 0000000000..695786e5c4
--- /dev/null
+++ b/test/files/run/t5419.scala
@@ -0,0 +1,9 @@
+import scala.reflect._
+import scala.reflect.api._
+
+class Foo extends StaticAnnotation
+
+object Test extends App {
+ val tree = scala.reflect.Code.lift{5: @Foo}.tree
+ println(tree.toString)
+} \ No newline at end of file