
scala.tools.nsc.tasty.bridge.AnnotationOps.scala Maven / Gradle / Ivy
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.tools.nsc.tasty.bridge
import scala.tools.nsc.tasty.TastyUniverse
/** Adds support for creating annotations from Trees */
trait AnnotationOps { self: TastyUniverse =>
import self.{symbolTable => u}
trait ShowKind[T] {
def showKind(annot: String, t: T)(implicit ctx: Context): String
}
object ShowKind {
implicit object ShowSymbol extends ShowKind[u.Symbol] {
def showKind(annot: String, t: u.Symbol)(implicit ctx: Context): String = s"$annot ${location(t)}"
}
implicit object ShowType extends ShowKind[u.Type] {
def showKind(annot: String, t: u.Type)(implicit ctx: Context): String =
s"type ${showType(t, wrap = false)} $annot of ${location(ctx.owner)}"
}
}
private[bridge] final def mkAnnotation[T: ShowKind](tree: Tree, annotee: T)(implicit ctx: Context): u.Annotation = {
def go(tpargs: List[Type], args: List[List[Tree]], tree: Tree): u.Annotation = tree match {
case u.Select(u.New(tpt), u.nme.CONSTRUCTOR) =>
val atp = if (tpargs.isEmpty) tpt.tpe else u.appliedType(tpt.tpe, tpargs)
if (args.lengthIs > 1) {
val soFar = s"@${atp.typeSymbol.name.toString}${args.map(_.mkString("(", ", ", ")")).mkString("")}"
u.reporter.warning(u.NoPosition,
"Implementation limitation: multiple argument lists on annotations are\n"+
"currently not supported; ignoring arguments " + args(1) + " on\n"+
s"${implicitly[ShowKind[T]].showKind(soFar, annotee)}")
}
u.AnnotationInfo(atp, args.headOption.getOrElse(Nil), Nil)
case u.TypeApply(pre, newTpArgs) if tpargs.isEmpty =>
go(newTpArgs.map(_.tpe), args, pre)
case u.Apply(pre, Nil) => // skip the empty term param list
go(tpargs, args, pre)
case u.Apply(pre, newArgs) =>
go(tpargs, newArgs :: args, pre)
case _ =>
throw new Exception(s"unexpected annotation kind from TASTy: ${u.showRaw(tree)}")
}
tree match {
case u.New(tpt) =>
// this is to handle incorrectly formatted annotations in dotty - https://github.com/scala/scala3/issues/10113
u.AnnotationInfo(tpt.tpe, Nil, Nil)
case _ =>
go(Nil, Nil, tree)
}
}
sealed abstract class DeferredAnnotation(annotSym: Symbol) {
protected def eager(annotee: Symbol)(implicit ctx: Context): u.AnnotationInfo
private[bridge] final def lzy(annotee: Symbol)(implicit ctx: Context): u.LazyAnnotationInfo = {
u.AnnotationInfo.lazily(annotSym, eager(annotee))
}
}
object DeferredAnnotation {
def fromTree(annotSym: Symbol)(tree: Symbol => Context => Tree): DeferredAnnotation = {
new DeferredAnnotation(annotSym) {
protected final def eager(annotee: Symbol)(implicit ctx: Context): u.AnnotationInfo = {
val atree = tree(annotee)(ctx)
mkAnnotation(atree, annotee)
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy