Skip to content

Commit 7574b91

Browse files
committed
Add migration rewrite for non-named arguments in Java annotations
1 parent f1adc55 commit 7574b91

File tree

7 files changed

+43
-6
lines changed

7 files changed

+43
-6
lines changed

compiler/src/dotty/tools/dotc/config/MigrationVersion.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ object MigrationVersion:
4343
val WithOperator = MigrationVersion(`3.4`, future)
4444
val FunctionUnderscore = MigrationVersion(`3.4`, future)
4545

46+
val NonNamedArgumentInJavaAnnotation = MigrationVersion(`3.6`, `3.6`)
47+
4648
val ImportWildcard = MigrationVersion(future, future)
4749
val ImportRename = MigrationVersion(future, future)
4850
val ParameterEnclosedByParenthesis = MigrationVersion(future, future)

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import dotty.tools.dotc.util.Spans.Span
3535
import dotty.tools.dotc.util.SourcePosition
3636
import scala.jdk.CollectionConverters.*
3737
import dotty.tools.dotc.util.SourceFile
38+
import dotty.tools.dotc.config.SourceVersion
3839
import DidYouMean.*
3940

4041
/** Messages
@@ -3291,13 +3292,14 @@ object UnusedSymbol {
32913292

32923293
class NonNamedArgumentInJavaAnnotation(using Context) extends SyntaxMsg(NonNamedArgumentInJavaAnnotationID):
32933294

3294-
override protected def msg(using Context): String =
3295+
override protected def msg(using Context): String =
32953296
"Named arguments are required for Java defined annotations"
3297+
+ Message.rewriteNotice("This", version = SourceVersion.`3.6-migration`)
32963298

3297-
override protected def explain(using Context): String =
3299+
override protected def explain(using Context): String =
32983300
i"""Starting from Scala 3.6.0, named arguments are required for Java defined annotations.
3299-
|Java defined annotations don't have an exact constructor representation
3300-
|and we previously relied on the order of the fields to create one.
3301+
|Java defined annotations don't have an exact constructor representation
3302+
|and we previously relied on the order of the fields to create one.
33013303
|One possible issue with this representation is the reordering of the fields.
33023304
|Lets take the following example:
33033305
|

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,14 +891,26 @@ object Checking {
891891
def annotationHasValueField: Boolean =
892892
sym.info.decls.exists(_.name == nme.value)
893893

894+
lazy val annotationFieldNamesByIdx: Map[Int, TermName] =
895+
sym.info.decls.filter: decl =>
896+
decl.is(Method) && decl.name != nme.CONSTRUCTOR
897+
.map(_.name.toTermName)
898+
.zipWithIndex
899+
.map(_.swap)
900+
.toMap
901+
894902
annot match
895903
case untpd.Apply(fun, List(param)) if !param.isInstanceOf[untpd.NamedArg] && annotationHasValueField =>
896904
untpd.cpy.Apply(annot)(fun, List(untpd.cpy.NamedArg(param)(nme.value, param)))
897905
case untpd.Apply(_, params) =>
898906
for
899-
param <- params
907+
(param, paramIdx) <- params.zipWithIndex
900908
if !param.isInstanceOf[untpd.NamedArg]
901-
do report.error(NonNamedArgumentInJavaAnnotation(), param)
909+
do
910+
report.errorOrMigrationWarning(NonNamedArgumentInJavaAnnotation(), param, MigrationVersion.NonNamedArgumentInJavaAnnotation)
911+
if MigrationVersion.NonNamedArgumentInJavaAnnotation.needsPatch then
912+
annotationFieldNamesByIdx.get(paramIdx).foreach: paramName =>
913+
patch(param.span, untpd.cpy.NamedArg(param)(paramName, param).show)
902914
annot
903915
case _ => annot
904916
end checkNamedArgumentForJavaAnnotation

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class CompilationTests {
7676
compileFile("tests/rewrites/i17187.scala", unindentOptions.and("-rewrite")),
7777
compileFile("tests/rewrites/i17399.scala", unindentOptions.and("-rewrite")),
7878
compileFile("tests/rewrites/i20002.scala", defaultOptions.and("-indent", "-rewrite")),
79+
compileDir("tests/rewrites/annotation-named-pararamters", defaultOptions.and("-rewrite", "-source:3.6-migration")),
7980
).checkRewrites()
8081
}
8182

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import java.util.concurrent.TimeUnit;
2+
3+
public @interface MyAnnotation {
4+
public TimeUnit D() default TimeUnit.DAYS;
5+
TimeUnit C() default TimeUnit.DAYS;
6+
String A() default "";
7+
public String B() default "";
8+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import java.util.concurrent.TimeUnit
2+
@MyAnnotation() class Test1
3+
@MyAnnotation(D = TimeUnit.DAYS) class Test2
4+
@MyAnnotation(D = TimeUnit.DAYS, C = TimeUnit.DAYS) class Test3
5+
@MyAnnotation(D = TimeUnit.DAYS, C = TimeUnit.DAYS, A = "foo") class Test4
6+
@MyAnnotation(D = TimeUnit.DAYS, C = TimeUnit.DAYS, A = "foo", B = "bar") class Test5
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import java.util.concurrent.TimeUnit
2+
@MyAnnotation() class Test1
3+
@MyAnnotation(TimeUnit.DAYS) class Test2
4+
@MyAnnotation(TimeUnit.DAYS, TimeUnit.DAYS) class Test3
5+
@MyAnnotation(TimeUnit.DAYS, TimeUnit.DAYS, "foo") class Test4
6+
@MyAnnotation(TimeUnit.DAYS, TimeUnit.DAYS, "foo", "bar") class Test5

0 commit comments

Comments
 (0)