From 8a61ff432543a29234193cd1f7c14abd3f3d31a0 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 2 Nov 2016 11:08:28 +0100 Subject: Move compiler and compiler tests to compiler dir --- .../src/dotty/tools/dotc/core/Annotations.scala | 162 +++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 compiler/src/dotty/tools/dotc/core/Annotations.scala (limited to 'compiler/src/dotty/tools/dotc/core/Annotations.scala') diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala new file mode 100644 index 000000000..0e8e5a1f0 --- /dev/null +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -0,0 +1,162 @@ +package dotty.tools.dotc +package core + +import Symbols._, Types._, util.Positions._, Contexts._, Constants._, ast.tpd._ +import config.ScalaVersion +import StdNames._ +import dotty.tools.dotc.ast.{tpd, untpd} + +object Annotations { + + abstract class Annotation { + def tree(implicit ctx: Context): Tree + def symbol(implicit ctx: Context): Symbol = + if (tree.symbol.isConstructor) tree.symbol.owner + else tree.tpe.typeSymbol + def matches(cls: Symbol)(implicit ctx: Context): Boolean = symbol.derivesFrom(cls) + def appliesToModule: Boolean = true // for now; see remark in SymDenotations + + def derivedAnnotation(tree: Tree)(implicit ctx: Context) = + if (tree eq this.tree) this else Annotation(tree) + + def arguments(implicit ctx: Context) = ast.tpd.arguments(tree) + def argument(i: Int)(implicit ctx: Context): Option[Tree] = { + val args = arguments + if (i < args.length) Some(args(i)) else None + } + def argumentConstant(i: Int)(implicit ctx: Context): Option[Constant] = + for (ConstantType(c) <- argument(i) map (_.tpe)) yield c + + def ensureCompleted(implicit ctx: Context): Unit = tree + } + + case class ConcreteAnnotation(t: Tree) extends Annotation { + def tree(implicit ctx: Context): Tree = t + } + + abstract case class LazyAnnotation(sym: Symbol) extends Annotation { + private var myTree: Tree = null + def tree(implicit ctx: Context) = { + if (myTree == null) myTree = complete(ctx) + myTree + } + def complete(implicit ctx: Context): Tree + override def symbol(implicit ctx: Context): Symbol = sym + } + + /** An annotation indicating the body of a right-hand side, + * typically of an inline method. Treated specially in + * pickling/unpickling and TypeTreeMaps + */ + abstract class BodyAnnotation extends Annotation { + override def symbol(implicit ctx: Context) = defn.BodyAnnot + override def derivedAnnotation(tree: Tree)(implicit ctx: Context) = + if (tree eq this.tree) this else ConcreteBodyAnnotation(tree) + override def arguments(implicit ctx: Context) = Nil + override def ensureCompleted(implicit ctx: Context) = () + } + + case class ConcreteBodyAnnotation(body: Tree) extends BodyAnnotation { + def tree(implicit ctx: Context) = body + } + + case class LazyBodyAnnotation(bodyExpr: Context => Tree) extends BodyAnnotation { + private var evaluated = false + private var myBody: Tree = _ + def tree(implicit ctx: Context) = { + if (evaluated) assert(myBody != null) + else { + evaluated = true + myBody = bodyExpr(ctx) + } + myBody + } + def isEvaluated = evaluated + } + + object Annotation { + + def apply(tree: Tree) = ConcreteAnnotation(tree) + + def apply(cls: ClassSymbol)(implicit ctx: Context): Annotation = + apply(cls, Nil) + + def apply(cls: ClassSymbol, arg: Tree)(implicit ctx: Context): Annotation = + apply(cls, arg :: Nil) + + def apply(cls: ClassSymbol, arg1: Tree, arg2: Tree)(implicit ctx: Context): Annotation = + apply(cls, arg1 :: arg2 :: Nil) + + def apply(cls: ClassSymbol, args: List[Tree])(implicit ctx: Context): Annotation = + apply(cls.typeRef, args) + + def apply(atp: Type, arg: Tree)(implicit ctx: Context): Annotation = + apply(atp, arg :: Nil) + + def apply(atp: Type, arg1: Tree, arg2: Tree)(implicit ctx: Context): Annotation = + apply(atp, arg1 :: arg2 :: Nil) + + def apply(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = + apply(New(atp, args)) + + private def resolveConstructor(atp: Type, args:List[Tree])(implicit ctx: Context): Tree = { + val targs = atp.argTypes + tpd.applyOverloaded(New(atp withoutArgs targs), nme.CONSTRUCTOR, args, targs, atp, isAnnotConstructor = true) + } + + def applyResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = { + apply(resolveConstructor(atp, args)) + } + + def deferred(sym: Symbol, treeFn: Context => Tree)(implicit ctx: Context): Annotation = + new LazyAnnotation(sym) { + def complete(implicit ctx: Context) = treeFn(ctx) + } + + def deferred(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = + deferred(atp.classSymbol, implicit ctx => New(atp, args)) + + def deferredResolve(atp: Type, args: List[Tree])(implicit ctx: Context): Annotation = + deferred(atp.classSymbol, implicit ctx => resolveConstructor(atp, args)) + + def makeAlias(sym: TermSymbol)(implicit ctx: Context) = + apply(defn.AliasAnnot, List( + ref(TermRef.withSigAndDenot(sym.owner.thisType, sym.name, sym.signature, sym)))) + + def makeChild(sym: Symbol)(implicit ctx: Context) = + deferred(defn.ChildAnnot, + implicit ctx => New(defn.ChildAnnotType.appliedTo(sym.owner.thisType.select(sym.name, sym)), Nil)) + + def makeSourceFile(path: String)(implicit ctx: Context) = + apply(defn.SourceFileAnnot, Literal(Constant(path))) + } + + def ThrowsAnnotation(cls: ClassSymbol)(implicit ctx: Context) = { + val tref = cls.typeRef + Annotation(defn.ThrowsAnnotType.appliedTo(tref), Ident(tref)) + } + + /** A decorator that provides queries for specific annotations + * of a symbol. + */ + implicit class AnnotInfo(val sym: Symbol) extends AnyVal { + + def isDeprecated(implicit ctx: Context) = + sym.hasAnnotation(defn.DeprecatedAnnot) + + def deprecationMessage(implicit ctx: Context) = + for (annot <- sym.getAnnotation(defn.DeprecatedAnnot); + arg <- annot.argumentConstant(0)) + yield arg.stringValue + + def migrationVersion(implicit ctx: Context) = + for (annot <- sym.getAnnotation(defn.MigrationAnnot); + arg <- annot.argumentConstant(1)) + yield ScalaVersion.parse(arg.stringValue) + + def migrationMessage(implicit ctx: Context) = + for (annot <- sym.getAnnotation(defn.MigrationAnnot); + arg <- annot.argumentConstant(0)) + yield ScalaVersion.parse(arg.stringValue) + } +} -- cgit v1.2.3