diff options
author | Johannes Rudolph <johannes.rudolph@gmail.com> | 2016-03-08 23:02:23 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2016-10-28 16:56:57 +0200 |
commit | 81d2c6185e6c10defcf1f6a25f69e8b2ed025d86 (patch) | |
tree | d1a69af725a9bd7944e3edd159bebf89ab4d7954 /src/compiler/scala/tools/nsc/javac/JavaParsers.scala | |
parent | b9a16c4a812a0bde8bd23fb90c0ec5d9439e0e14 (diff) | |
download | scala-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.scala | 58 |
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) } } |