Skip to content

Commit fabe697

Browse files
committed
Merge pull request #1244 from dotty-staging/add/sbt-phase
Add sbt incremental compilation support
2 parents 5d6cc45 + 4c865c5 commit fabe697

File tree

17 files changed

+1032
-17
lines changed

17 files changed

+1032
-17
lines changed

AUTHORS.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ The majority of the dotty codebase is new code, with the exception of the compon
4242
> The utilities package is a mix of new and adapted components. The files in [scala/scala](https://github.com/scala/scala) were originally authored by many people,
4343
> including Paul Phillips, Martin Odersky, Sean McDirmid, and others.
4444
45-
`dotty.tools.io`
45+
`dotty.tools.io`
4646

4747
> The I/O support library was adapted from current Scala compiler. Original authors were Paul Phillips and others.
4848
@@ -52,3 +52,12 @@ The majority of the dotty codebase is new code, with the exception of the compon
5252
> [scala/scala](https://github.com/scala/scala). It has been reworked to fit
5353
> the needs of dotty. Original authors include: Adrian Moors, Lukas Rytz,
5454
> Grzegorz Kossakowski, Paul Phillips
55+
56+
`dotty.tools.dotc.sbt`
57+
58+
> The sbt compiler phases are based on
59+
> https://github.com/adriaanm/scala/tree/sbt-api-consolidate/src/compiler/scala/tools/sbt
60+
> which attempts to integrate the sbt phases into scalac and is itself based on
61+
> the [compiler bridge in sbt 0.13](https://github.com/sbt/sbt/tree/0.13/compile/interface/src/main/scala/xsbt),
62+
> but has been heavily adapted and refactored.
63+
> Original authors were Mark Harrah, Grzegorz Kossakowski, Martin Duhemm, Adriaan Moors and others.

bin/dotc

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ SCALA_BINARY_VERSION=2.11
2323
SCALA_COMPILER_VERSION=$(getLastStringOnLineWith "scala-compiler")
2424
DOTTY_VERSION=$(getLastStringOnLineWith "version in")
2525
JLINE_VERSION=$(getLastStringOnLineWith "jline")
26+
SBT_VERSION=$(grep "sbt.version=" "$DOTTY_ROOT/project/build.properties" | sed 's/sbt.version=//')
2627
bootcp=true
2728
bootstrapped=false
2829
default_java_opts="-Xmx768m -Xms768m"
@@ -100,13 +101,19 @@ then
100101
JLINE_JAR=$HOME/.ivy2/cache/jline/jline/jars/jline-$JLINE_VERSION.jar
101102
fi
102103

103-
if [ ! -f "$SCALA_LIBRARY_JAR" -o ! -f "$SCALA_REFLECT_JAR" -o ! -f "$SCALA_COMPILER_JAR" -o ! -f "$JLINE_JAR" ]
104+
if [ "$SBT_INTERFACE_JAR" == "" ]
105+
then
106+
SBT_INTERFACE_JAR=$HOME/.ivy2/cache/org.scala-sbt/interface/jars/interface-$SBT_VERSION.jar
107+
fi
108+
109+
if [ ! -f "$SCALA_LIBRARY_JAR" -o ! -f "$SCALA_REFLECT_JAR" -o ! -f "$SCALA_COMPILER_JAR" -o ! -f "$JLINE_JAR" -o ! -f "$SBT_INTERFACE_JAR" ]
104110
then
105111
echo To use this script please set
106112
echo SCALA_LIBRARY_JAR to point to scala-library-$SCALA_VERSION.jar "(currently $SCALA_LIBRARY_JAR)"
107113
echo SCALA_REFLECT_JAR to point to scala-reflect-$SCALA_VERSION.jar "(currently $SCALA_REFLECT_JAR)"
108114
echo SCALA_COMPILER_JAR to point to scala-compiler-$SCALA_VERSION.jar with bcode patches "(currently $SCALA_COMPILER_JAR)"
109115
echo JLINE_JAR to point to jline-$JLINE_VERSION.jar "(currently $JLINE_JAR)"
116+
echo SBT_INTERFACE_JAR to point to interface-$SBT_VERSION.jar "(currently $SBT_INTERFACE_JAR)"
110117
fi
111118

112119
ifdebug () {
@@ -196,9 +203,9 @@ trap onExit INT
196203
classpathArgs () {
197204
if [[ "true" == $bootstrapped ]]; then
198205
checkjar $DOTTY_JAR "test:runMain dotc.build" src
199-
toolchain="$DOTTY_JAR:$SCALA_LIBRARY_JAR:$SCALA_REFLECT_JAR:$SCALA_COMPILER_JAR:$JLINE_JAR"
206+
toolchain="$DOTTY_JAR:$SCALA_LIBRARY_JAR:$SCALA_REFLECT_JAR:$SCALA_COMPILER_JAR:$JLINE_JAR:$SBT_INTERFACE_JAR"
200207
else
201-
toolchain="$SCALA_LIBRARY_JAR:$SCALA_REFLECT_JAR:$SCALA_COMPILER_JAR:$JLINE_JAR"
208+
toolchain="$SCALA_LIBRARY_JAR:$SCALA_REFLECT_JAR:$SCALA_COMPILER_JAR:$JLINE_JAR:$SBT_INTERFACE_JAR"
202209
fi
203210
bcpJars="$INTERFACES_JAR:$MAIN_JAR"
204211
cpJars="$INTERFACES_JAR:$MAIN_JAR:$TEST_JAR"

project/Build.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ object DottyBuild extends Build {
8888
libraryDependencies ++= Seq("org.scala-lang.modules" %% "scala-xml" % "1.0.1",
8989
"org.scala-lang.modules" %% "scala-partest" % "1.0.11" % "test",
9090
"com.novocode" % "junit-interface" % "0.11" % "test",
91-
"jline" % "jline" % "2.12"),
91+
"jline" % "jline" % "2.12",
92+
"org.scala-sbt" % "interface" % sbtVersion.value),
9293

9394
// enable improved incremental compilation algorithm
9495
incOptions := incOptions.value.withNameHashing(true),

src/dotty/tools/backend/jvm/GenBCode.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
389389
val className = jclassName.replace('/', '.')
390390
if (ctx.compilerCallback != null)
391391
ctx.compilerCallback.onClassGenerated(sourceFile, convertAbstractFile(outFile), className)
392+
if (ctx.sbtCallback != null)
393+
ctx.sbtCallback.generatedClass(sourceFile.jfile.orElse(null), outFile.file, className)
392394
}
393395
catch {
394396
case e: FileConflictException =>

src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ class Compiler {
4242
def phases: List[List[Phase]] =
4343
List(
4444
List(new FrontEnd), // Compiler frontend: scanner, parser, namer, typer
45+
List(new sbt.ExtractDependencies), // Sends information on classes' dependencies to sbt via callbacks
4546
List(new PostTyper), // Additional checks and cleanups after type checking
47+
List(new sbt.ExtractAPI), // Sends a representation of the API of classes to sbt via callbacks
4648
List(new Pickler), // Generate TASTY info
4749
List(new FirstTransform, // Some transformations to put trees into a canonical form
4850
new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars

src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ object desugar {
958958
* Example: Given
959959
*
960960
* class C
961-
* type T1 extends C { type T <: A }
961+
* type T1 = C { type T <: A }
962962
*
963963
* the refined type
964964
*

src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,10 @@ object Trees {
559559
type ThisTree[-T >: Untyped] = SingletonTypeTree[T]
560560
}
561561

562-
/** qualifier # name */
562+
/** qualifier # name
563+
* In Scala, this always refers to a type, but in a Java
564+
* compilation unit this might refer to a term.
565+
*/
563566
case class SelectFromTypeTree[-T >: Untyped] private[ast] (qualifier: Tree[T], name: Name)
564567
extends RefTree[T] {
565568
type ThisTree[-T >: Untyped] = SelectFromTypeTree[T]

src/dotty/tools/dotc/config/ScalaSettings.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ class ScalaSettings extends Settings.SettingGroup {
160160
val YtestPickler = BooleanSetting("-Ytest-pickler", "self-test for pickling functionality; should be used with -Ystop-after:pickler")
161161
val YcheckReentrant = BooleanSetting("-Ycheck-reentrant", "check that compiled program does not contain vars that can be accessed from a global root.")
162162
val YkeepComments = BooleanSetting("-Ykeep-comments", "Keep comments when scanning source files.")
163+
val YforceSbtPhases = BooleanSetting("-Yforce-sbt-phases", "Run the phases used by sbt for incremental compilation (ExtractDependencies and ExtractAPI) even if the compiler is ran outside of sbt, for debugging.")
164+
val YdumpSbtInc = BooleanSetting("-Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.")
163165
def stop = YstopAfter
164166

165167
/** Area-specific debug output.

src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import printing._
2929
import config.{Settings, ScalaSettings, Platform, JavaPlatform, SJSPlatform}
3030
import language.implicitConversions
3131
import DenotTransformers.DenotTransformer
32+
import xsbti.AnalysisCallback
3233

3334
object Contexts {
3435

@@ -84,6 +85,12 @@ object Contexts {
8485
_compilerCallback = callback
8586
def compilerCallback: CompilerCallback = _compilerCallback
8687

88+
/** The sbt callback implementation if we are run from sbt, null otherwise */
89+
private[this] var _sbtCallback: AnalysisCallback = _
90+
protected def sbtCallback_=(callback: AnalysisCallback) =
91+
_sbtCallback = callback
92+
def sbtCallback: AnalysisCallback = _sbtCallback
93+
8794
/** The current context */
8895
private[this] var _period: Period = _
8996
protected def period_=(period: Period) = {
@@ -426,6 +433,7 @@ object Contexts {
426433
def setPeriod(period: Period): this.type = { this.period = period; this }
427434
def setMode(mode: Mode): this.type = { this.mode = mode; this }
428435
def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
436+
def setSbtCallback(callback: AnalysisCallback): this.type = { this.sbtCallback = callback; this }
429437
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
430438
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.withReporter(reporter))
431439
def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ object SymDenotations {
868868
*/
869869
final def topLevelClass(implicit ctx: Context): Symbol = {
870870
def topLevel(d: SymDenotation): Symbol = {
871-
if ((d is PackageClass) || (d.owner is PackageClass)) d.symbol
871+
if (d.isEffectiveRoot || (d is PackageClass) || (d.owner is PackageClass)) d.symbol
872872
else topLevel(d.owner)
873873
}
874874
val sym = topLevel(this)

src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ object Symbols {
519519

520520
/** The source or class file from which this class was generated, null if not applicable. */
521521
override def associatedFile(implicit ctx: Context): AbstractFile =
522-
if (assocFile != null || (this.owner is PackageClass)) assocFile
522+
if (assocFile != null || (this.owner is PackageClass) || this.isEffectiveRoot) assocFile
523523
else super.associatedFile
524524

525525
final def classDenot(implicit ctx: Context): ClassDenotation =

src/dotty/tools/dotc/core/Types.scala

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,16 @@ object Types {
415415
memberExcluding(name, Flags.Private)
416416
}
417417

418-
final def memberExcluding(name: Name, excluding: FlagSet)(implicit ctx: Context): Denotation =
419-
findMember(name, widenIfUnstable, excluding)
418+
final def memberExcluding(name: Name, excluding: FlagSet)(implicit ctx: Context): Denotation = {
419+
// We need a valid prefix for `asSeenFrom`
420+
val pre = this match {
421+
case tp: ClassInfo =>
422+
tp.typeRef
423+
case _ =>
424+
widenIfUnstable
425+
}
426+
findMember(name, pre, excluding)
427+
}
420428

421429
/** Find member of this type with given name and
422430
* produce a denotation that contains the type of the member
@@ -2476,10 +2484,14 @@ object Types {
24762484

24772485
abstract class ParamType extends BoundType {
24782486
def paramNum: Int
2487+
def paramName: Name
24792488
}
24802489

24812490
abstract case class MethodParam(binder: MethodType, paramNum: Int) extends ParamType with SingletonType {
24822491
type BT = MethodType
2492+
2493+
def paramName = binder.paramNames(paramNum)
2494+
24832495
override def underlying(implicit ctx: Context): Type = binder.paramTypes(paramNum)
24842496
def copyBoundType(bt: BT) = new MethodParamImpl(bt, paramNum)
24852497

@@ -2492,7 +2504,7 @@ object Types {
24922504
false
24932505
}
24942506

2495-
override def toString = s"MethodParam(${binder.paramNames(paramNum)})"
2507+
override def toString = s"MethodParam($paramName)"
24962508
}
24972509

24982510
class MethodParamImpl(binder: MethodType, paramNum: Int) extends MethodParam(binder, paramNum)
@@ -2522,9 +2534,11 @@ object Types {
25222534
case _ => false
25232535
}
25242536

2537+
def paramName = binder.paramNames(paramNum)
2538+
25252539
override def underlying(implicit ctx: Context): Type = binder.paramBounds(paramNum)
25262540
// no customized hashCode/equals needed because cycle is broken in PolyType
2527-
override def toString = s"PolyParam(${binder.paramNames(paramNum)})"
2541+
override def toString = s"PolyParam($paramName)"
25282542

25292543
override def computeHash = doHash(paramNum, binder.identityHash)
25302544

@@ -2776,9 +2790,9 @@ object Types {
27762790
if ((prefix eq cls.owner.thisType) || !cls.owner.isClass || ctx.erasedTypes) tp
27772791
else tp.substThis(cls.owner.asClass, prefix)
27782792

2779-
private var typeRefCache: Type = null
2793+
private var typeRefCache: TypeRef = null
27802794

2781-
def typeRef(implicit ctx: Context): Type = {
2795+
def typeRef(implicit ctx: Context): TypeRef = {
27822796
def clsDenot = if (prefix eq cls.owner.thisType) cls.denot else cls.denot.copySymDenotation(info = this)
27832797
if (typeRefCache == null)
27842798
typeRefCache =
@@ -2787,7 +2801,7 @@ object Types {
27872801
typeRefCache
27882802
}
27892803

2790-
def symbolicTypeRef(implicit ctx: Context): Type = TypeRef(prefix, cls)
2804+
def symbolicTypeRef(implicit ctx: Context): TypeRef = TypeRef(prefix, cls)
27912805

27922806
// cached because baseType needs parents
27932807
private var parentsCache: List[TypeRef] = null
@@ -3400,6 +3414,12 @@ object Types {
34003414
}
34013415
}
34023416

3417+
abstract class TypeTraverser(implicit ctx: Context) extends TypeAccumulator[Unit] {
3418+
def traverse(tp: Type): Unit
3419+
def apply(x: Unit, tp: Type): Unit = traverse(tp)
3420+
protected def traverseChildren(tp: Type) = foldOver((), tp)
3421+
}
3422+
34033423
class ExistsAccumulator(p: Type => Boolean)(implicit ctx: Context) extends TypeAccumulator[Boolean] {
34043424
override def stopAtStatic = false
34053425
def apply(x: Boolean, tp: Type) = x || p(tp) || foldOver(x, tp)

0 commit comments

Comments
 (0)