diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala index 8322c75e5e2d..c9514eeb7cd4 100644 --- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala @@ -359,19 +359,6 @@ object JavaParsers { * but instead we skip entire annotation silently. */ def annotation(): Option[Tree] = { - object LiteralT: - def unapply(token: Token) = Option(token match { - case TRUE => true - case FALSE => false - case CHARLIT => in.name(0) - case INTLIT => in.intVal(false).toInt - case LONGLIT => in.intVal(false) - case FLOATLIT => in.floatVal(false).toFloat - case DOUBLELIT => in.floatVal(false) - case STRINGLIT => in.name.toString - case _ => null - }).map(Constant(_)) - def classOrId(): Tree = val id = qualId() if in.lookaheadToken == CLASS then @@ -398,17 +385,17 @@ object JavaParsers { } def argValue(): Option[Tree] = - val tree = in.token match { - case LiteralT(c) => - val tree = atSpan(in.offset)(Literal(c)) - in.nextToken() - Some(tree) - case AT => - in.nextToken() - annotation() - case IDENTIFIER => Some(classOrId()) - case LBRACE => array() - case _ => None + val tree = tryConstant match { + case Some(c) => + Some(atSpan(in.offset)(Literal(c))) + case _ => in.token match { + case AT => + in.nextToken() + annotation() + case IDENTIFIER => Some(classOrId()) + case LBRACE => array() + case _ => None + } } if in.token == COMMA || in.token == RBRACE || in.token == RPAREN then tree @@ -716,11 +703,7 @@ object JavaParsers { in.nextToken() // EQUALS if (mods.is(Flags.JavaStatic) && mods.is(Flags.Final)) { - val neg = in.token match { - case MINUS | BANG => in.nextToken(); true - case _ => false - } - tryLiteral(neg).map(forConst).getOrElse(tpt1) + tryConstant.map(forConst).getOrElse(tpt1) } else tpt1 } @@ -976,7 +959,11 @@ object JavaParsers { case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree) } - def tryLiteral(negate: Boolean = false): Option[Constant] = { + def tryConstant: Option[Constant] = { + val negate = in.token match { + case MINUS | BANG => in.nextToken(); true + case _ => false + } val l = in.token match { case TRUE => !negate case FALSE => negate diff --git a/tests/run-macros/annot-arg-value-in-java.check b/tests/run-macros/annot-arg-value-in-java.check new file mode 100644 index 000000000000..d49aaf91ae6a --- /dev/null +++ b/tests/run-macros/annot-arg-value-in-java.check @@ -0,0 +1,11 @@ +J: +new java.lang.SuppressWarnings(value = "a") +new java.lang.SuppressWarnings(value = "b") +new java.lang.SuppressWarnings(value = _root_.scala.Array.apply[java.lang.String]("c", "d")(scala.reflect.ClassTag.apply[java.lang.String](classOf[java.lang.String]))) +JOtherTypes: +new Annot(value = 1, _, _) +new Annot(value = -2, _, _) +new Annot(_, m = false, _) +new Annot(_, m = true, _) +new Annot(_, _, n = 1.1) +new Annot(_, _, n = -2.1) \ No newline at end of file diff --git a/tests/run-macros/annot-arg-value-in-java/AnnoMacro.scala b/tests/run-macros/annot-arg-value-in-java/AnnoMacro.scala new file mode 100644 index 000000000000..7528653ef903 --- /dev/null +++ b/tests/run-macros/annot-arg-value-in-java/AnnoMacro.scala @@ -0,0 +1,11 @@ +import scala.quoted.* + +inline def showAnnots(inline c: String): Unit = ${ showAnnotsImpl('c) } + +def showAnnotsImpl(c: Expr[String])(using Quotes): Expr[Unit] = + import quotes.reflect.* + val al = Expr(Symbol.requiredClass(c.valueOrError).declaredMethods.flatMap(_.annotations.map(_.show))) + '{ + println($c + ":") + $al.foreach(println) + } \ No newline at end of file diff --git a/tests/run-macros/annot-arg-value-in-java/Annot.java b/tests/run-macros/annot-arg-value-in-java/Annot.java new file mode 100644 index 000000000000..2764bf8c8324 --- /dev/null +++ b/tests/run-macros/annot-arg-value-in-java/Annot.java @@ -0,0 +1,5 @@ +public @interface Annot { + int value() default 0; + boolean m() default false; + double n() default 0; +} \ No newline at end of file diff --git a/tests/run-macros/annot-arg-value-in-java/J.java b/tests/run-macros/annot-arg-value-in-java/J.java new file mode 100644 index 000000000000..d1234e080258 --- /dev/null +++ b/tests/run-macros/annot-arg-value-in-java/J.java @@ -0,0 +1,23 @@ +public class J { + @SuppressWarnings(value = "a") + public void f1() {} + @SuppressWarnings("b") + public void f2() {} + @SuppressWarnings({"c", "d"}) + public void f3() {} +} + +class JOtherTypes { + @Annot(1) + public void f1() {} + @Annot(-2) + public void f2() {} + @Annot(m = false) + public void f3() {} + @Annot(m = true) + public void f4() {} + @Annot(n = 1.1) + public void f5() {} + @Annot(n = -2.1) + public void f6() {} +} \ No newline at end of file diff --git a/tests/run-macros/annot-arg-value-in-java/S.scala b/tests/run-macros/annot-arg-value-in-java/S.scala new file mode 100644 index 000000000000..8b4369df97b1 --- /dev/null +++ b/tests/run-macros/annot-arg-value-in-java/S.scala @@ -0,0 +1,5 @@ +// Display annotation arguments in Java + +@main def Test = + showAnnots("J") + showAnnots("JOtherTypes")