Skip to content

Commit e837e2a

Browse files
oderskyDarkDimius
authored andcommitted
Add the right constructor to Java annotations
1 parent 9f508df commit e837e2a

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

src/dotty/tools/dotc/core/Flags.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ object Flags {
318318
/** An unpickled Scala 2.x class */
319319
final val Scala2x = typeFlag(26, "<scala-2.x>")
320320

321-
/** A method that has default params */ // TODO: drop
321+
/** A method that has default params */
322322
final val DefaultParameterized = termFlag(27, "<defaultparam>")
323323

324324
/** Symbol is initialized to the default value, e.g. var x: T = _ */

src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1992,7 +1992,7 @@ object Types {
19921992
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this
19931993
else copy(paramNames, paramBounds, restpe)
19941994

1995-
def copy(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
1995+
def copy(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, restpe: Type)(implicit ctx: Context) =
19961996
PolyType(paramNames)(
19971997
x => paramBounds mapConserve (_.subst(this, x).bounds),
19981998
x => restpe.subst(this, x))

src/dotty/tools/dotc/core/pickling/ClassfileParser.scala

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class ClassfileParser(
128128
for (i <- 0 until in.nextChar) parseMember(method = false)
129129
for (i <- 0 until in.nextChar) parseMember(method = true)
130130
classInfo = parseAttributes(classRoot.symbol, classInfo)
131+
if (isAnnotation) addAnnotationConstructor(classInfo)
131132
setClassInfo(classRoot, classInfo)
132133
setClassInfo(moduleRoot, staticInfo)
133134
}
@@ -546,6 +547,45 @@ class ClassfileParser(
546547
newType
547548
}
548549

550+
/** Add a synthetic constructor and potentially also default getters which
551+
* reflects the fields of the annotation with given `classInfo`.
552+
* Annotations in Scala are assumed to get all their arguments as constructor
553+
* parameters. For Java annotations we need to fake it by making up the constructor.
554+
* Note that default getters have type Nothing. That's OK because we need
555+
* them only to signal that the corresponding parameter is optional.
556+
*/
557+
def addAnnotationConstructor(classInfo: Type, tparams: List[Symbol] = Nil)(implicit ctx: Context): Unit = {
558+
def addDefaultGetter(attr: Symbol, n: Int) =
559+
ctx.newSymbol(
560+
owner = moduleRoot.symbol,
561+
name = nme.CONSTRUCTOR.defaultGetterName(n),
562+
flags = attr.flags & Flags.AccessFlags,
563+
info = defn.NothingType).entered
564+
565+
classInfo match {
566+
case classInfo @ TempPolyType(tparams, restpe) if tparams.isEmpty =>
567+
addAnnotationConstructor(restpe, tparams)
568+
case classInfo: TempClassInfoType =>
569+
val attrs = classInfo.decls.toList.filter(_.isTerm)
570+
val targs = tparams.map(_.typeRef)
571+
val methType = MethodType(
572+
attrs.map(_.name.asTermName),
573+
attrs.map(_.info.resultType),
574+
classRoot.typeRef.appliedTo(targs))
575+
val constr = ctx.newSymbol(
576+
owner = classRoot.symbol,
577+
name = nme.CONSTRUCTOR,
578+
flags = Flags.Synthetic,
579+
info = if (tparams.isEmpty) methType else TempPolyType(tparams, methType)
580+
).entered
581+
for ((attr, i) <- attrs.zipWithIndex)
582+
if (attr.hasAnnotation(defn.AnnotationDefaultAnnot)) {
583+
constr.setFlag(Flags.HasDefaultParams)
584+
addDefaultGetter(attr, i)
585+
}
586+
}
587+
}
588+
549589
/** Enter own inner classes in the right scope. It needs the scopes to be set up,
550590
* and implicitly current class' superclasses.
551591
*/

tests/pos/annot.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import java.beans.Transient
2+
3+
class Test {
4+
5+
@SuppressWarnings(Array("hi")) def foo() = ???
6+
7+
@Transient(false) def bar = ???
8+
9+
@Transient() def baz = ???
10+
}
11+

0 commit comments

Comments
 (0)