diff options
author | Lukas Rytz <lukas.rytz@epfl.ch> | 2012-07-20 11:52:59 -0700 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@epfl.ch> | 2012-07-20 11:52:59 -0700 |
commit | b67828d03908a3b94ca42404355b28f0f999eb89 (patch) | |
tree | 9349bcf56a28c3465e64cefc95bdaf88334296cd /test | |
parent | 46da0ee29f380ccb455c9c3c2adcf375e0c13ccf (diff) | |
parent | 124f316b0813116c6574f60737e5b63f06f4329e (diff) | |
download | scala-b67828d03908a3b94ca42404355b28f0f999eb89.tar.gz scala-b67828d03908a3b94ca42404355b28f0f999eb89.tar.bz2 scala-b67828d03908a3b94ca42404355b28f0f999eb89.zip |
Merge pull request #894 from axel22/topic/static-annot-cherry-2.10.x
Implement @static annotation on singleton object fields.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/neg/static-annot.check | 19 | ||||
-rw-r--r-- | test/files/neg/static-annot.scala | 47 | ||||
-rw-r--r-- | test/files/run/static-annot/field.scala | 243 |
3 files changed, 309 insertions, 0 deletions
diff --git a/test/files/neg/static-annot.check b/test/files/neg/static-annot.check new file mode 100644 index 0000000000..66efebdcee --- /dev/null +++ b/test/files/neg/static-annot.check @@ -0,0 +1,19 @@ +static-annot.scala:8: error: Only members of top-level objects and their nested objects can be annotated with @static. + @static val bar = 1 + ^ +static-annot.scala:27: error: @static annotated field bar has the same name as a member of class Conflicting + @static val bar = 1 + ^ +static-annot.scala:37: error: The @static annotation is only allowed on public members. + @static private val bar = 1 + ^ +static-annot.scala:38: error: The @static annotation is only allowed on public members. + @static private val baz = 2 + ^ +static-annot.scala:39: error: The @static annotation is not allowed on lazy members. + @static lazy val bam = 3 + ^ +static-annot.scala:14: error: Only members of top-level objects and their nested objects can be annotated with @static. + @static val blah = 2 + ^ +6 errors found
\ No newline at end of file diff --git a/test/files/neg/static-annot.scala b/test/files/neg/static-annot.scala new file mode 100644 index 0000000000..c6c626d42b --- /dev/null +++ b/test/files/neg/static-annot.scala @@ -0,0 +1,47 @@ + + +import annotation.static + + + +class StaticInClass { + @static val bar = 1 +} + + +class NestedObjectInClass { + object Nested { + @static val blah = 2 + } +} + + +object NestedObjectInObject { + object Nested { + @static val succeed = 3 + } +} + + +object Conflicting { + @static val bar = 1 +} + + +class Conflicting { + val bar = 45 +} + + +object PrivateProtectedLazy { + @static private val bar = 1 + @static private val baz = 2 + @static lazy val bam = 3 +} + + +class PrivateProtectedLazy { + println(PrivateProtectedLazy.bar) + println(PrivateProtectedLazy.baz) + println(PrivateProtectedLazy.bam) +} diff --git a/test/files/run/static-annot/field.scala b/test/files/run/static-annot/field.scala new file mode 100644 index 0000000000..a7d8158321 --- /dev/null +++ b/test/files/run/static-annot/field.scala @@ -0,0 +1,243 @@ + + + +import java.lang.reflect.Modifier +import annotation.static +import reflect._ + + + +/* TEST 1 */ + +/* A @static-annotated field in the companion object should yield + * a static field in its companion class. + */ +object Foo { + @static val bar = 17 +} + + +class Foo + + +trait Check { + def checkStatic(cls: Class[_]) { + cls.getDeclaredFields.find(_.getName == "bar") match { + case Some(f) => assert(Modifier.isStatic(f.getModifiers), "no static modifier") + case None => assert(false, "no static field bar in class") + } + } + + def test(): Unit +} + + +object Test1 extends Check { + def test() { + checkStatic(classOf[Foo]) + assert(Foo.bar == 17, "Companion object field should be 17.") + } +} + + +/* TEST 2 */ + +class Foo2 + + +/** The order of declaring the class and its companion is inverted now. */ +object Foo2 { + @static val bar = 199 +} + + +object Test2 extends Check { + def test() { + checkStatic(Class.forName("Foo3")) + assert(Foo3.bar == 1984, "Companion object field should be 1984.") + } +} + + +/* TEST 3 */ + +/** The case where there is no explicit companion class */ +object Foo3 { + @static val bar = 1984 +} + + +object Test3 extends Check { + def test() { + checkStatic(Class.forName("Foo3")) + assert(Foo3.bar == 1984, "Companion object field should be 1984.") + } +} + + +/* TEST 4 */ + +/** We want to be able to generate atomic reference field updaters on the companion object + * so that they are created only once per class declaration, but we want them to actually + * be initialize __in the static initializer of the class itself__. + * This is extremely important, because otherwise the creation of the ARFU fails, since it uses + * trickery to detect the caller and compare it to the owner of the field being modified. + * Previously, this used to be circumvented through the use of Java base classes. A pain. + */ +class ArfuTarget { + @volatile var strfield = ArfuTarget.STR + + def CAS(ov: String, nv: String): Boolean = { + ArfuTarget.arfu.compareAndSet(this, ov, nv) + } +} + + +object ArfuTarget { + @static val arfu = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater(classOf[ArfuTarget], classOf[String], "strfield") + val STR = "Some string" +} + + +object Test4 extends Check { + def checkArfu() { + val at = new ArfuTarget + assert(at.strfield == ArfuTarget.STR) + at.CAS(ArfuTarget.STR, null) + assert(at.strfield == null) + } + + def test() { + checkArfu() + } +} + + +/* TEST 5 */ + +/** Although our main use-case is to use final static fields, we should be able to use non-final too. + * Here we set the static field of the class by using the setters in the companion object. + * It is legal to do so using the reference to `Foo` directly (in which case the callsites + * are rewritten to access the static field directly), or through an interface `Var` (in + * which case the getter and the setter for `field` access the static field in `Var`). + */ +trait Var { + var field: Int +} + +object VarHolder extends Var { + @static var field = 1 +} + + +object Test5 extends Check { + def test() { + assert(VarHolder.field == 1) + VarHolder.field = 2 + assert(VarHolder.field == 2) + val vh: Var = VarHolder + vh.field = 3 + assert(vh.field == 3) + } +} + + +/* TEST 6 */ + +/** Here we test flattening the static ctor body and changing the owners of local definitions. */ +object Foo6 { + var companionField = 101 + @static val staticField = { + val intermediate = companionField + 1 + intermediate * 2 + } +} + + +object Test6 extends Check { + def test() { + assert(Foo6.staticField == 204) + } +} + + + +/* TEST 7 */ + +/** Here we test objects nested in top-level objects */ +object Foo7 { + object AndHisFriend { + @static val bar = "string" + } + class AndHisFriend +} + + +object Test7 extends Check { + def test() { + checkStatic(classOf[Foo7.AndHisFriend]) + assert(Foo7.AndHisFriend.bar == "string") + } +} + + + +/* TEST 8 */ + +object Foo8 { + @static val field = 7 + + val function: () => Int = () => { + field + 1 + } + + val anon = new Runnable { + def run() { + assert(field == 7, "runnable asserting field is 7") + } + } + + @static var mutable = 10 + + val mutation: () => Unit = () => { + mutable += 1 + } +} + +object Test8 { + def test() { + assert(Foo8.function() == 8, "function must return 8") + Foo8.anon.run() + assert(Foo8.mutable == 10, "mutable is 10") + Foo8.mutation() + assert(Foo8.mutable == 11, "mutable is 11") + Foo8.mutation() + assert(Foo8.mutable == 12, "mutable is 12") + } +} + + + + +/* main */ + +object Test { + + def main(args: Array[String]) { + Test1.test() + Test2.test() + Test3.test() + Test4.test() + Test5.test() + Test6.test() + Test7.test() + Test8.test() + } + +} + + + + + + |