summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala58
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala2
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--test/files/run/t3236/AnnotationTest.scala33
-rw-r--r--test/files/run/t3236/BooleanAnnotation.java7
-rw-r--r--test/files/run/t3236/ByteAnnotation.java7
-rw-r--r--test/files/run/t3236/CharAnnotation.java7
-rw-r--r--test/files/run/t3236/Constants.java34
-rw-r--r--test/files/run/t3236/DoubleAnnotation.java7
-rw-r--r--test/files/run/t3236/FloatAnnotation.java7
-rw-r--r--test/files/run/t3236/IntAnnotation.java7
-rw-r--r--test/files/run/t3236/LongAnnotation.java7
-rw-r--r--test/files/run/t3236/ShortAnnotation.java7
-rw-r--r--test/files/run/t3236/StringAnnotation.java7
-rw-r--r--test/files/run/t3236/Test.scala44
15 files changed, 234 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index eb25eb6e06..bc1c19237a 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -567,10 +567,64 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: TermName): ValDef = {
val tpt1 = optArrayBrackets(tpt)
- if (in.token == EQUALS && !mods.isParameter) skipTo(COMMA, SEMI)
+
+ /** Tries to detect final static literals syntactically and returns a constant type replacement */
+ def optConstantTpe(): Tree = {
+ in.nextToken()
+
+ def constantTpe(lit: Any): Tree =
+ try TypeTree(ConstantType(Constant(lit)))
+ finally in.nextToken()
+
+ def byType(value: Long): Tree =
+ tpt.tpe match {
+ case ByteTpe => constantTpe(value.toByte)
+ case CharTpe => constantTpe(value.toChar)
+ case ShortTpe => constantTpe(value.toShort)
+ case IntTpe => constantTpe(value.toInt)
+ case LongTpe => constantTpe(value.toLong)
+ case _ => tpt1
+ }
+
+ if (mods.hasFlag(Flags.STATIC) && mods.isFinal) {
+ def lit(negate: Boolean): Tree =
+ if (in.lookaheadToken == SEMI)
+ in.token match {
+ case TRUE if tpt.tpe == BooleanTpe => constantTpe(!negate)
+ case FALSE if tpt.tpe == BooleanTpe => constantTpe(negate)
+ case CHARLIT => byType(in.name.charAt(0))
+ case INTLIT => byType(in.intVal(negate))
+ case LONGLIT if tpt.tpe == LongTpe => constantTpe(in.intVal(negate))
+ case FLOATLIT if tpt.tpe == FloatTpe => constantTpe(in.floatVal(negate).toFloat)
+ case DOUBLELIT if tpt.tpe == DoubleTpe => constantTpe(in.floatVal(negate))
+ case STRINGLIT =>
+ tpt match {
+ case Ident(TypeName("String")) => constantTpe(in.name.toString)
+ case _ => tpt1
+ }
+ case _ => tpt1
+ }
+ else tpt1
+
+ in.token match {
+ case MINUS | BANG =>
+ in.nextToken()
+ lit(negate = true)
+ case other => lit(negate = false)
+ }
+ } else tpt1
+ }
+
+ val tpt2: Tree =
+ if (in.token == EQUALS && !mods.isParameter) {
+ val res = optConstantTpe()
+ skipTo(COMMA, SEMI)
+ res
+ } else tpt1
+
val mods1 = if (mods.isFinal) mods &~ Flags.FINAL else mods | Flags.MUTABLE
atPos(pos) {
- ValDef(mods1, name, tpt1, blankExpr)
+ ValDef(mods1, name, tpt2, blankExpr)
}
}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
index ac86dfd665..94c9d07939 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -89,6 +89,7 @@ trait JavaScanners extends ast.parser.ScannersCommon {
javanme.ELSEkw -> ELSE,
javanme.ENUMkw -> ENUM,
javanme.EXTENDSkw -> EXTENDS,
+ javanme.FALSEkw -> FALSE,
javanme.FINALkw -> FINAL,
javanme.FINALLYkw -> FINALLY,
javanme.FLOATkw -> FLOAT,
@@ -118,6 +119,7 @@ trait JavaScanners extends ast.parser.ScannersCommon {
javanme.THROWkw -> THROW,
javanme.THROWSkw -> THROWS,
javanme.TRANSIENTkw -> TRANSIENT,
+ javanme.TRUEkw -> TRUE,
javanme.TRYkw -> TRY,
javanme.VOIDkw -> VOID,
javanme.VOLATILEkw -> VOLATILE,
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index a0688e129c..5e2bbf9598 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -1103,6 +1103,7 @@ trait StdNames {
final val ELSEkw: TermName = kw("else")
final val ENUMkw: TermName = kw("enum")
final val EXTENDSkw: TermName = kw("extends")
+ final val FALSEkw: TermName = kw("false")
final val FINALkw: TermName = kw("final")
final val FINALLYkw: TermName = kw("finally")
final val FLOATkw: TermName = kw("float")
@@ -1132,6 +1133,7 @@ trait StdNames {
final val THROWkw: TermName = kw("throw")
final val THROWSkw: TermName = kw("throws")
final val TRANSIENTkw: TermName = kw("transient")
+ final val TRUEkw: TermName = kw("true")
final val TRYkw: TermName = kw("try")
final val VOIDkw: TermName = kw("void")
final val VOLATILEkw: TermName = kw("volatile")
diff --git a/test/files/run/t3236/AnnotationTest.scala b/test/files/run/t3236/AnnotationTest.scala
new file mode 100644
index 0000000000..c2f9ae7837
--- /dev/null
+++ b/test/files/run/t3236/AnnotationTest.scala
@@ -0,0 +1,33 @@
+trait AnnotationTest {
+ @BooleanAnnotation(Constants.BooleanTrue)
+ @ByteAnnotation(Constants.Byte)
+ @CharAnnotation(Constants.Char)
+ @ShortAnnotation(Constants.Short)
+ @IntAnnotation(Constants.Int)
+ @LongAnnotation(Constants.Long)
+ @FloatAnnotation(Constants.Float)
+ @DoubleAnnotation(Constants.Double)
+ @StringAnnotation(Constants.String)
+ def test1: Unit
+
+ @BooleanAnnotation(Constants.InvertedBoolean)
+ @ByteAnnotation(Constants.NegativeByte)
+ @ShortAnnotation(Constants.NegativeShort)
+ @IntAnnotation(Constants.NegativeInt)
+ @LongAnnotation(Constants.NegativeLong)
+ @FloatAnnotation(Constants.NegativeFloat)
+ @DoubleAnnotation(Constants.NegativeDouble)
+ @StringAnnotation(Constants.NegativeString)
+ def test2: Unit
+
+ @BooleanAnnotation(Constants.BooleanFalse)
+ @ByteAnnotation(Constants.LiteralCharAsByte)
+ @CharAnnotation(Constants.LiteralChar)
+ @ShortAnnotation(Constants.LiteralCharAsShort)
+ @IntAnnotation(Constants.LiteralCharAsInt)
+ @LongAnnotation(Constants.LiteralCharAsLong)
+ def test3: Unit
+
+ @LongAnnotation(Constants.LiteralIntAsLong)
+ def test4: Unit
+}
diff --git a/test/files/run/t3236/BooleanAnnotation.java b/test/files/run/t3236/BooleanAnnotation.java
new file mode 100644
index 0000000000..7e57a5e0db
--- /dev/null
+++ b/test/files/run/t3236/BooleanAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface BooleanAnnotation {
+ boolean value();
+}
diff --git a/test/files/run/t3236/ByteAnnotation.java b/test/files/run/t3236/ByteAnnotation.java
new file mode 100644
index 0000000000..c986fa5d27
--- /dev/null
+++ b/test/files/run/t3236/ByteAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ByteAnnotation {
+ byte value();
+}
diff --git a/test/files/run/t3236/CharAnnotation.java b/test/files/run/t3236/CharAnnotation.java
new file mode 100644
index 0000000000..1715f1b7de
--- /dev/null
+++ b/test/files/run/t3236/CharAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CharAnnotation {
+ char value();
+}
diff --git a/test/files/run/t3236/Constants.java b/test/files/run/t3236/Constants.java
new file mode 100644
index 0000000000..16b4001f76
--- /dev/null
+++ b/test/files/run/t3236/Constants.java
@@ -0,0 +1,34 @@
+public class Constants {
+ public static final boolean BooleanTrue = true;
+ public static final boolean BooleanFalse = false;
+ public static final boolean InvertedBoolean = !true;
+
+ public static final byte Byte = 23;
+ public static final byte NegativeByte = -42;
+ public static final byte LiteralCharAsByte = 'a';
+
+ public static final char Char = 33;
+ public static final char LiteralChar = 'b';
+
+ public static final short Short = 0x1234;
+ public static final short NegativeShort= -0x5678;
+ public static final short LiteralCharAsShort = 'c';
+
+ public static final int Int = 0xabcdef;
+ public static final int NegativeInt = -12345678;
+ public static final int LiteralCharAsInt = 'd';
+
+ public static final long Long = 0x1234567890abcdefL;
+ public static final long NegativeLong = -0xfedcba09876L;
+ public static final long LiteralCharAsLong = 'e';
+ public static final long LiteralIntAsLong = 0x12345678;
+
+ public static final float Float = 42.232323f;
+ public static final float NegativeFloat = -3.1415f;
+
+ public static final double Double = 23.4243598374594d;
+ public static final double NegativeDouble = -42.2324358934589734859d;
+
+ public static final String String = "testConstant";
+ public static final String NegativeString = "!#!$!grml%!%!$#@@@";
+}
diff --git a/test/files/run/t3236/DoubleAnnotation.java b/test/files/run/t3236/DoubleAnnotation.java
new file mode 100644
index 0000000000..1eb8223f4e
--- /dev/null
+++ b/test/files/run/t3236/DoubleAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DoubleAnnotation {
+ double value();
+}
diff --git a/test/files/run/t3236/FloatAnnotation.java b/test/files/run/t3236/FloatAnnotation.java
new file mode 100644
index 0000000000..c723a25fad
--- /dev/null
+++ b/test/files/run/t3236/FloatAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FloatAnnotation {
+ float value();
+}
diff --git a/test/files/run/t3236/IntAnnotation.java b/test/files/run/t3236/IntAnnotation.java
new file mode 100644
index 0000000000..2ffad8890c
--- /dev/null
+++ b/test/files/run/t3236/IntAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IntAnnotation {
+ int value();
+}
diff --git a/test/files/run/t3236/LongAnnotation.java b/test/files/run/t3236/LongAnnotation.java
new file mode 100644
index 0000000000..9f80b41398
--- /dev/null
+++ b/test/files/run/t3236/LongAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface LongAnnotation {
+ long value();
+}
diff --git a/test/files/run/t3236/ShortAnnotation.java b/test/files/run/t3236/ShortAnnotation.java
new file mode 100644
index 0000000000..f0a35892c7
--- /dev/null
+++ b/test/files/run/t3236/ShortAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ShortAnnotation {
+ short value();
+}
diff --git a/test/files/run/t3236/StringAnnotation.java b/test/files/run/t3236/StringAnnotation.java
new file mode 100644
index 0000000000..0fdc1ead38
--- /dev/null
+++ b/test/files/run/t3236/StringAnnotation.java
@@ -0,0 +1,7 @@
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface StringAnnotation {
+ String value();
+}
diff --git a/test/files/run/t3236/Test.scala b/test/files/run/t3236/Test.scala
new file mode 100644
index 0000000000..7e351e0b6b
--- /dev/null
+++ b/test/files/run/t3236/Test.scala
@@ -0,0 +1,44 @@
+import scala.language.reflectiveCalls
+
+object Test extends App {
+ val theClass = classOf[AnnotationTest]
+
+ def annotation[T <: java.lang.annotation.Annotation](annotationClass: Class[T], methodName: String): T =
+ theClass.getDeclaredMethod(methodName)
+ .getAnnotation[T](annotationClass)
+
+ def check[T, U <: java.lang.annotation.Annotation { def value(): T } ](annotationClass: Class[U], methodName: String, expected: T): Unit = {
+ val a = annotation(annotationClass, methodName)
+ assert(a != null, s"No annotation of type $annotationClass found on method $methodName")
+ assert(a.value() == expected, s"Actual value of annotation $a on $methodName was not of expected value $expected")
+ }
+
+ check(classOf[BooleanAnnotation], "test1", Constants.BooleanTrue)
+ check(classOf[ByteAnnotation], "test1", Constants.Byte)
+ check(classOf[CharAnnotation], "test1", Constants.Char)
+ check(classOf[ShortAnnotation], "test1", Constants.Short)
+ check(classOf[IntAnnotation], "test1", Constants.Int)
+ check(classOf[LongAnnotation], "test1", Constants.Long)
+ check(classOf[FloatAnnotation], "test1", Constants.Float)
+ check(classOf[DoubleAnnotation], "test1", Constants.Double)
+ check(classOf[StringAnnotation], "test1", Constants.String)
+
+ check(classOf[BooleanAnnotation], "test2", Constants.InvertedBoolean)
+ check(classOf[ByteAnnotation], "test2", Constants.NegativeByte)
+ // no negative char possible
+ check(classOf[ShortAnnotation], "test2", Constants.NegativeShort)
+ check(classOf[IntAnnotation], "test2", Constants.NegativeInt)
+ check(classOf[LongAnnotation], "test2", Constants.NegativeLong)
+ check(classOf[FloatAnnotation], "test2", Constants.NegativeFloat)
+ check(classOf[DoubleAnnotation], "test2", Constants.NegativeDouble)
+ check(classOf[StringAnnotation], "test2", Constants.NegativeString)
+
+ check(classOf[BooleanAnnotation], "test3", Constants.BooleanFalse)
+ check(classOf[ByteAnnotation], "test3", Constants.LiteralCharAsByte)
+ check(classOf[CharAnnotation], "test3", Constants.LiteralChar)
+ check(classOf[ShortAnnotation], "test3", Constants.LiteralCharAsShort)
+ check(classOf[IntAnnotation], "test3", Constants.LiteralCharAsInt)
+ check(classOf[LongAnnotation], "test3", Constants.LiteralCharAsLong)
+
+ check(classOf[LongAnnotation], "test4", Constants.LiteralIntAsLong)
+}