summaryrefslogblamecommitdiff
path: root/src/main/scala/forge/scalaplugin/Subproject.scala
blob: c4c9c562d241e2793bee7d4bb03c56ec70500894 (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                   




                                                                                           

                          






                                                                     
                  






























































                                                                                                                                                            
                                                  












                                                                                 








                                              
















                                                                                             



                                                                        





                                          


                                                                                         
package forge
package scalaplugin

import java.io.File

import ammonite.ops.{Path, ls, mkdir, pwd}
import coursier.{Cache, Dependency, Fetch, MavenRepository, Module, Repository, Resolution}
import forge.scalaplugin.Compile.getClass
import forge.{Target => T}
import forge.util.PathRef
import sbt.internal.inc.{FreshCompilerCache, ScalaInstance, ZincUtil}
import sbt.internal.util.{ConsoleOut, MainAppender}
import sbt.util.LogExchange
import xsbti.api.{ClassLike, DependencyContext}
import xsbti.compile.DependencyChanges

import scalaz.concurrent.Task
object Subproject{
  def compileScala(scalaVersion: T[String],
                   sources: T[PathRef],
                   compileClasspath: T[Seq[PathRef]],
                   outputPath: T[Path]): T[PathRef] = {
    for((scalaVersion, sources, compileClasspath, outputPath) <- zip(scalaVersion, sources, compileClasspath, outputPath))
    yield {
      val binaryScalaVersion = scalaVersion.split('.').dropRight(1).mkString(".")
      def grepJar(s: String) = compileClasspath.find(_.toString.endsWith(s)).get.path.toIO
      val scalac = ZincUtil.scalaCompiler(
        new ScalaInstance(
          version = scalaVersion,
          loader = getClass.getClassLoader,
          libraryJar = grepJar(s"scala-library-$scalaVersion.jar"),
          compilerJar = grepJar(s"scala-compiler-$scalaVersion.jar"),
          allJars = compileClasspath.toArray.map(_.path.toIO),
          explicitActual = None
        ),
        grepJar(s"compiler-bridge_$binaryScalaVersion-1.0.3.jar")
      )

      val outputDir = pwd/'target/'zinc
      mkdir(outputDir)


      scalac.apply(
        sources = ls.rec(sources.path).map(_.toIO).toArray,
        changes = new DependencyChanges {
          def isEmpty = true
          def modifiedBinaries() = Array[File]()
          def modifiedClasses() = Array[String]()
        },
        classpath = compileClasspath.map(_.path.toIO).toArray,
        singleOutput = outputDir.toIO,
        options = Array(),
        callback = new xsbti.AnalysisCallback {
          def startSource(source: File) = ()
          def apiPhaseCompleted() = ()
          def enabled() = true
          def binaryDependency(onBinaryEntry: File, onBinaryClassName: String, fromClassName: String, fromSourceFile: File, context: DependencyContext) = ()
          def generatedNonLocalClass(source: File, classFile: File, binaryClassName: String, srcClassName: String) = ()
          def problem(what: String, pos: xsbti.Position, msg: String, severity: xsbti.Severity, reported: Boolean) = ()
          def dependencyPhaseCompleted() = ()
          def classDependency(onClassName: String, sourceClassName: String, context: DependencyContext) = ()
          def generatedLocalClass(source: File, classFile: File) = ()
          def api(sourceFile: File, classApi: ClassLike) = ()

          def mainClass(sourceFile: File, className: String) = ()
          def usedName(className: String, name: String, useScopes: java.util.EnumSet[xsbti.UseScope]) = ()
        },
        maximumErrors = 10,
        cache = new FreshCompilerCache(),
        log = {
          val console = ConsoleOut.systemOut
          val consoleAppender = MainAppender.defaultScreen(console)
          val l = LogExchange.logger("Hello")
          LogExchange.unbindLoggerAppenders("Hello")
          LogExchange.bindLoggerAppenders("Hello", (consoleAppender -> sbt.util.Level.Warn) :: Nil)
          l
        }
      )
      PathRef(outputPath)
    }
  }
  def createJar(sourceDirs: T[Seq[PathRef]]) = ???
  def resolveDependencies(repositories: T[Seq[Repository]],
                          deps: T[Seq[coursier.Dependency]]): T[Seq[PathRef]] = {
    for((repositories, deps) <- zip(repositories, deps)) yield {
      val start = Resolution(deps.toSet)
      val fetch = Fetch.from(repositories, Cache.fetch())
      val resolution = start.process.run(fetch).unsafePerformSync
      val localArtifacts: Seq[File] = Task.gatherUnordered(
        resolution.artifacts.map(Cache.file(_).run)
      ).unsafePerformSync.flatMap(_.toOption)

      localArtifacts.map(p => PathRef(Path(p)))
    }
  }
}
import Subproject._
abstract class Subproject {
  val scalaVersion: T[String]

  val compileDeps: T[Seq[coursier.Dependency]]
  val runDeps: T[Seq[coursier.Dependency]]
  val basePath: T[Path]

  val repositories: T[Seq[Repository]] = T(
    Seq(Cache.ivy2Local, MavenRepository("https://repo1.maven.org/maven2"))
  )

  val compileDepClasspath: T[Seq[PathRef]] = resolveDependencies(
    repositories,
    for((scalaVersion, compileDeps) <- zip(scalaVersion, compileDeps))
    yield compileDeps :+ Dependency(Module("org.scala-lang", "scala-compiler"), scalaVersion)
  )
  val runDepClasspath: T[Seq[PathRef]] = resolveDependencies(
    repositories,
    for((scalaVersion, runDeps) <- zip(scalaVersion, runDeps))
    yield runDeps ++ Seq(
      Dependency(Module("org.scala-lang", "scala-library"), scalaVersion)
    )
  )

  val sources: T[PathRef] = basePath.map(p => PathRef(p / 'src))
  val outputPath: T[Path] = basePath.map(p => p / 'out)
  val resources: T[PathRef] = basePath.map(p => PathRef(p / 'resources))
  val compiledPath: T[Path] = outputPath.map(p => p / 'classpath)
  val compiled: T[PathRef] = compileScala(
    scalaVersion,
    sources,
    compileDepClasspath,
    outputPath
  )
  val classpath: T[Seq[PathRef]] = for((r, c) <- resources.zip(compiled)) yield Seq(r, c)
  val jar: T[PathRef] = createJar(classpath)
}