diff options
author | Dmitry Petrashko <dark@d-d.me> | 2016-12-16 10:55:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-16 10:55:42 +0100 |
commit | 653698ef67a5cf8f5e0fd0fcdcd1f631f1dc96e2 (patch) | |
tree | 9ba2ced6eca5d58190dcdb40422be3e0ff2380be /compiler | |
parent | 50bcb1ac954436d011cf11a30ef0ee4a066c00d1 (diff) | |
parent | 9411539eac8aaa8f052b7e6701d5d1d2b833d409 (diff) | |
download | dotty-653698ef67a5cf8f5e0fd0fcdcd1f631f1dc96e2.tar.gz dotty-653698ef67a5cf8f5e0fd0fcdcd1f631f1dc96e2.tar.bz2 dotty-653698ef67a5cf8f5e0fd0fcdcd1f631f1dc96e2.zip |
Merge pull request #1763 from dotty-staging/fix/annotations
Fix emission of annotations
Diffstat (limited to 'compiler')
3 files changed, 41 insertions, 22 deletions
diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 397382c2f..ed32d2df9 100644 --- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -206,18 +206,15 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma implicit val ConstantClassTag: ClassTag[Constant] = ClassTag[Constant](classOf[Constant]) implicit val ClosureTag: ClassTag[Closure] = ClassTag[Closure](classOf[Closure]) - /* dont emit any annotations for now*/ - def isRuntimeVisible(annot: Annotation): Boolean = { - annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr) match { - case Some(retentionAnnot) => - retentionAnnot.tree.find(_.symbol == AnnotationRetentionRuntimeAttr).isDefined - case _ => - // SI-8926: if the annotation class symbol doesn't have a @RetentionPolicy annotation, the - // annotation is emitted with visibility `RUNTIME` - // dotty bug: #389 - true + def isRuntimeVisible(annot: Annotation): Boolean = + if (toDenot(annot.atp.typeSymbol).hasAnnotation(AnnotationRetentionAttr)) + retentionPolicyOf(annot) == AnnotationRetentionRuntimeAttr + else { + // SI-8926: if the annotation class symbol doesn't have a @RetentionPolicy annotation, the + // annotation is emitted with visibility `RUNTIME` + // dotty bug: #389 + true } - } def shouldEmitAnnotation(annot: Annotation): Boolean = { annot.symbol.isJavaDefined && @@ -227,7 +224,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma private def retentionPolicyOf(annot: Annotation): Symbol = annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr). - flatMap(_.argument(0).map(_.symbol)).getOrElse(AnnotationRetentionClassAttr) + flatMap(_.argumentConstant(0).map(_.symbolValue)).getOrElse(AnnotationRetentionClassAttr) private def emitArgument(av: AnnotationVisitor, name: String, @@ -708,7 +705,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma } else Nil - def annotations: List[Annotation] = Nil + def annotations: List[Annotation] = toDenot(sym).annotations def companionModuleMembers: List[Symbol] = { // phase travel to exitingPickler: this makes sure that memberClassesOf only sees member classes, // not local classes of the companion module (E in the exmaple) that were lifted by lambdalift. diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index bc8528c05..1fffe6841 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -3,7 +3,7 @@ package sbt import ast.{Trees, tpd} import core._, core.Decorators._ -import Contexts._, Flags._, Phases._, Trees._, Types._, Symbols._ +import Annotations._, Contexts._, Flags._, Phases._, Trees._, Types._, Symbols._ import Names._, NameOps._, StdNames._ import typer.Inliner @@ -333,7 +333,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder // TODO: Never dealias. We currently have to dealias because // sbt main class discovery relies on the signature of the main // method being fully dealiased. See https://github.com/sbt/zinc/issues/102 - val tp2 = if (!tp.isHK) tp.dealias else tp + val tp2 = if (!tp.isHK) tp.dealiasKeepAnnots else tp tp2 match { case NoPrefix | NoType => Constants.emptyType @@ -411,9 +411,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder case ConstantType(constant) => new api.Constant(apiType(constant.tpe), constant.stringValue) case AnnotatedType(tpe, annot) => - // TODO: Annotation support - ctx.debuglog(i"sbt-api: skipped annotation in $tp2") - apiType(tpe) + new api.Annotated(apiType(tpe), Array(apiAnnotation(annot))) case tp: ThisType => apiThis(tp.cls) case tp: ParamType => @@ -498,7 +496,6 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder sym.is(Implicit), sym.is(Lazy), sym.is(Macro), sym.is(SuperAccessor)) } - // TODO: Support other annotations def apiAnnotations(s: Symbol): List[api.Annotation] = { val annots = new mutable.ListBuffer[api.Annotation] @@ -513,6 +510,27 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder annots += marker(Inliner.bodyToInline(s).show(printTypesCtx).toString) } + // In the Scala2 ExtractAPI phase we only extract annotations that extend + // StaticAnnotation, but in Dotty we currently pickle all annotations so we + // extract everything (except inline body annotations which are handled + // above). + s.annotations.filter(_.symbol != defn.BodyAnnot) foreach { annot => + annots += apiAnnotation(annot) + } + annots.toList } + + def apiAnnotation(annot: Annotation): api.Annotation = { + // FIXME: To faithfully extract an API we should extract the annotation tree, + // sbt instead wants us to extract the annotation type and its arguments, + // to do this properly we would need a way to hash trees and types in dotty itself, + // instead we pretty-print the annotation tree. + // However, we still need to extract the annotation type in the way sbt expect + // because sbt uses this information to find tests to run (for example + // junit tests are annotated @org.junit.Test). + new api.Annotation( + apiType(annot.tree.tpe), // Used by sbt to find tests to run + Array(new api.AnnotationArgument("FULLTREE", annot.tree.show.toString))) + } } diff --git a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala index 5385ca720..b0bd40578 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -3,7 +3,6 @@ package dotc package transform import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Annotations.ConcreteAnnotation import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.DenotTransformers.{InfoTransformer, DenotTransformer} import dotty.tools.dotc.core.Denotations.SingleDenotation @@ -181,10 +180,15 @@ object TreeTransforms { abstract override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = super.transform(ref) match { case ref1: SymDenotation if ref1.symbol.isDefinedInCurrentRun => - val annotTrees = ref1.annotations.map(_.tree) + val annots = ref1.annotations + val annotTrees = annots.map(_.tree) val annotTrees1 = annotTrees.mapConserve(annotationTransformer.macroTransform) if (annotTrees eq annotTrees1) ref1 - else ref1.copySymDenotation(annotations = annotTrees1.map(new ConcreteAnnotation(_))) + else { + val derivedAnnots = (annots, annotTrees1).zipped.map((annot, annotTree1) => + annot.derivedAnnotation(annotTree1)) + ref1.copySymDenotation(annotations = derivedAnnots) + } case ref1 => ref1 } |