Skip to content

Commit 2833b01

Browse files
committed
Merge pull request #315 from dotty-staging/fix/annot-vararg-constr
Allow for varargs passed to Java annotation constructors.
2 parents 13ec91b + 8239303 commit 2833b01

File tree

3 files changed

+30
-20
lines changed

3 files changed

+30
-20
lines changed

src/dotty/tools/dotc/core/pickling/ClassfileParser.scala

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -553,12 +553,15 @@ class ClassfileParser(
553553
newType
554554
}
555555

556-
/** Add a synthetic constructor and potentially also default getters which
556+
/** Add synthetic constructor(s) and potentially also default getters which
557557
* reflects the fields of the annotation with given `classInfo`.
558558
* Annotations in Scala are assumed to get all their arguments as constructor
559559
* parameters. For Java annotations we need to fake it by making up the constructor.
560560
* Note that default getters have type Nothing. That's OK because we need
561561
* them only to signal that the corresponding parameter is optional.
562+
* If the constructor takes as last parameter an array, it can also accept
563+
* a vararg argument. We solve this by creating two constructors, one with
564+
* an array, the other with a repeated parameter.
562565
*/
563566
def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = {
564567
def addDefaultGetter(attr: Symbol, n: Int) =
@@ -574,21 +577,33 @@ class ClassfileParser(
574577
case classInfo: TempClassInfoType =>
575578
val attrs = classInfo.decls.toList.filter(_.isTerm)
576579
val targs = tparams.map(_.typeRef)
577-
val methType = MethodType(
578-
attrs.map(_.name.asTermName),
579-
attrs.map(_.info.resultType),
580-
classRoot.typeRef.appliedTo(targs))
581-
val constr = ctx.newSymbol(
580+
val paramNames = attrs.map(_.name.asTermName)
581+
val paramTypes = attrs.map(_.info.resultType)
582+
583+
def addConstr(ptypes: List[Type]) = {
584+
val mtype = MethodType(paramNames, ptypes, classRoot.typeRef.appliedTo(targs))
585+
val constrType = if (tparams.isEmpty) mtype else TempPolyType(tparams, mtype)
586+
val constr = ctx.newSymbol(
582587
owner = classRoot.symbol,
583588
name = nme.CONSTRUCTOR,
584589
flags = Flags.Synthetic,
585-
info = if (tparams.isEmpty) methType else TempPolyType(tparams, methType)
590+
info = constrType
586591
).entered
587-
for ((attr, i) <- attrs.zipWithIndex)
588-
if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) {
589-
constr.setFlag(Flags.HasDefaultParams)
590-
addDefaultGetter(attr, i)
591-
}
592+
for ((attr, i) <- attrs.zipWithIndex)
593+
if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) {
594+
constr.setFlag(Flags.HasDefaultParams)
595+
addDefaultGetter(attr, i)
596+
}
597+
}
598+
599+
addConstr(paramTypes)
600+
if (paramTypes.nonEmpty)
601+
paramTypes.last match {
602+
case defn.ArrayType(elemtp) =>
603+
addConstr(paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp))
604+
case _ =>
605+
}
606+
592607
}
593608
}
594609

tests/pending/pos/annot.scala

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/pos/annot.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import java.beans.Transient
22

33
class Test {
44

5-
@SuppressWarnings(Array("hi")) def foo() = ??? // evalutation of annotation on type cannot be deffered as requires implicit resolution(only generic Array$.apply applies here)
5+
@SuppressWarnings(Array("hi")) def foo() = ??? // evalutation of annotation on type cannot be deferred as requires implicit resolution(only generic Array$.apply applies here)
66

7-
@SuppressWarnings(Array("hi", "foo")) def foo2() = ??? //can be deffered as there is a non-generic method
7+
@SuppressWarnings(Array("hi", "foo")) def foo2() = ??? //can be deferred as there is a non-generic method
88

9-
// @SuppressWarnings("hi") def foo3() = ??? // can be written in java and is serialized this way in bytecode. doesn't typecheck
9+
@SuppressWarnings("hi") def foo3() = ??? // can be written in java and is serialized this way in bytecode. doesn't typecheck
1010

1111
@Transient(false) def bar = ???
1212

0 commit comments

Comments
 (0)