diff options
author | Jan Christopher Vogt <oss.nsp@cvogt.org> | 2016-09-28 21:29:26 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-09-28 21:29:26 -0400 |
commit | 9d3c9e9087a6dc0a4445f9428e02f6e7612470c6 (patch) | |
tree | ab1aef0726e71ff1ad760b6574489dc20b2d1950 /stage2 | |
parent | ab5ebf2577146b6d8e7c54db4d6bf9ba6230ab57 (diff) | |
parent | 9b4b9e0c7a747972229fe9dbabe4b6e546c29f4d (diff) | |
download | cbt-9d3c9e9087a6dc0a4445f9428e02f6e7612470c6.tar.gz cbt-9d3c9e9087a6dc0a4445f9428e02f6e7612470c6.tar.bz2 cbt-9d3c9e9087a6dc0a4445f9428e02f6e7612470c6.zip |
Merge pull request #235 from cvogt/dotty
Dotty plugin and example project.
Diffstat (limited to 'stage2')
-rw-r--r-- | stage2/plugins/Dotty.scala | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/stage2/plugins/Dotty.scala b/stage2/plugins/Dotty.scala new file mode 100644 index 0000000..50255d5 --- /dev/null +++ b/stage2/plugins/Dotty.scala @@ -0,0 +1,172 @@ +package cbt +import java.io.File +import java.net.URL +import java.nio.file.Files +import java.nio.file.attribute.FileTime + +trait Dotty extends BaseBuild{ + def dottyVersion: String = "0.1-20160926-ec28ea1-NIGHTLY" + def dottyOptions: Seq[String] = Seq() + override def scalaTarget: File = target ++ s"/dotty-$dottyVersion" + + private lazy val dottyLib = new DottyLib( + logger, context.cbtHasChanged, context.paths.mavenCache, + context.classLoaderCache, dottyVersion = dottyVersion + ) + + private object compileCache extends Cache[Option[File]] + override def compile: Option[File] = compileCache{ + dottyLib.compile( + needsUpdate || context.parentBuild.map(_.needsUpdate).getOrElse(false), + sourceFiles, compileTarget, compileStatusFile, compileClasspath, + dottyOptions + ) + } + + def doc: ExitCode = + dottyLib.doc( + sourceFiles, compileClasspath, docTarget, dottyOptions + ) + + def repl = dottyLib.repl(context.args, classpath) + + override def dependencies = Resolver(mavenCentral).bind( + ScalaDependency( "org.scala-lang.modules", "scala-java8-compat", "0.8.0-RC7" ) + ) +} + +class DottyLib( + logger: Logger, + cbtHasChanged: Boolean, + mavenCache: File, + classLoaderCache: ClassLoaderCache, + dottyVersion: String +){ + val lib = new Lib(logger) + import lib._ + + private def Resolver(urls: URL*) = MavenResolver(cbtHasChanged, mavenCache, urls: _*) + private lazy val dottyDependency = Resolver(mavenCentral).bindOne( + MavenDependency("ch.epfl.lamp","dotty_2.11",dottyVersion) + ) + + def repl(args: Seq[String], classpath: ClassPath) = { + consoleOrFail("Use `cbt direct repl` instead") + lib.runMain( + "dotty.tools.dotc.repl.Main", + Seq( + "-bootclasspath", + dottyDependency.classpath.string, + "-classpath", + classpath.string + ) ++ args, + dottyDependency.classLoader(classLoaderCache) + ) + } + + def doc( + sourceFiles: Seq[File], + dependencyClasspath: ClassPath, + docTarget: File, + compileArgs: Seq[String] + ): ExitCode = { + if(sourceFiles.isEmpty){ + ExitCode.Success + } else { + docTarget.mkdirs + val args = Seq( + // FIXME: can we use compiler dependency here? + "-bootclasspath", dottyDependency.classpath.string, // FIXME: does this break for builds that don't have scalac dependencies? + "-classpath", dependencyClasspath.string, // FIXME: does this break for builds that don't have scalac dependencies? + "-d", docTarget.toString + ) ++ compileArgs ++ sourceFiles.map(_.toString) + logger.lib("creating docs for source files "+args.mkString(", ")) + val exitCode = redirectOutToErr{ + runMain( + "dotty.tools.dottydoc.api.java.Dottydoc", + args, + dottyDependency.classLoader(classLoaderCache), + fakeInstance = true // this is a hack as Dottydoc's main method is not static + ) + } + System.err.println("done") + exitCode + } + } + + def compile( + needsRecompile: Boolean, + files: Seq[File], + compileTarget: File, + statusFile: File, + classpath: ClassPath, + dottyOptions: Seq[String] + ): Option[File] = { + + if(classpath.files.isEmpty) + throw new Exception("Trying to compile with empty classpath. Source files: " ++ files.toString) + + if( files.isEmpty ){ + None + }else{ + if( needsRecompile ){ + val start = System.currentTimeMillis + + val _class = "dotty.tools.dotc.Main" + val dualArgs = + Seq( + "-d", compileTarget.toString + ) + val singleArgs = dottyOptions.map( "-S" ++ _ ) + + val code = + try{ + System.err.println("Compiling with Dotty to " ++ compileTarget.toString) + compileTarget.mkdirs + redirectOutToErr{ + lib.runMain( + _class, + dualArgs ++ singleArgs ++ Seq( + "-bootclasspath", dottyDependency.classpath.string, // let's put cp last. It so long + "-classpath", classpath.string // let's put cp last. It so long + ) ++ files.map(_.toString), + dottyDependency.classLoader(classLoaderCache) + ) + } + } catch { + case e: Exception => + System.err.println(red("Dotty crashed. See https://github.com/lampepfl/dotty/issues. To reproduce run:")) + System.out.println(s""" +java -cp \\ +${dottyDependency.classpath.strings.mkString(":\\\n")} \\ +\\ +${_class} \\ +\\ +${dualArgs.grouped(2).map(_.mkString(" ")).mkString(" \\\n")} \\ +\\ +${singleArgs.mkString(" \\\n")} \\ +\\ +-bootclasspath \\ +${dottyDependency.classpath.strings.mkString(":\\\n")} \\ +-classpath \\ +${classpath.strings.mkString(":\\\n")} \\ +\\ +${files.sorted.mkString(" \\\n")} +""" + ) + ExitCode.Failure + } + + if(code == ExitCode.Success){ + // write version and when last compilation started so we can trigger + // recompile if cbt version changed or newer source files are seen + write(statusFile, "")//cbtVersion.getBytes) + Files.setLastModifiedTime(statusFile.toPath, FileTime.fromMillis(start) ) + } else { + System.exit(code.integer) // FIXME: let's find a better solution for error handling. Maybe a monad after all. + } + } + Some( compileTarget ) + } + } +} |