From 1e1f260577d8522a5c99052cea5b3ebe64a12830 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 10 Oct 2014 16:25:26 +0200 Subject: Add the right constructor to Java annotations --- .../tools/dotc/core/pickling/ClassfileParser.scala | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src/dotty/tools/dotc/core/pickling/ClassfileParser.scala') diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 8dd9314ee..fb5a6309b 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -128,6 +128,7 @@ class ClassfileParser( for (i <- 0 until in.nextChar) parseMember(method = false) for (i <- 0 until in.nextChar) parseMember(method = true) classInfo = parseAttributes(classRoot.symbol, classInfo) + if (isAnnotation) addAnnotationConstructor(classInfo) setClassInfo(classRoot, classInfo) setClassInfo(moduleRoot, staticInfo) } @@ -551,6 +552,45 @@ class ClassfileParser( newType } + /** Add a synthetic constructor 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. + */ + def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = { + def addDefaultGetter(attr: Symbol, n: Int) = + ctx.newSymbol( + owner = moduleRoot.symbol, + name = nme.CONSTRUCTOR.defaultGetterName(n), + flags = attr.flags & Flags.AccessFlags, + info = defn.NothingType).entered + + classInfo match { + case classInfo @ TempPolyType(tparams, restpe) if tparams.isEmpty => + addAnnotationConstructor(restpe, tparams) + 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( + owner = classRoot.symbol, + name = nme.CONSTRUCTOR, + flags = Flags.Synthetic, + info = if (tparams.isEmpty) methType else TempPolyType(tparams, methType) + ).entered + for ((attr, i) <- attrs.zipWithIndex) + if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) { + constr.setFlag(Flags.HasDefaultParams) + addDefaultGetter(attr, i) + } + } + } + /** Enter own inner classes in the right scope. It needs the scopes to be set up, * and implicitly current class' superclasses. */ -- cgit v1.2.3