aboutsummaryrefslogtreecommitdiff
path: root/sbt-bridge/test
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2016-11-20 00:02:50 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:08 +0100
commitc3eb841ce8ae349d9820dbf6c18884955e74254e (patch)
tree5e82e22a6f0e8245c11a6db81cb9647106a14bde /sbt-bridge/test
parentda1bfe392c638fc03181e0d6b51eb41dbdcce548 (diff)
downloaddotty-c3eb841ce8ae349d9820dbf6c18884955e74254e.tar.gz
dotty-c3eb841ce8ae349d9820dbf6c18884955e74254e.tar.bz2
dotty-c3eb841ce8ae349d9820dbf6c18884955e74254e.zip
Make every project use the new directory structure
Diffstat (limited to 'sbt-bridge/test')
-rw-r--r--sbt-bridge/test/xsbt/DependencySpecification.scala151
-rw-r--r--sbt-bridge/test/xsbt/ExtractAPISpecification.scala45
-rw-r--r--sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala119
-rw-r--r--sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala191
-rw-r--r--sbt-bridge/test/xsbti/TestCallback.scala35
5 files changed, 541 insertions, 0 deletions
diff --git a/sbt-bridge/test/xsbt/DependencySpecification.scala b/sbt-bridge/test/xsbt/DependencySpecification.scala
new file mode 100644
index 000000000..60545091b
--- /dev/null
+++ b/sbt-bridge/test/xsbt/DependencySpecification.scala
@@ -0,0 +1,151 @@
+/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/DependencySpecification.scala */
+package xsbt
+
+import org.junit.runner.RunWith
+import xsbti.api.ClassLike
+import xsbti.api.Def
+import xsbt.api.SameAPI
+import org.specs2.mutable.Specification
+import org.specs2.runner.JUnitRunner
+
+import ScalaCompilerForUnitTesting.ExtractedSourceDependencies
+
+@RunWith(classOf[JUnitRunner])
+class DependencySpecification extends Specification {
+
+ "Extracted source dependencies from public members" in {
+ val sourceDependencies = extractSourceDependenciesPublic
+ val memberRef = sourceDependencies.memberRef
+ val inheritance = sourceDependencies.inheritance
+ memberRef('A) === Set.empty
+ inheritance('A) === Set.empty
+ memberRef('B) === Set('A, 'D)
+ inheritance('B) === Set('D)
+ memberRef('C) === Set('A)
+ inheritance('C) === Set.empty
+ memberRef('D) === Set.empty
+ inheritance('D) === Set.empty
+ memberRef('E) === Set.empty
+ inheritance('E) === Set.empty
+ memberRef('F) === Set('A, 'B, 'C, 'D, 'E, 'G)
+ inheritance('F) === Set('A, 'E)
+ memberRef('H) === Set('B, 'E, 'G)
+ // aliases and applied type constructors are expanded so we have inheritance dependency on B
+ inheritance('H) === Set('B, 'E)
+ }
+
+ "Extracted source dependencies from private members" in {
+ val sourceDependencies = extractSourceDependenciesPrivate
+ val memberRef = sourceDependencies.memberRef
+ val inheritance = sourceDependencies.inheritance
+ memberRef('A) === Set.empty
+ inheritance('A) === Set.empty
+ memberRef('B) === Set.empty
+ inheritance('B) === Set.empty
+ memberRef('C) === Set('A)
+ inheritance('C) === Set('A)
+ memberRef('D) === Set('B)
+ inheritance('D) === Set('B)
+ }
+
+ "Extracted source dependencies with trait as first parent" in {
+ val sourceDependencies = extractSourceDependenciesTraitAsFirstPatent
+ val memberRef = sourceDependencies.memberRef
+ val inheritance = sourceDependencies.inheritance
+ memberRef('A) === Set.empty
+ inheritance('A) === Set.empty
+ memberRef('B) === Set('A)
+ inheritance('B) === Set('A)
+ // verify that memberRef captures the oddity described in documentation of `Relations.inheritance`
+ // we are mainly interested whether dependency on A is captured in `memberRef` relation so
+ // the invariant that says that memberRef is superset of inheritance relation is preserved
+ memberRef('C) === Set('A, 'B)
+ inheritance('C) === Set('A, 'B)
+ // same as above but indirect (C -> B -> A), note that only A is visible here
+ memberRef('D) === Set('A, 'C)
+ inheritance('D) === Set('A, 'C)
+ }
+
+ /*
+ "Extracted source dependencies from macro arguments" in {
+ val sourceDependencies = extractSourceDependenciesFromMacroArgument
+ val memberRef = sourceDependencies.memberRef
+ val inheritance = sourceDependencies.inheritance
+
+ memberRef('A) === Set('B, 'C)
+ inheritance('A) === Set.empty
+ memberRef('B) === Set.empty
+ inheritance('B) === Set.empty
+ memberRef('C) === Set.empty
+ inheritance('C) === Set.empty
+ }
+ */
+
+ private def extractSourceDependenciesPublic: ExtractedSourceDependencies = {
+ val srcA = "class A"
+ val srcB = "class B extends D[A]"
+ val srcC = """|class C {
+ | def a: A = null
+ |}""".stripMargin
+ val srcD = "class D[T]"
+ val srcE = "trait E[T]"
+ val srcF = "trait F extends A with E[D[B]] { self: G.MyC => }"
+ val srcG = "object G { type T[x] = B ; type MyC = C }"
+ // T is a type constructor [x]B
+ // B extends D
+ // E verifies the core type gets pulled out
+ val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)"
+
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val sourceDependencies = compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC,
+ 'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH)
+ sourceDependencies
+ }
+
+ private def extractSourceDependenciesPrivate: ExtractedSourceDependencies = {
+ val srcA = "class A"
+ val srcB = "class B"
+ val srcC = "class C { private class Inner1 extends A }"
+ val srcD = "class D { def foo: Unit = { class Inner2 extends B } }"
+
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val sourceDependencies =
+ compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
+ sourceDependencies
+ }
+
+ private def extractSourceDependenciesTraitAsFirstPatent: ExtractedSourceDependencies = {
+ val srcA = "class A"
+ val srcB = "trait B extends A"
+ val srcC = "trait C extends B"
+ val srcD = "class D extends C"
+
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val sourceDependencies =
+ compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
+ sourceDependencies
+ }
+
+ /*
+ private def extractSourceDependenciesFromMacroArgument: ExtractedSourceDependencies = {
+ val srcA = "class A { println(B.printTree(C.foo)) }"
+ val srcB = """
+ |import scala.language.experimental.macros
+ |import scala.reflect.macros._
+ |object B {
+ | def printTree(arg: Any) = macro printTreeImpl
+ | def printTreeImpl(c: Context)(arg: c.Expr[Any]): c.Expr[String] = {
+ | val argStr = arg.tree.toString
+ | val literalStr = c.universe.Literal(c.universe.Constant(argStr))
+ | c.Expr[String](literalStr)
+ | }
+ |}""".stripMargin
+ val srcC = "object C { val foo = 1 }"
+
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val sourceDependencies =
+ compilerForTesting.extractDependenciesFromSrcs(List(Map('B -> srcB, 'C -> srcC), Map('A -> srcA)))
+ sourceDependencies
+ }
+ */
+}
diff --git a/sbt-bridge/test/xsbt/ExtractAPISpecification.scala b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala
new file mode 100644
index 000000000..f5af67e45
--- /dev/null
+++ b/sbt-bridge/test/xsbt/ExtractAPISpecification.scala
@@ -0,0 +1,45 @@
+/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/ExtractAPISpecification.scala */
+package xsbt
+
+import org.junit.runner.RunWith
+import xsbti.api.ClassLike
+import xsbti.api.Def
+import xsbt.api.ShowAPI
+import org.specs2.mutable.Specification
+import org.specs2.runner.JUnitRunner
+
+@RunWith(classOf[JUnitRunner])
+class ExtractAPISpecification extends Specification {
+
+ "Existential types in method signatures" should {
+ "have stable names" in { stableExistentialNames }
+ }
+
+ def stableExistentialNames: Boolean = {
+ def compileAndGetFooMethodApi(src: String): Def = {
+ val compilerForTesting = new ScalaCompilerForUnitTesting
+ val sourceApi = compilerForTesting.extractApiFromSrc(src)
+ val FooApi = sourceApi.definitions().find(_.name() == "Foo").get.asInstanceOf[ClassLike]
+ val fooMethodApi = FooApi.structure().declared().find(_.name == "foo").get
+ fooMethodApi.asInstanceOf[Def]
+ }
+ val src1 = """
+ |class Box[T]
+ |class Foo {
+ | def foo: Box[_] = null
+ |
+ }""".stripMargin
+ val fooMethodApi1 = compileAndGetFooMethodApi(src1)
+ val src2 = """
+ |class Box[T]
+ |class Foo {
+ | def bar: Box[_] = null
+ | def foo: Box[_] = null
+ |
+ }""".stripMargin
+ val fooMethodApi2 = compileAndGetFooMethodApi(src2)
+ fooMethodApi1 == fooMethodApi2
+ // Fails because xsbt.api is compiled with Scala 2.10
+ // SameAPI.apply(fooMethodApi1, fooMethodApi2)
+ }
+}
diff --git a/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala
new file mode 100644
index 000000000..ed463a3e6
--- /dev/null
+++ b/sbt-bridge/test/xsbt/ExtractUsedNamesSpecification.scala
@@ -0,0 +1,119 @@
+/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/ExtractUsedNamesSpecification.scala */
+package xsbt
+
+import org.junit.runner.RunWith
+import xsbti.api.ClassLike
+import xsbti.api.Def
+import xsbti.api.Package
+import xsbt.api.SameAPI
+import org.junit.runners.JUnit4
+
+import org.specs2.mutable.Specification
+
+@RunWith(classOf[JUnit4])
+class ExtractUsedNamesSpecification extends Specification {
+
+ /**
+ * Standard names that appear in every compilation unit that has any class
+ * definition.
+ */
+ private val standardNames = Set(
+ // All class extend Object
+ "Object",
+ // All class have a default constructor called <init>
+ "<init>",
+ // the return type of the default constructor is Unit
+ "Unit"
+ )
+
+ "imported name" in {
+ val src = """
+ |package a { class A }
+ |package b {
+ | import a.{A => A2}
+ |}""".stripMargin
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val usedNames = compilerForTesting.extractUsedNamesFromSrc(src)
+ val expectedNames = standardNames ++ Set("a", "A", "A2", "b")
+ usedNames === expectedNames
+ }
+
+ // test covers https://github.com/gkossakowski/sbt/issues/6
+ "names in type tree" in {
+ val srcA = """|
+ |package a {
+ | class A {
+ | class C { class D }
+ | }
+ | class B[T]
+ | class BB
+ |}""".stripMargin
+ val srcB = """|
+ |package b {
+ | abstract class X {
+ | def foo: a.A#C#D
+ | def bar: a.B[a.BB]
+ | }
+ |}""".stripMargin
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB)
+ // DOTTY: unlike the scalac sbt phase, this does not contain "X", I believe this is safe
+ // TODO: report issue against sbt suggesting that they do the same
+ val expectedNames = standardNames ++ Set("a", "A", "B", "C", "D", "b", "BB")
+ usedNames === expectedNames
+ }
+
+ // test for https://github.com/gkossakowski/sbt/issues/5
+ "symbolic names" in {
+ val srcA = """|
+ |class A {
+ | def `=`: Int = 3
+ |}""".stripMargin
+ val srcB = """|
+ |class B {
+ | def foo(a: A) = a.`=`
+ |}""".stripMargin
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB)
+ // DOTTY TODO: "Int" is not actually used, but we collect it because
+ // it's the inferred return type so it appears in a TypeTree
+ // We could avoid this by checking if the untyped tree has a return type
+ // but is it worth it? Revisit this after https://github.com/sbt/sbt/issues/1104
+ // has landed.
+ val expectedNames = standardNames ++ Set("A", "a", "$eq", "Int")
+ usedNames === expectedNames
+ }
+
+ // test for https://github.com/gkossakowski/sbt/issues/3
+ "used names from the same compilation unit" in {
+ val src = "class A { def foo: Int = 0; def bar: Int = foo }"
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val usedNames = compilerForTesting.extractUsedNamesFromSrc(src)
+ val expectedNames = standardNames ++ Set("A", "foo", "Int")
+ usedNames === expectedNames
+ }
+
+ // pending test for https://issues.scala-lang.org/browse/SI-7173
+ "names of constants" in {
+ val src = "class A { final val foo = 12; def bar: Int = foo }"
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val usedNames = compilerForTesting.extractUsedNamesFromSrc(src)
+ val expectedNames = standardNames ++ Set("A", "foo", "Int")
+ usedNames === expectedNames
+ }
+
+ // pending test for https://github.com/gkossakowski/sbt/issues/4
+ // TODO: we should fix it by having special treatment of `selectDynamic` and `applyDynamic` calls
+ "names from method calls on Dynamic" in {
+ val srcA = """|import scala.language.dynamics
+ |class A extends Dynamic {
+ | def selectDynamic(name: String): Int = name.length
+ |}""".stripMargin
+ val srcB = "class B { def foo(a: A): Int = a.bla }"
+ val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
+ val usedNames = compilerForTesting.extractUsedNamesFromSrc(srcA, srcB)
+ val expectedNames = standardNames ++ Set("B", "A", "a", "Int", "selectDynamic", "bla")
+ usedNames === expectedNames
+ }.pendingUntilFixed("Call to Dynamic is desugared in type checker so Select nodes is turned into string literal.")
+
+}
diff --git a/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala b/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala
new file mode 100644
index 000000000..db037effe
--- /dev/null
+++ b/sbt-bridge/test/xsbt/ScalaCompilerForUnitTesting.scala
@@ -0,0 +1,191 @@
+/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala */
+package xsbt
+
+import xsbti.compile.SingleOutput
+import java.io.File
+import _root_.scala.tools.nsc.reporters.ConsoleReporter
+import _root_.scala.tools.nsc.Settings
+import xsbti._
+import xsbti.api.SourceAPI
+import sbt.IO.withTemporaryDirectory
+import xsbti.api.ClassLike
+import xsbti.api.Definition
+import xsbti.api.Def
+import xsbt.api.SameAPI
+import sbt.ConsoleLogger
+import xsbti.DependencyContext._
+
+import ScalaCompilerForUnitTesting.ExtractedSourceDependencies
+
+/**
+ * Provides common functionality needed for unit tests that require compiling
+ * source code using Scala compiler.
+ */
+class ScalaCompilerForUnitTesting(nameHashing: Boolean = false) {
+
+ /**
+ * Compiles given source code using Scala compiler and returns API representation
+ * extracted by ExtractAPI class.
+ */
+ def extractApiFromSrc(src: String): SourceAPI = {
+ val (Seq(tempSrcFile), analysisCallback) = compileSrcs(src)
+ analysisCallback.apis(tempSrcFile)
+ }
+
+ def extractUsedNamesFromSrc(src: String): Set[String] = {
+ val (Seq(tempSrcFile), analysisCallback) = compileSrcs(src)
+ analysisCallback.usedNames(tempSrcFile)
+ }
+
+ /**
+ * Extract used names from src provided as the second argument.
+ *
+ * The purpose of the first argument is to define names that the second
+ * source is going to refer to. Both files are compiled in the same compiler
+ * Run but only names used in the second src file are returned.
+ */
+ def extractUsedNamesFromSrc(definitionSrc: String, actualSrc: String): Set[String] = {
+ // we drop temp src file corresponding to the definition src file
+ val (Seq(_, tempSrcFile), analysisCallback) = compileSrcs(definitionSrc, actualSrc)
+ analysisCallback.usedNames(tempSrcFile)
+ }
+
+ /**
+ * Compiles given source code snippets (passed as Strings) using Scala compiler and returns extracted
+ * dependencies between snippets. Source code snippets are identified by symbols. Each symbol should
+ * be associated with one snippet only.
+ *
+ * Snippets can be grouped to be compiled together in the same compiler run. This is
+ * useful to compile macros, which cannot be used in the same compilation run that
+ * defines them.
+ *
+ * Symbols are used to express extracted dependencies between source code snippets. This way we have
+ * file system-independent way of testing dependencies between source code "files".
+ */
+ def extractDependenciesFromSrcs(srcs: List[Map[Symbol, String]]): ExtractedSourceDependencies = {
+ val rawGroupedSrcs = srcs.map(_.values.toList)
+ val symbols = srcs.flatMap(_.keys)
+ val (tempSrcFiles, testCallback) = compileSrcs(rawGroupedSrcs)
+ val fileToSymbol = (tempSrcFiles zip symbols).toMap
+
+ val memberRefFileDeps = testCallback.sourceDependencies collect {
+ // false indicates that those dependencies are not introduced by inheritance
+ case (target, src, DependencyByMemberRef) => (src, target)
+ }
+ val inheritanceFileDeps = testCallback.sourceDependencies collect {
+ // true indicates that those dependencies are introduced by inheritance
+ case (target, src, DependencyByInheritance) => (src, target)
+ }
+ def toSymbols(src: File, target: File): (Symbol, Symbol) = (fileToSymbol(src), fileToSymbol(target))
+ val memberRefDeps = memberRefFileDeps map { case (src, target) => toSymbols(src, target) }
+ val inheritanceDeps = inheritanceFileDeps map { case (src, target) => toSymbols(src, target) }
+ def pairsToMultiMap[A, B](pairs: Seq[(A, B)]): Map[A, Set[B]] = {
+ import scala.collection.mutable.{ HashMap, MultiMap }
+ val emptyMultiMap = new HashMap[A, scala.collection.mutable.Set[B]] with MultiMap[A, B]
+ val multiMap = pairs.foldLeft(emptyMultiMap) {
+ case (acc, (key, value)) =>
+ acc.addBinding(key, value)
+ }
+ // convert all collections to immutable variants
+ multiMap.toMap.mapValues(_.toSet).withDefaultValue(Set.empty)
+ }
+
+ ExtractedSourceDependencies(pairsToMultiMap(memberRefDeps), pairsToMultiMap(inheritanceDeps))
+ }
+
+ def extractDependenciesFromSrcs(srcs: (Symbol, String)*): ExtractedSourceDependencies = {
+ val symbols = srcs.map(_._1)
+ assert(symbols.distinct.size == symbols.size,
+ s"Duplicate symbols for srcs detected: $symbols")
+ extractDependenciesFromSrcs(List(srcs.toMap))
+ }
+
+ /**
+ * Compiles given source code snippets written to temporary files. Each snippet is
+ * written to a separate temporary file.
+ *
+ * Snippets can be grouped to be compiled together in the same compiler run. This is
+ * useful to compile macros, which cannot be used in the same compilation run that
+ * defines them.
+ *
+ * The sequence of temporary files corresponding to passed snippets and analysis
+ * callback is returned as a result.
+ */
+ private def compileSrcs(groupedSrcs: List[List[String]]): (Seq[File], TestCallback) = {
+ withTemporaryDirectory { temp =>
+ val analysisCallback = new TestCallback(nameHashing)
+ val classesDir = new File(temp, "classes")
+ classesDir.mkdir()
+
+ // val (compiler, ctx) = prepareCompiler(classesDir, analysisCallback, classesDir.toString)
+
+ val files = for ((compilationUnit, unitId) <- groupedSrcs.zipWithIndex) yield {
+ val (compiler, ctx) = prepareCompiler(classesDir, analysisCallback, classesDir.toString)
+ val run = compiler.newRun(ctx)
+ val srcFiles = compilationUnit.toSeq.zipWithIndex map {
+ case (src, i) =>
+ val fileName = s"Test-$unitId-$i.scala"
+ prepareSrcFile(temp, fileName, src)
+ }
+ val srcFilePaths = srcFiles.map(srcFile => srcFile.getAbsolutePath).toList
+
+ run.compile(srcFilePaths)
+
+ srcFilePaths.foreach(f => new File(f).delete)
+ srcFiles
+ }
+ (files.flatten.toSeq, analysisCallback)
+ }
+ }
+
+ private def compileSrcs(srcs: String*): (Seq[File], TestCallback) = {
+ compileSrcs(List(srcs.toList))
+ }
+
+ private def prepareSrcFile(baseDir: File, fileName: String, src: String): File = {
+ val srcFile = new File(baseDir, fileName)
+ sbt.IO.write(srcFile, src)
+ srcFile
+ }
+
+ private def prepareCompiler(outputDir: File, analysisCallback: AnalysisCallback, classpath: String = ".") = {
+ val args = Array.empty[String]
+ object output extends SingleOutput {
+ def outputDirectory: File = outputDir
+ override def toString = s"SingleOutput($outputDirectory)"
+ }
+
+ import dotty.tools.dotc._
+ import dotty.tools.dotc.core.Contexts._
+
+ val driver = new Driver {
+
+ protected def newCompiler(implicit ctx: Context): Compiler = new Compiler
+
+ override protected def sourcesRequired = false
+
+ def getCompiler(args: Array[String], rootCtx: Context) = {
+ val (fileNames, ctx) = setup(args, rootCtx)
+ (newCompiler(ctx), ctx)
+ }
+ }
+ val ctx = (new ContextBase).initialCtx.fresh.setSbtCallback(analysisCallback)
+ driver.getCompiler(Array("-classpath", classpath, "-usejavacp"), ctx)
+ }
+
+ private object ConsoleReporter extends Reporter {
+ def reset(): Unit = ()
+ def hasErrors: Boolean = false
+ def hasWarnings: Boolean = false
+ def printWarnings(): Unit = ()
+ def problems: Array[Problem] = Array.empty
+ def log(pos: Position, msg: String, sev: Severity): Unit = println(msg)
+ def comment(pos: Position, msg: String): Unit = ()
+ def printSummary(): Unit = ()
+ }
+
+}
+
+object ScalaCompilerForUnitTesting {
+ case class ExtractedSourceDependencies(memberRef: Map[Symbol, Set[Symbol]], inheritance: Map[Symbol, Set[Symbol]])
+}
diff --git a/sbt-bridge/test/xsbti/TestCallback.scala b/sbt-bridge/test/xsbti/TestCallback.scala
new file mode 100644
index 000000000..b849e1a80
--- /dev/null
+++ b/sbt-bridge/test/xsbti/TestCallback.scala
@@ -0,0 +1,35 @@
+/** Copied from https://github.com/sbt/sbt/blob/0.13/interface/src/test/scala/xsbti/TestCallback.scala */
+package xsbti
+
+import java.io.File
+import scala.collection.mutable.ArrayBuffer
+import xsbti.api.SourceAPI
+import xsbti.DependencyContext._
+
+class TestCallback(override val nameHashing: Boolean = false) extends AnalysisCallback
+{
+ val sourceDependencies = new ArrayBuffer[(File, File, DependencyContext)]
+ val binaryDependencies = new ArrayBuffer[(File, String, File, DependencyContext)]
+ val products = new ArrayBuffer[(File, File, String)]
+ val usedNames = scala.collection.mutable.Map.empty[File, Set[String]].withDefaultValue(Set.empty)
+ val apis: scala.collection.mutable.Map[File, SourceAPI] = scala.collection.mutable.Map.empty
+
+ def sourceDependency(dependsOn: File, source: File, inherited: Boolean): Unit = {
+ val context = if(inherited) DependencyByInheritance else DependencyByMemberRef
+ sourceDependency(dependsOn, source, context)
+ }
+ def sourceDependency(dependsOn: File, source: File, context: DependencyContext): Unit = { sourceDependencies += ((dependsOn, source, context)) }
+ def binaryDependency(binary: File, name: String, source: File, inherited: Boolean): Unit = {
+ val context = if(inherited) DependencyByInheritance else DependencyByMemberRef
+ binaryDependency(binary, name, source, context)
+ }
+ def binaryDependency(binary: File, name: String, source: File, context: DependencyContext): Unit = { binaryDependencies += ((binary, name, source, context)) }
+ def generatedClass(source: File, module: File, name: String): Unit = { products += ((source, module, name)) }
+
+ def usedName(source: File, name: String): Unit = { usedNames(source) += name }
+ def api(source: File, sourceAPI: SourceAPI): Unit = {
+ assert(!apis.contains(source), s"The `api` method should be called once per source file: $source")
+ apis(source) = sourceAPI
+ }
+ def problem(category: String, pos: xsbti.Position, message: String, severity: xsbti.Severity, reported: Boolean): Unit = ()
+}