Skip to content

Add the right constructor to Java annotations #184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ object Flags {
/** An unpickled Scala 2.x class */
final val Scala2x = typeFlag(27, "<scala-2.x>")

/** A method that has default params */ // TODO: drop
/** A method that has default params */
final val DefaultParameterized = termFlag(28, "<defaultparam>")

/** Symbol is initialized to the default value, e.g. var x: T = _ */
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1804,7 +1804,7 @@ object Types {
if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (restpe eq this.resultType)) this
else copy(paramNames, paramBounds, restpe)

def copy(paramNames: List[TypeName], paramBounds: List[TypeBounds], restpe: Type)(implicit ctx: Context) =
def copy(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, restpe: Type)(implicit ctx: Context) =
PolyType(paramNames)(
x => paramBounds mapConserve (_.subst(this, x).bounds),
x => restpe.subst(this, x))
Expand Down
40 changes: 40 additions & 0 deletions src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,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)
}
Expand Down Expand Up @@ -539,6 +540,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.
*/
Expand Down
11 changes: 11 additions & 0 deletions tests/pos/annot.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import java.beans.Transient

class Test {

@SuppressWarnings(Array("hi")) def foo() = ???

@Transient(false) def bar = ???

@Transient() def baz = ???
}