Skip to content

Commit

Permalink
Add Dotty support
Browse files Browse the repository at this point in the history
  • Loading branch information
jvican authored and Duhemm committed May 1, 2018
1 parent cc15fd0 commit 03fccd8
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 4 deletions.
6 changes: 5 additions & 1 deletion backend/src/main/scala/bloop/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import xsbti.T2
import java.util.Optional
import java.io.File

import bloop.internal.Ecosystem
import bloop.io.{AbsolutePath, Paths}
import bloop.logging.Logger
import bloop.reporter.Reporter
Expand Down Expand Up @@ -75,7 +76,10 @@ object Compiler {
val reporter = compileInputs.reporter
val compilerCache = new FreshCompilerCache
val cacheFile = compileInputs.baseDirectory.resolve("cache").toFile
val incOptions = IncOptions.create()
val incOptions = {
if (!compileInputs.scalaInstance.isDotty) IncOptions.create()
else Ecosystem.supportDotty(IncOptions.create())
}
val progress = Optional.empty[CompileProgress]
Setup.create(lookup, skip, cacheFile, compilerCache, incOptions, reporter, progress, empty)
}
Expand Down
6 changes: 5 additions & 1 deletion backend/src/main/scala/bloop/ScalaInstance.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ScalaInstance(

private def isJar(filename: String): Boolean = filename.endsWith(".jar")
private def hasScalaCompilerName(filename: String): Boolean =
filename.startsWith("scala-compiler")
if (isDotty) filename.startsWith("dotty-compiler") else filename.startsWith("scala-compiler")
private def hasScalaLibraryName(filename: String): Boolean =
filename.startsWith("scala-library")

Expand All @@ -33,6 +33,10 @@ class ScalaInstance(
isJar(filename) && !hasScalaCompilerName(filename) && !hasScalaLibraryName(filename)
}

/** Is this `ScalaInstance` using Dotty? */
def isDotty: Boolean =
organization == "ch.epfl.lamp" && sbt.internal.inc.ScalaInstance.isDotty(version)

/** Tells us what the real version of the classloaded scalac compiler in this instance is. */
override def actualVersion(): String = {
// TODO: Report when the `actualVersion` and the passed in version do not match.
Expand Down
45 changes: 45 additions & 0 deletions backend/src/main/scala/bloop/internal/Ecosystem.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package bloop.internal

import java.io.File
import java.util.Optional

import xsbti.compile.{
ClassFileManager,
ClassFileManagerUtil,
DefaultExternalHooks,
IncOptions,
WrappedClassFileManager
}

object Ecosystem {
def supportDotty(incOptions: IncOptions): IncOptions = {
val tastyFileManager = new ClassFileManager {
private[this] val inherited = ClassFileManagerUtil.getDefaultClassFileManager(incOptions)

def delete(classes: Array[File]): Unit = {
val tastySuffixes = List(".tasty", ".hasTasty")
inherited.delete(classes flatMap { classFile =>
if (classFile.getPath endsWith ".class") {
val prefix = classFile.getAbsolutePath.stripSuffix(".class")
tastySuffixes.map(suffix => new File(prefix + suffix)).filter(_.exists)
} else Nil
})
}

def generated(classes: Array[File]): Unit = {}
def complete(success: Boolean): Unit = {}
}
val inheritedHooks = incOptions.externalHooks
val externalClassFileManager: Optional[ClassFileManager] = Option(
inheritedHooks.getExternalClassFileManager.orElse(null)) match {
case Some(prevManager) =>
Optional.of(WrappedClassFileManager.of(prevManager, Optional.of(tastyFileManager)))
case None =>
Optional.of(tastyFileManager)
}

val newExternalHooks =
new DefaultExternalHooks(inheritedHooks.getExternalLookup, externalClassFileManager)
incOptions.withExternalHooks(newExternalHooks)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ object ZincInternals {
def compilerBridgeId(scalaVersion: String) = {
// Defaults to bridge for 2.13 for Scala versions bigger than 2.13.x
scalaVersion match {
case sc if (sc startsWith "0.") => "dotty-sbt-bridge"
case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10"
case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11"
case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12"
case _ => "compiler-bridge_2.13"
case _ => "compiler-bridge_2.13"
}
}

val organization = if (scalaInstance.isDotty) scalaInstance.organization else "ch.epfl.scala"
val bridgeId = compilerBridgeId(scalaInstance.version)
ModuleID("ch.epfl.scala", bridgeId, latestVersion).withConfigurations(CompileConf).sources()
val version = if (scalaInstance.isDotty) scalaInstance.version else latestVersion

ModuleID(organization, bridgeId, version).withConfigurations(CompileConf).sources()
}

/**
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/test/scala/bloop/tasks/CompilationTaskTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class CompilationTaskTest {
val `B2.scala` = "package p1\ntrait B"
val `C.scala` = "package p2\nimport p0.A\nimport p1.B\nobject C extends A with B"
val `C2.scala` = "package p2\nimport p0.A\nobject C extends A"
val `Dotty.scala` = "package p0\nobject Foo { val x: String | Int = 1 }"
}

@Test
Expand Down Expand Up @@ -232,4 +233,16 @@ class CompilationTaskTest {
assert(msgs.exists(m => m._1 == "warn" && m._2.contains(targetMsg)))
}
}

@Test
def compileWithDotty080RC1: Unit = {
val logger = new RecordingLogger()
val scalaInstance =
ScalaInstance.resolve("ch.epfl.lamp", "dotty-compiler_0.8", "0.8.0-RC1", logger)
val structures = Map(RootProject -> Map("Dotty.scala" -> ArtificialSources.`Dotty.scala`))
checkAfterCleanCompilation(structures, Map.empty, scalaInstance = scalaInstance) { state =>
val projects = state.build.projects
assert(projects.forall(p => hasPreviousResult(p, state)))
}
}
}

0 comments on commit 03fccd8

Please sign in to comment.