mirror of https://github.com/sbt/sbt.git
Enable name hashing incremental compilation by default.
This commit changes the default value of `IncOptions.nameHashing` to be set to true. It means, the improved incremental compilation algorithm known as "name hashing" will be enabled by default. In order to disable it, users should add this to their sbt configuration: incOptions := incOptions.value.withNameHashing(false) Number of tests has been cleaned up as part of this change. All tests that were marked as name hashing specific are removed. The list includes: * constants-name-hashing * import-class-name-hashing * java-static-name-hashing * macro-name-hashing * struct-name-hashing We'll keep just regular version of those tests. The tests will just exercise the default algorithm: name hashing. This is the first step towards phasing out of the old incremental compilation algorithm. Apart from that, a few tests changed its status due to enabling name hashing algorithm. The `constants` test has been marked pending due to issue described in #1543. The `import-class` test has been marked as passing because name hashing tracks dependencies introduced by import statements correctly, now. The `macro` test has been marked as pending due to issue described in #1544. The `struct` test has been marked as pending due to issue described in #1545. The `java-static` has been slightly modified to exercise just static field and not run into the same issue as with `constants` test. There are no other known issues related to name hashing so we conclude that name hashing is ready to be shipped to all sbt, Scala IDE and zinc users.
This commit is contained in:
parent
b202bd6848
commit
c440c578fc
|
|
@ -217,7 +217,7 @@ final class IncOptions(
|
|||
|
||||
object IncOptions extends Serializable {
|
||||
private val recompileOnMacroDefDefault: Boolean = true
|
||||
private val nameHashingDefault: Boolean = false
|
||||
private val nameHashingDefault: Boolean = true
|
||||
private val antStyleDefault: Boolean = false
|
||||
val Default = IncOptions(
|
||||
// 1. recompile changed sources
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
incOptions := incOptions.value.withNameHashing(true)
|
||||
|
|
@ -1 +0,0 @@
|
|||
object A { final val x = 1 }
|
||||
|
|
@ -1 +0,0 @@
|
|||
object A { final val x = 2 }
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
object B
|
||||
{
|
||||
def main(args: Array[String]) = assert(args(0).toInt == A.x )
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
# Marked as pending, see https://github.com/sbt/sbt/issues/1543
|
||||
#
|
||||
# Tests if source dependencies are tracked properly
|
||||
# for compile-time constants (like final vals in top-level objects)
|
||||
# see https://issues.scala-lang.org/browse/SI-7173 for details
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
# Tests if source dependencies are tracked properly
|
||||
# for compile-time constants (like final vals in top-level objects)
|
||||
# see https://issues.scala-lang.org/browse/SI-7173 for details
|
||||
# why compile-time constants can be tricky to track due to early inlining
|
||||
|
||||
$ copy-file changes/B.scala B.scala
|
||||
|
||||
$ copy-file changes/A1.scala A.scala
|
||||
> run 1
|
||||
$ copy-file changes/A2.scala A.scala
|
||||
> run 2
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
package a
|
||||
|
||||
class A
|
||||
|
|
@ -1 +0,0 @@
|
|||
import a.A
|
||||
|
|
@ -1 +0,0 @@
|
|||
incOptions := incOptions.value.withNameHashing(true)
|
||||
|
|
@ -1 +0,0 @@
|
|||
package a
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
> compile
|
||||
|
||||
# remove class a.A
|
||||
$ copy-file changes/A.scala A.scala
|
||||
|
||||
# 'import a.A' should now fail in B.scala
|
||||
# succeeds because scalac doesn't track this dependency
|
||||
-> compile
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
// this test is specific to the old incremental compilation algorithm
|
||||
incOptions := incOptions.value.withNameHashing(false)
|
||||
|
||||
lazy val verifyDeps = taskKey[Unit]("verify inherited dependencies are properly extracted")
|
||||
|
||||
verifyDeps := {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// this test is specific to the old incremental compilation algorithm
|
||||
incOptions := incOptions.value.withNameHashing(false)
|
||||
|
||||
lazy val verifyDeps = taskKey[Unit]("verify inherited dependencies are properly extracted")
|
||||
|
||||
verifyDeps := {
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
incOptions := incOptions.value.withNameHashing(true)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
public class J
|
||||
{
|
||||
public static final int x = 3;
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
public class J
|
||||
{
|
||||
public static final String x = "3";
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
object S
|
||||
{
|
||||
val y: Int = J.x
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
# When a Java class is loaded from a class file and not parsed from a source file, scalac reports
|
||||
# the statics as an object without a file and so the Analyzer must know to look for the
|
||||
# object's linked class.
|
||||
# This test verifies this happens.
|
||||
# The test compiles a Java class with a static field.
|
||||
# It then adds a Scala object that references the static field. Because the object only depends on a
|
||||
# static member and because the Java source is not included in the compilation (since it didn't change),
|
||||
# this triggers the special case above.
|
||||
|
||||
# add and compile the Java source
|
||||
$ copy-file changes/J1.java src/main/java/J.java
|
||||
> compile
|
||||
|
||||
# add and compile the Scala source
|
||||
$ copy-file changes/S.scala src/main/scala/S.scala
|
||||
> compile
|
||||
|
||||
# change the Java source so that a compile error should occur if S.scala is also recompiled (which will happen if the dependency was properly recorded)
|
||||
$ copy-file changes/J2.java src/main/java/J.java
|
||||
-> compile
|
||||
|
||||
# verify it should have failed by doing a full recompilation
|
||||
> clean
|
||||
-> compile
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
public class J
|
||||
{
|
||||
public static final int x = 3;
|
||||
public static final Integer x = 3;
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package macro
|
||||
|
||||
object Client {
|
||||
Provider.tree(0)
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package macro
|
||||
import scala.language.experimental.macros
|
||||
import scala.reflect.macros._
|
||||
|
||||
object Provider {
|
||||
def tree(args: Any) = macro treeImpl
|
||||
def treeImpl(c: Context)(args: c.Expr[Any]) = c.universe.reify(args.splice)
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
package macro
|
||||
import scala.language.experimental.macros
|
||||
import scala.reflect.macros._
|
||||
|
||||
object Provider {
|
||||
def tree(args: Any) = macro treeImpl
|
||||
def treeImpl(c: Context)(args: c.Expr[Any]) = sys.error("no macro for you!")
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import sbt._
|
||||
import Keys._
|
||||
|
||||
object build extends Build {
|
||||
val defaultSettings = Seq(
|
||||
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-reflect" % _ ),
|
||||
incOptions := incOptions.value.withNameHashing(true)
|
||||
)
|
||||
|
||||
lazy val root = Project(
|
||||
base = file("."),
|
||||
id = "macro",
|
||||
aggregate = Seq(macroProvider, macroClient),
|
||||
settings = Defaults.defaultSettings ++ defaultSettings
|
||||
)
|
||||
|
||||
lazy val macroProvider = Project(
|
||||
base = file("macro-provider"),
|
||||
id = "macro-provider",
|
||||
settings = Defaults.defaultSettings ++ defaultSettings
|
||||
)
|
||||
|
||||
lazy val macroClient = Project(
|
||||
base = file("macro-client"),
|
||||
id = "macro-client",
|
||||
dependencies = Seq(macroProvider),
|
||||
settings = Defaults.defaultSettings ++ defaultSettings
|
||||
)
|
||||
}
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
# Marked as pending due to StackOverflow error, see
|
||||
# https://github.com/sbt/sbt/issues/1544 for details
|
||||
|
||||
> compile
|
||||
|
||||
# replace macro with one that throws an error
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
> compile
|
||||
|
||||
# replace macro with one that throws an error
|
||||
|
||||
$ copy-file macro-provider/changes/Provider.scala macro-provider/Provider.scala
|
||||
|
||||
> macro-provider/compile
|
||||
|
||||
-> macro-client/compile
|
||||
|
||||
> clean
|
||||
|
||||
-> compile
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
object A {
|
||||
def x: Int = 3
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
object B {
|
||||
def onX(m: { def x: Int } ) =
|
||||
m.x
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
object C {
|
||||
def main(args: Array[String]) =
|
||||
println(B.onX(A))
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
incOptions := incOptions.value.withNameHashing(true)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
object A {
|
||||
def x: Byte = 3
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
> compile
|
||||
|
||||
# modify A.scala so that it does not conform to the structural type in B.scala
|
||||
$ copy-file changes/A.scala A.scala
|
||||
|
||||
-> compile
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Marked as pending because name hashing doesn't support structural types
|
||||
# in some cases. See: https://github.com/sbt/sbt/issues/1545
|
||||
|
||||
> compile
|
||||
|
||||
# modify A.scala so that it does not conform to the structural type in B.scala
|
||||
$ copy-file changes/A.scala A.scala
|
||||
|
||||
-> compile
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
> compile
|
||||
|
||||
# modify A.scala so that it does not conform to the structural type in B.scala
|
||||
$ copy-file changes/A.scala A.scala
|
||||
|
||||
-> compile
|
||||
Loading…
Reference in New Issue