@@ -166,7 +166,10 @@ class ClassfileParser(
166166 for (i <- 0 until in.nextChar) parseMember(method = false )
167167 for (i <- 0 until in.nextChar) parseMember(method = true )
168168 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 ])
170173
171174 classRoot.registerCompanion(moduleRoot.symbol)
172175 moduleRoot.registerCompanion(classRoot.symbol)
@@ -632,67 +635,23 @@ class ClassfileParser(
632635 cook.apply(newType)
633636 }
634637
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
638639 * 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.
641640 */
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)
696655 }
697656 }
698657
0 commit comments