aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-12-19 22:58:13 +0100
committerMartin Odersky <odersky@gmail.com>2014-12-19 22:58:13 +0100
commitb3af6169d06796f3ac57d7082bc9eaeb0db34155 (patch)
treecf39f8eec2e1520331aff518c72a4abdf48a4974 /src
parent13ec91b955b5c10da750b26e10f793ea44a72945 (diff)
downloaddotty-b3af6169d06796f3ac57d7082bc9eaeb0db34155.tar.gz
dotty-b3af6169d06796f3ac57d7082bc9eaeb0db34155.tar.bz2
dotty-b3af6169d06796f3ac57d7082bc9eaeb0db34155.zip
Allow for varargs passed to Java annotation constructors.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala39
1 files changed, 27 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index cc3d3eb7f..24b2f4257 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -553,12 +553,15 @@ class ClassfileParser(
newType
}
- /** Add a synthetic constructor and potentially also default getters which
+ /** Add synthetic constructor(s) and potentially also default getters which
* reflects the fields of the annotation with given `classInfo`.
* Annotations in Scala are assumed to get all their arguments as constructor
* parameters. For Java annotations we need to fake it by making up the constructor.
* Note that default getters have type Nothing. That's OK because we need
* them only to signal that the corresponding parameter is optional.
+ * If the constructor takes as last parameter an array, it can also accept
+ * a vararg argument. We solve this by creating two constructors, one with
+ * an array, the other with a repeated parameter.
*/
def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = {
def addDefaultGetter(attr: Symbol, n: Int) =
@@ -574,21 +577,33 @@ class ClassfileParser(
case classInfo: TempClassInfoType =>
val attrs = classInfo.decls.toList.filter(_.isTerm)
val targs = tparams.map(_.typeRef)
- val methType = MethodType(
- attrs.map(_.name.asTermName),
- attrs.map(_.info.resultType),
- classRoot.typeRef.appliedTo(targs))
- val constr = ctx.newSymbol(
+ val paramNames = attrs.map(_.name.asTermName)
+ val paramTypes = attrs.map(_.info.resultType)
+
+ def addConstr(ptypes: List[Type]) = {
+ val mtype = MethodType(paramNames, ptypes, classRoot.typeRef.appliedTo(targs))
+ val constrType = if (tparams.isEmpty) mtype else TempPolyType(tparams, mtype)
+ val constr = ctx.newSymbol(
owner = classRoot.symbol,
name = nme.CONSTRUCTOR,
flags = Flags.Synthetic,
- info = if (tparams.isEmpty) methType else TempPolyType(tparams, methType)
+ info = constrType
).entered
- for ((attr, i) <- attrs.zipWithIndex)
- if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) {
- constr.setFlag(Flags.HasDefaultParams)
- addDefaultGetter(attr, i)
- }
+ for ((attr, i) <- attrs.zipWithIndex)
+ if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) {
+ constr.setFlag(Flags.HasDefaultParams)
+ addDefaultGetter(attr, i)
+ }
+ }
+
+ addConstr(paramTypes)
+ if (paramTypes.nonEmpty)
+ paramTypes.last match {
+ case defn.ArrayType(elemtp) =>
+ addConstr(paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp))
+ case _ =>
+ }
+
}
}