aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala23
-rw-r--r--compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala30
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TreeTransform.scala10
-rw-r--r--sbt-bridge/sbt-test/discovery/test-discovery/build.sbt1
-rw-r--r--sbt-bridge/sbt-test/discovery/test-discovery/changes/A2.scala3
-rw-r--r--sbt-bridge/sbt-test/discovery/test-discovery/project/DottyInjectedPlugin.scala17
-rw-r--r--sbt-bridge/sbt-test/discovery/test-discovery/src/main/scala/A.scala3
-rw-r--r--sbt-bridge/sbt-test/discovery/test-discovery/src/test/scala/TestA.scala8
-rw-r--r--sbt-bridge/sbt-test/discovery/test-discovery/test8
9 files changed, 81 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
}
diff --git a/sbt-bridge/sbt-test/discovery/test-discovery/build.sbt b/sbt-bridge/sbt-test/discovery/test-discovery/build.sbt
new file mode 100644
index 000000000..68b89ac35
--- /dev/null
+++ b/sbt-bridge/sbt-test/discovery/test-discovery/build.sbt
@@ -0,0 +1 @@
+libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test"
diff --git a/sbt-bridge/sbt-test/discovery/test-discovery/changes/A2.scala b/sbt-bridge/sbt-test/discovery/test-discovery/changes/A2.scala
new file mode 100644
index 000000000..696daab5e
--- /dev/null
+++ b/sbt-bridge/sbt-test/discovery/test-discovery/changes/A2.scala
@@ -0,0 +1,3 @@
+object A {
+ def three: Int = 3 // Ah!
+}
diff --git a/sbt-bridge/sbt-test/discovery/test-discovery/project/DottyInjectedPlugin.scala b/sbt-bridge/sbt-test/discovery/test-discovery/project/DottyInjectedPlugin.scala
new file mode 100644
index 000000000..ec22870f4
--- /dev/null
+++ b/sbt-bridge/sbt-test/discovery/test-discovery/project/DottyInjectedPlugin.scala
@@ -0,0 +1,17 @@
+import sbt._
+import Keys._
+
+object DottyInjectedPlugin extends AutoPlugin {
+ override def requires = plugins.JvmPlugin
+ override def trigger = allRequirements
+
+ override val projectSettings = Seq(
+ scalaVersion := "0.1-SNAPSHOT",
+ scalaOrganization := "ch.epfl.lamp",
+ scalacOptions += "-language:Scala2",
+ scalaBinaryVersion := "2.11",
+ autoScalaLibrary := false,
+ libraryDependencies ++= Seq("org.scala-lang" % "scala-library" % "2.11.5"),
+ scalaCompilerBridgeSource := ("ch.epfl.lamp" % "dotty-sbt-bridge" % "0.1.1-SNAPSHOT" % "component").sources()
+ )
+}
diff --git a/sbt-bridge/sbt-test/discovery/test-discovery/src/main/scala/A.scala b/sbt-bridge/sbt-test/discovery/test-discovery/src/main/scala/A.scala
new file mode 100644
index 000000000..81f77071e
--- /dev/null
+++ b/sbt-bridge/sbt-test/discovery/test-discovery/src/main/scala/A.scala
@@ -0,0 +1,3 @@
+object A {
+ def three: Int = 4 // Hmm
+}
diff --git a/sbt-bridge/sbt-test/discovery/test-discovery/src/test/scala/TestA.scala b/sbt-bridge/sbt-test/discovery/test-discovery/src/test/scala/TestA.scala
new file mode 100644
index 000000000..1d4f479d8
--- /dev/null
+++ b/sbt-bridge/sbt-test/discovery/test-discovery/src/test/scala/TestA.scala
@@ -0,0 +1,8 @@
+import org.junit.Test
+import org.junit.Assert.assertEquals
+
+class TestA {
+ @Test def testThree = {
+ assertEquals(A.three, 3)
+ }
+}
diff --git a/sbt-bridge/sbt-test/discovery/test-discovery/test b/sbt-bridge/sbt-test/discovery/test-discovery/test
new file mode 100644
index 000000000..2e035dee8
--- /dev/null
+++ b/sbt-bridge/sbt-test/discovery/test-discovery/test
@@ -0,0 +1,8 @@
+> compile
+# Intentionally failing test
+-> test
+# Fix the bug!
+$ copy-file changes/A2.scala src/main/scala/A.scala
+> compile
+# The test should pass now
+> test