@@ -166,7 +166,10 @@ class ClassfileParser(
166
166
for (i <- 0 until in.nextChar) parseMember(method = false )
167
167
for (i <- 0 until in.nextChar) parseMember(method = true )
168
168
classInfo = parseAttributes(classRoot.symbol, classInfo)
169
- if (isAnnotation) addAnnotationConstructor(classInfo)
169
+ if (isAnnotation)
170
+ // classInfo must be a TempClassInfoType and not a TempPolyType,
171
+ // because Java annotations cannot have type parameters.
172
+ addAnnotationConstructor(classInfo.asInstanceOf [TempClassInfoType ])
170
173
171
174
classRoot.registerCompanion(moduleRoot.symbol)
172
175
moduleRoot.registerCompanion(classRoot.symbol)
@@ -632,67 +635,23 @@ class ClassfileParser(
632
635
cook.apply(newType)
633
636
}
634
637
635
- /** Add synthetic constructor(s) and potentially also default getters which
636
- * reflects the fields of the annotation with given `classInfo`.
637
- * Annotations in Scala are assumed to get all their arguments as constructor
638
+ /** Annotations in Scala are assumed to get all their arguments as constructor
638
639
* parameters. For Java annotations we need to fake it by making up the constructor.
639
- * Note that default getters have type Nothing. That's OK because we need
640
- * them only to signal that the corresponding parameter is optional.
641
640
*/
642
- def addAnnotationConstructor (classInfo : Type , tparams : List [TypeSymbol ] = Nil )(implicit ctx : Context ): Unit = {
643
- def addDefaultGetter (attr : Symbol , n : Int ) =
644
- ctx.newSymbol(
645
- owner = moduleRoot.symbol,
646
- name = DefaultGetterName (nme.CONSTRUCTOR , n),
647
- flags = attr.flags & Flags .AccessFlags ,
648
- info = defn.NothingType ).entered
649
-
650
- classInfo match {
651
- case classInfo @ TempPolyType (tparams, restpe) if tparams.isEmpty =>
652
- addAnnotationConstructor(restpe, tparams)
653
- case classInfo : TempClassInfoType =>
654
- val attrs = classInfo.decls.toList.filter(_.isTerm)
655
- val targs = tparams.map(_.typeRef)
656
- val paramNames = attrs.map(_.name.asTermName)
657
- val paramTypes = attrs.map(_.info.resultType)
658
-
659
- def addConstr (ptypes : List [Type ]) = {
660
- val mtype = MethodType (paramNames, ptypes, classRoot.typeRef.appliedTo(targs))
661
- val constrType = if (tparams.isEmpty) mtype else TempPolyType (tparams, mtype)
662
- val constr = ctx.newSymbol(
663
- owner = classRoot.symbol,
664
- name = nme.CONSTRUCTOR ,
665
- flags = Flags .Synthetic | Flags .JavaDefined | Flags .Method ,
666
- info = constrType
667
- ).entered
668
- for ((attr, i) <- attrs.zipWithIndex)
669
- if (attr.hasAnnotation(defn.AnnotationDefaultAnnot )) {
670
- constr.setFlag(Flags .DefaultParameterized )
671
- addDefaultGetter(attr, i)
672
- }
673
- }
674
-
675
- addConstr(paramTypes)
676
-
677
- // The code below added an extra constructor to annotations where the
678
- // last parameter of the constructor is an Array[X] for some X, the
679
- // array was replaced by a vararg argument. Unfortunately this breaks
680
- // inference when doing:
681
- // @Annot(Array())
682
- // The constructor is overloaded so the expected type of `Array()` is
683
- // WildcardType, and the type parameter of the Array apply method gets
684
- // instantiated to `Nothing` instead of `X`.
685
- // I'm leaving this commented out in case we improve inference to make this work.
686
- // Note that if this is reenabled then JavaParser will also need to be modified
687
- // to add the extra constructor (this was not implemented before).
688
- /*
689
- if (paramTypes.nonEmpty)
690
- paramTypes.last match {
691
- case defn.ArrayOf(elemtp) =>
692
- addConstr(paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp))
693
- case _ =>
694
- }
695
- */
641
+ def addAnnotationConstructor (classInfo : TempClassInfoType )(implicit ctx : Context ): Unit =
642
+ ctx.newSymbol(
643
+ owner = classRoot.symbol,
644
+ name = nme.CONSTRUCTOR ,
645
+ flags = Flags .Synthetic | Flags .JavaDefined | Flags .Method ,
646
+ info = new AnnotConstructorCompleter (classInfo)
647
+ ).entered
648
+
649
+ class AnnotConstructorCompleter (classInfo : TempClassInfoType ) extends LazyType {
650
+ def complete (denot : SymDenotation )(implicit ctx : Context ): Unit = {
651
+ val attrs = classInfo.decls.toList.filter(sym => sym.isTerm && sym != denot.symbol)
652
+ val paramNames = attrs.map(_.name.asTermName)
653
+ val paramTypes = attrs.map(_.info.resultType)
654
+ denot.info = MethodType (paramNames, paramTypes, classRoot.typeRef)
696
655
}
697
656
}
698
657
0 commit comments