diff options
Diffstat (limited to 'sbt-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala')
-rw-r--r-- | sbt-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala | 191 |
1 files changed, 0 insertions, 191 deletions
diff --git a/sbt-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala b/sbt-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala deleted file mode 100644 index db037effe..000000000 --- a/sbt-bridge/src/test/scala/xsbt/ScalaCompilerForUnitTesting.scala +++ /dev/null @@ -1,191 +0,0 @@ -/** 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]]) -} |