summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-12-15 12:10:25 -0800
committerGitHub <noreply@github.com>2016-12-15 12:10:25 -0800
commitbf54f1ff8e022043bbef31b19b574c760f5fe73e (patch)
treeb808a6ac19b792e5475ef74bdab00c302246667c /src
parente231c09c4149a05591c639666949f987a7010298 (diff)
parent9b27a08f78b09f208792835de4673e20e4121284 (diff)
downloadscala-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')
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala61
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala2
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
3 files changed, 63 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,
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")