diff options
author | Dmitry Petrashko <dark@d-d.me> | 2014-12-21 22:38:21 +0200 |
---|---|---|
committer | Dmitry Petrashko <dark@d-d.me> | 2014-12-21 22:38:21 +0200 |
commit | 2833b0107cdd95bdceb4d8aa968e0f66a6eb24e3 (patch) | |
tree | 9c2cb6eae1e2f7df4a49c58b342c8ac708afe478 | |
parent | 13ec91b955b5c10da750b26e10f793ea44a72945 (diff) | |
parent | 823930308048a26c07bb54ac77923ba8e24e68a4 (diff) | |
download | dotty-2833b0107cdd95bdceb4d8aa968e0f66a6eb24e3.tar.gz dotty-2833b0107cdd95bdceb4d8aa968e0f66a6eb24e3.tar.bz2 dotty-2833b0107cdd95bdceb4d8aa968e0f66a6eb24e3.zip |
Merge pull request #315 from dotty-staging/fix/annot-vararg-constr
Allow for varargs passed to Java annotation constructors.
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 39 | ||||
-rw-r--r-- | tests/pending/pos/annot.scala | 5 | ||||
-rw-r--r-- | tests/pos/annot.scala | 6 |
3 files changed, 30 insertions, 20 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 _ => + } + } } diff --git a/tests/pending/pos/annot.scala b/tests/pending/pos/annot.scala deleted file mode 100644 index 8e21803b4..000000000 --- a/tests/pending/pos/annot.scala +++ /dev/null @@ -1,5 +0,0 @@ -class Test { - - @SuppressWarnings("hi") def foo() = ??? - -} diff --git a/tests/pos/annot.scala b/tests/pos/annot.scala index ab80aba27..c3a17ff1d 100644 --- a/tests/pos/annot.scala +++ b/tests/pos/annot.scala @@ -2,11 +2,11 @@ import java.beans.Transient class Test { - @SuppressWarnings(Array("hi")) def foo() = ??? // evalutation of annotation on type cannot be deffered as requires implicit resolution(only generic Array$.apply applies here) + @SuppressWarnings(Array("hi")) def foo() = ??? // evalutation of annotation on type cannot be deferred as requires implicit resolution(only generic Array$.apply applies here) - @SuppressWarnings(Array("hi", "foo")) def foo2() = ??? //can be deffered as there is a non-generic method + @SuppressWarnings(Array("hi", "foo")) def foo2() = ??? //can be deferred as there is a non-generic method -// @SuppressWarnings("hi") def foo3() = ??? // can be written in java and is serialized this way in bytecode. doesn't typecheck + @SuppressWarnings("hi") def foo3() = ??? // can be written in java and is serialized this way in bytecode. doesn't typecheck @Transient(false) def bar = ??? |