Skip to content

Commit 202a377

Browse files
oderskyDarkDimius
authored andcommitted
Add the right constructor to Java annotations
1 parent 5f05c4b commit 202a377

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
@@ -1979,7 +1979,7 @@ object Types {
19791979
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this
19801980
else copy(paramNames, paramBounds, restpe)
19811981

1982-
def copy(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
1982+
def copy(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, restpe: Type)(implicit ctx: Context) =
19831983
PolyType(paramNames)(
19841984
x => paramBounds mapConserve (_.subst(this, x).bounds),
19851985
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
}
@@ -544,6 +545,45 @@ class ClassfileParser(
544545
newType
545546
}
546547

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

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)