Skip to content

Commit 8a6c719

Browse files
committed
Add the right constructor to Java annotations
1 parent e0b290c commit 8a6c719

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(27, "<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(28, "<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
@@ -1804,7 +1804,7 @@ object Types {
18041804
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this
18051805
else copy(paramNames, paramBounds, restpe)
18061806

1807-
def copy(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
1807+
def copy(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, restpe: Type)(implicit ctx: Context) =
18081808
PolyType(paramNames)(
18091809
x => paramBounds mapConserve (_.subst(this, x).bounds),
18101810
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
@@ -127,6 +127,7 @@ class ClassfileParser(
127127
for (i <- 0 until in.nextChar) parseMember(method = false)
128128
for (i <- 0 until in.nextChar) parseMember(method = true)
129129
classInfo = parseAttributes(classRoot.symbol, classInfo)
130+
if (isAnnotation) addAnnotationConstructor(classInfo)
130131
setClassInfo(classRoot, classInfo)
131132
setClassInfo(moduleRoot, staticInfo)
132133
}
@@ -539,6 +540,45 @@ class ClassfileParser(
539540
newType
540541
}
541542

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

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)