summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
diff options
context:
space:
mode:
authorJohannes Rudolph <johannes.rudolph@gmail.com>2016-03-08 23:02:23 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2016-10-28 16:56:57 +0200
commit81d2c6185e6c10defcf1f6a25f69e8b2ed025d86 (patch)
treed1a69af725a9bd7944e3edd159bebf89ab4d7954 /src/compiler/scala/tools/nsc/javac/JavaParsers.scala
parentb9a16c4a812a0bde8bd23fb90c0ec5d9439e0e14 (diff)
downloadscala-81d2c6185e6c10defcf1f6a25f69e8b2ed025d86.tar.gz
scala-81d2c6185e6c10defcf1f6a25f69e8b2ed025d86.tar.bz2
scala-81d2c6185e6c10defcf1f6a25f69e8b2ed025d86.zip
SI-3236 constant types for literal final static java fields
Since we don't parse Java expressions, fields of Java classes coming from source files never have constant types. This prevents using static java fields in annotation arguments in mixed compilation This PR assigns constant types to final static java fields if the initializer is a simple literal.
Diffstat (limited to 'src/compiler/scala/tools/nsc/javac/JavaParsers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala58
1 files changed, 56 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)
}
}