diff options
author | Adriaan Moors <adriaan@lightbend.com> | 2016-12-15 12:10:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-15 12:10:25 -0800 |
commit | bf54f1ff8e022043bbef31b19b574c760f5fe73e (patch) | |
tree | b808a6ac19b792e5475ef74bdab00c302246667c /src/compiler/scala | |
parent | e231c09c4149a05591c639666949f987a7010298 (diff) | |
parent | 9b27a08f78b09f208792835de4673e20e4121284 (diff) | |
download | scala-bf54f1ff8e022043bbef31b19b574c760f5fe73e.tar.gz scala-bf54f1ff8e022043bbef31b19b574c760f5fe73e.tar.bz2 scala-bf54f1ff8e022043bbef31b19b574c760f5fe73e.zip |
Merge pull request #5487 from lrytz/java-constants
SI-3236 constant types for literal final static java fields
Diffstat (limited to 'src/compiler/scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/javac/JavaParsers.scala | 61 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/javac/JavaScanners.scala | 2 |
2 files changed, 61 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..876247510b 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -567,10 +567,48 @@ 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 = { + def constantTpe(const: Constant): Tree = TypeTree(ConstantType(const)) + + def forConst(const: Constant): Tree = { + if (in.token != SEMI) tpt1 + else { + def isStringTyped = tpt1 match { + case Ident(TypeName("String")) => true + case _ => false + } + if (const.tag == StringTag && isStringTyped) constantTpe(const) + else if (tpt1.tpe != null && (const.tag == BooleanTag || const.isNumeric)) { + // for example, literal 'a' is ok for float. 127 is ok for byte, but 128 is not. + val converted = const.convertTo(tpt1.tpe) + if (converted == null) tpt1 + else constantTpe(converted) + } else tpt1 + } + } + + in.nextToken() // EQUALS + if (mods.hasFlag(Flags.STATIC) && mods.isFinal) { + val neg = in.token match { + case MINUS | BANG => in.nextToken(); true + case _ => false + } + tryLiteral(neg).map(forConst).getOrElse(tpt1) + } 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) } } @@ -843,6 +881,25 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree) } + def tryLiteral(negate: Boolean = false): Option[Constant] = { + val l = in.token match { + case TRUE => !negate + case FALSE => negate + case CHARLIT => in.name.charAt(0) + case INTLIT => in.intVal(negate).toInt + case LONGLIT => in.intVal(negate) + case FLOATLIT => in.floatVal(negate).toFloat + case DOUBLELIT => in.floatVal(negate) + case STRINGLIT => in.name.toString + case _ => null + } + if (l == null) None + else { + in.nextToken() + Some(Constant(l)) + } + } + /** CompilationUnit ::= [package QualId semi] TopStatSeq */ def compilationUnit(): Tree = { 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, |