Merge branch '0.13.10' into wip/0.13.10-merge

This commit is contained in:
Eugene Yokota 2016-02-22 13:19:38 -05:00
commit 2fe5eabd6e
41 changed files with 405 additions and 198 deletions

View File

@ -7,7 +7,7 @@ import Sxr.sxr
// but can be shared across the multi projects.
def buildLevelSettings: Seq[Setting[_]] = inThisBuild(Seq(
organization := "org.scala-sbt",
version := "0.13.10-SNAPSHOT",
version := "0.13.11-SNAPSHOT",
bintrayOrganization := Some(if (publishStatus.value == "releases") "typesafe" else "sbt"),
bintrayRepository := s"ivy-${publishStatus.value}",
bintrayPackage := "sbt",

View File

@ -261,7 +261,7 @@ object ClassToAPI {
def modifiers(i: Int): api.Modifiers =
{
import Modifier.{ isAbstract, isFinal }
new api.Modifiers(isAbstract(i), false, isFinal(i), false, false, false, false)
new api.Modifiers(isAbstract(i), false, isFinal(i), false, false, false, false, false)
}
def access(i: Int, pkg: Option[String]): api.Access =
{

View File

@ -12,7 +12,7 @@ object APIUtil {
}
val byteToModifiers = (b: Byte) => {
def x(bit: Int) = (b & (1 << bit)) != 0
new Modifiers(x(0), x(1), x(2), x(3), x(4), x(5), x(6))
new Modifiers(x(0), x(1), x(2), x(3), x(4), x(5), x(6), x(7))
}
def isScalaSourceName(name: String): Boolean = name.endsWith(".scala")

View File

@ -139,16 +139,37 @@ final class HashAPI(includePrivate: Boolean, includeParamNames: Boolean, include
{
hash = startHash(0)
hashSymmetric(s.packages, hashPackage)
hashDefinitions(s.definitions, true)
hashDefinitions(s.definitions, topLevel = true, isTrait = false)
finalizeHash
}
def hashPackage(p: Package) = hashString(p.name)
@deprecated("Use the overload that indicates if the enclosing definition is a trait.", "0.14")
def hashDefinitions(ds: Seq[Definition], topLevel: Boolean): Unit =
hashDefinitions(ds, topLevel, isTrait = false)
def hashDefinitions(ds: Seq[Definition], topLevel: Boolean, isTrait: Boolean): Unit =
{
def isPublic(d: Definition): Boolean = d.access match { case _: xsbti.api.Public => true; case _ => false }
def isTraitBreaker(d: Definition): Boolean = d match {
// Vars and vals in traits introduce getters, setters and fields in the implementing classes.
// See test `source-dependencies/trait-private-var
case _: FieldLike => true
// Objects in traits introduce fields in the implementing classes.
// See test `source-dependencies/trait-private-object`
case cl: ClassLike => cl.definitionType == DefinitionType.Module
// super calls introduce accessors that are not part of the public API
case d: Def => d.modifiers.isSuperAccessor
case _ => false
}
val includedPrivateDefinitions =
if (!includePrivate && !topLevel && isTrait) {
ds filter (x => isTraitBreaker(x) && !isPublic(x))
} else Seq.empty
val defs = SameAPI.filterDefinitions(ds, topLevel, includePrivate)
hashSymmetric(defs, hashDefinition)
hashSymmetric(includedPrivateDefinitions ++ defs, hashDefinition)
}
/**
@ -356,9 +377,9 @@ final class HashAPI(includePrivate: Boolean, includeParamNames: Boolean, include
def hashStructure0(structure: Structure, includeDefinitions: Boolean, isTrait: Boolean = false): Unit = {
extend(StructureHash)
hashTypes(structure.parents, includeDefinitions)
if (includeDefinitions || isTrait) {
hashDefinitions(structure.declared, isTrait)
hashDefinitions(structure.inherited, isTrait)
if (includeDefinitions) {
hashDefinitions(structure.declared, topLevel = false, isTrait)
hashDefinitions(structure.inherited, topLevel = false, isTrait)
}
}
def hashParameters(parameters: Seq[TypeParameter], base: Type): Unit =

View File

@ -165,20 +165,39 @@ class NameHashingSpecification extends Specification {
}
/**
* Checks that private members are included in the hash of the public API of traits.
* Including the private members of traits is required because classes that implement a trait
* have to define the private members of the trait. Therefore, if a private member of a trait is added,
* modified or removed we need to recompile the classes that implement this trait.
* Checks that private vars are included in the hash of the public API of traits.
* Including the private vars of traits is required because classes that implement a trait
* have to define getters and setters for these vars.
* For instance, if trait Foo is initially defined as:
* trait Foo { private val x = new A }
* trait Foo { private var x = new A }
* changing it to
* trait Foo { private val x = new B }
* trait Foo { private var x = new B }
* requires us to recompile all implementors of trait Foo, because scalac generates setters and getters
* for the private fields of trait Foo in its implementor. If the clients of trait Foo are not recompiled,
* for the private vars of trait Foo in its implementor. If the clients of trait Foo are not recompiled,
* we get abstract method errors at runtime, because the types expected by the setter (for instance) does not
* match.
*/
"private members in traits" in {
"private var in traits are included in API hash" in {
/* trait Foo { private var x } */
val fooTrait1 =
simpleTrait("Foo",
simpleStructure(new Var(emptyType, "x", privateAccess, defaultModifiers, Array.empty)),
publicAccess)
/* trait Foo */
val fooTrait2 =
simpleTrait("Foo",
simpleStructure(),
publicAccess)
val api1 = new SourceAPI(Array.empty, Array(fooTrait1))
val api2 = new SourceAPI(Array.empty, Array(fooTrait2))
HashAPI(api1) !== HashAPI(api2)
}
"private vals in traits are included in API hash" in {
/* trait Foo { private val x } */
val fooTrait1 =
simpleTrait("Foo",
@ -198,15 +217,97 @@ class NameHashingSpecification extends Specification {
}
"private objects in traits are included in API hash" in {
/* trait Foo { private object x } */
val fooTrait1 =
simpleTrait("Foo",
simpleStructure(
new ClassLike(DefinitionType.Module, lzy(emptyType), lzy(simpleStructure()), Array.empty, Array.empty, "x", privateAccess, defaultModifiers, Array.empty)),
publicAccess)
/* trait Foo */
val fooTrait2 =
simpleTrait("Foo",
simpleStructure(),
publicAccess)
val api1 = new SourceAPI(Array.empty, Array(fooTrait1))
val api2 = new SourceAPI(Array.empty, Array(fooTrait2))
HashAPI(api1) !== HashAPI(api2)
}
"private non-synthetic def in traits are not included in API hash" in {
/* trait Foo { private def x } */
val fooTrait1 =
simpleTrait("Foo",
simpleStructure(new Def(Array.empty, emptyType, Array.empty, "x", privateAccess, defaultModifiers, Array.empty)),
publicAccess)
/* trait Foo */
val fooTrait2 =
simpleTrait("Foo",
simpleStructure(),
publicAccess)
val api1 = new SourceAPI(Array.empty, Array(fooTrait1))
val api2 = new SourceAPI(Array.empty, Array(fooTrait2))
HashAPI(api1) === HashAPI(api2)
}
"private synthetic def in traits are included in API hash" in {
/* trait Foo { private <superaccessor> def x } */
val modifiers = new xsbti.api.Modifiers(false, false, false, false, false, false, false, true)
val fooTrait1 =
simpleTrait("Foo",
simpleStructure(new Def(Array.empty, emptyType, Array.empty, "x", privateAccess, modifiers, Array.empty)),
publicAccess)
/* trait Foo */
val fooTrait2 =
simpleTrait("Foo",
simpleStructure(),
publicAccess)
val api1 = new SourceAPI(Array.empty, Array(fooTrait1))
val api2 = new SourceAPI(Array.empty, Array(fooTrait2))
HashAPI(api1) !== HashAPI(api2)
}
"private types in traits are included not in API hash" in {
/* trait Foo { private type x } */
val fooTrait1 =
simpleTrait("Foo",
simpleStructure(new TypeAlias(emptyType, Array.empty, "x", privateAccess, defaultModifiers, Array.empty)),
publicAccess)
/* trait Foo */
val fooTrait2 =
simpleTrait("Foo",
simpleStructure(),
publicAccess)
val api1 = new SourceAPI(Array.empty, Array(fooTrait1))
val api2 = new SourceAPI(Array.empty, Array(fooTrait2))
HashAPI(api1) === HashAPI(api2)
}
/**
* Checks that private members in non-top-level traits are included as well.
* Checks that private vars in non-top-level traits are included as well.
*/
"private members in nested traits" in {
/* class A { trait Foo { private val x } } */
"private variables in nested traits are include in the API hash" in {
/* class A { trait Foo { private var x } } */
val classA1 =
simpleClass("A",
simpleTrait("Foo",
simpleStructure(new Val(emptyType, "x", privateAccess, defaultModifiers, Array.empty)),
simpleStructure(new Var(emptyType, "x", privateAccess, defaultModifiers, Array.empty)),
publicAccess))
/* class A { trait Foo } */
@ -226,12 +327,12 @@ class NameHashingSpecification extends Specification {
/**
* Checks that private traits are NOT included in the hash.
*/
"private traits" in {
/* class Foo { private trait T { private val x } } */
"private inner traits are not included in the API hash" in {
/* class Foo { private trait T { private var x } } */
val classFoo1 =
simpleClass("Foo",
simpleTrait("T",
simpleStructure(new Val(emptyType, "x", privateAccess, defaultModifiers, Array.empty)),
simpleStructure(new Var(emptyType, "x", privateAccess, defaultModifiers, Array.empty)),
privateAccess))
/** class Foo { private trait T } */
@ -256,10 +357,10 @@ class NameHashingSpecification extends Specification {
* Checks that private members are NOT included in the hash of the public API of classes.
*/
"private members in classes are not included in the api hash" in {
/* class Foo { private val x } */
/* class Foo { private var x } */
val classFoo1 =
simpleClass("Foo",
simpleStructure(new Val(emptyType, "x", privateAccess, defaultModifiers, Array.empty)))
simpleStructure(new Var(emptyType, "x", privateAccess, defaultModifiers, Array.empty)))
/* class Foo */
val classFoo2 =
@ -274,9 +375,9 @@ class NameHashingSpecification extends Specification {
}
/**
* Checks that private members do NOT contribute to name hashes.
* Test for https://github.com/sbt/sbt/issues/2324
*/
* Checks that private members do NOT contribute to name hashes.
* Test for https://github.com/sbt/sbt/issues/2324
*/
"private members in classes do not contribute to name hashes" in {
/* class Foo { private val x } */
val classFoo =
@ -336,6 +437,6 @@ class NameHashingSpecification extends Specification {
private val strTpe = new Projection(emptyType, "String")
private val publicAccess = new Public
private val privateAccess = new Private(new Unqualified)
private val defaultModifiers = new Modifiers(false, false, false, false, false, false, false)
private val defaultModifiers = new Modifiers(false, false, false, false, false, false, false, false)
}

View File

@ -76,7 +76,7 @@ object TestCaseGenerators {
private[this] def makeDefinition(name: String): Definition =
new ClassLike(DefinitionType.ClassDef, lzy(new EmptyType()),
lzy(new Structure(lzy(Array()), lzy(Array()), lzy(Array()))), Array(), Array(),
name, new Public(), new Modifiers(false, false, false, false, false, false, false), Array())
name, new Public(), new Modifiers(false, false, false, false, false, false, false, false), Array())
private[this] def lzy[T <: AnyRef](x: T) = SafeLazy.strict(x)

View File

@ -37,7 +37,7 @@ final class MixedAnalyzingCompiler(
*/
def compile(include: Set[File], changes: DependencyChanges, callback: AnalysisCallback): Unit = {
val outputDirs = outputDirectories(output)
outputDirs foreach (IO.createDirectory)
outputDirs foreach (d => if (!d.getPath.endsWith(".jar")) IO.createDirectory(d))
val incSrc = sources.filter(include)
val (javaSrcs, scalaSrcs) = incSrc partition javaOnly
logInputs(log, javaSrcs.size, scalaSrcs.size, outputDirs)

View File

@ -107,8 +107,8 @@ abstract class Compat {
}
lazy val AnyValClass = global.rootMirror.getClassIfDefined("scala.AnyVal")
def isAnyValSubtype(sym: Symbol): Boolean = sym.isNonBottomSubClass(AnyValClass)
def isDerivedValueClass(sym: Symbol): Boolean =
sym.isNonBottomSubClass(AnyValClass) && !definitions.ScalaValueClasses.contains(sym)
}
object MacroExpansionOf {

View File

@ -205,23 +205,17 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType,
val hasValueClassAsParameter: Boolean = {
import MirrorHelper._
s.asMethod.paramss.flatten map (_.info) exists (t => isAnyValSubtype(t.typeSymbol))
s.asMethod.paramss.flatten map (_.info) exists (t => isDerivedValueClass(t.typeSymbol))
}
// Note: We only inspect the "outermost type" (i.e. no recursion) because we don't need to
// inspect after erasure a function that would, for instance, return a function that returns
// a subtype of AnyVal.
val hasValueClassAsReturnType: Boolean = {
val tpe = viewer(in).memberInfo(s)
tpe match {
case PolyType(_, base) => isAnyValSubtype(base.typeSymbol)
case MethodType(_, resultType) => isAnyValSubtype(resultType.typeSymbol)
case Nullary(resultType) => isAnyValSubtype(resultType.typeSymbol)
case resultType => isAnyValSubtype(resultType.typeSymbol)
}
def hasValueClassAsReturnType(tpe: Type): Boolean = tpe match {
case PolyType(_, base) => hasValueClassAsReturnType(base)
case MethodType(_, resultType) => hasValueClassAsReturnType(resultType)
case Nullary(resultType) => hasValueClassAsReturnType(resultType)
case resultType => isDerivedValueClass(resultType.typeSymbol)
}
val inspectPostErasure = hasValueClassAsParameter || hasValueClassAsReturnType
val inspectPostErasure = hasValueClassAsParameter || hasValueClassAsReturnType(viewer(in).memberInfo(s))
def build(t: Type, typeParams: Array[xsbti.api.TypeParameter], valueParameters: List[xsbti.api.ParameterList]): List[xsbti.api.Def] =
{
@ -444,7 +438,7 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType,
val absOver = s.hasFlag(ABSOVERRIDE)
val abs = s.hasFlag(ABSTRACT) || s.hasFlag(DEFERRED) || absOver
val over = s.hasFlag(OVERRIDE) || absOver
new xsbti.api.Modifiers(abs, over, s.isFinal, s.hasFlag(SEALED), isImplicit(s), s.hasFlag(LAZY), hasMacro(s))
new xsbti.api.Modifiers(abs, over, s.isFinal, s.hasFlag(SEALED), isImplicit(s), s.hasFlag(LAZY), hasMacro(s), s.hasFlag(SUPERACCESSOR))
}
private def isImplicit(s: Symbol) = s.hasFlag(Flags.IMPLICIT)

View File

@ -9,13 +9,14 @@ public final class Modifiers implements java.io.Serializable
private static final int ImplicitBit = 4;
private static final int LazyBit = 5;
private static final int MacroBit = 6;
private static final int SuperAccessorBit = 7;
private static int flag(boolean set, int bit)
{
return set ? (1 << bit) : 0;
}
public Modifiers(boolean isAbstract, boolean isOverride, boolean isFinal, boolean isSealed, boolean isImplicit, boolean isLazy, boolean isMacro)
public Modifiers(boolean isAbstract, boolean isOverride, boolean isFinal, boolean isSealed, boolean isImplicit, boolean isLazy, boolean isMacro, boolean isSuperAccessor)
{
this.flags = (byte)(
flag(isAbstract, AbstractBit) |
@ -24,7 +25,8 @@ public final class Modifiers implements java.io.Serializable
flag(isSealed, SealedBit) |
flag(isImplicit, ImplicitBit) |
flag(isLazy, LazyBit) |
flag(isMacro, MacroBit)
flag(isMacro, MacroBit) |
flag(isSuperAccessor, SuperAccessorBit)
);
}
@ -68,6 +70,10 @@ public final class Modifiers implements java.io.Serializable
{
return flag(MacroBit);
}
public final boolean isSuperAccessor()
{
return flag(SuperAccessorBit);
}
public boolean equals(Object o)
{
return (o instanceof Modifiers) && flags == ((Modifiers)o).flags;
@ -78,6 +84,6 @@ public final class Modifiers implements java.io.Serializable
}
public String toString()
{
return "Modifiers(" + "isAbstract: " + isAbstract() + ", " + "isOverride: " + isOverride() + ", " + "isFinal: " + isFinal() + ", " + "isSealed: " + isSealed() + ", " + "isImplicit: " + isImplicit() + ", " + "isLazy: " + isLazy() + ", " + "isMacro: " + isMacro()+ ")";
return "Modifiers(" + "isAbstract: " + isAbstract() + ", " + "isOverride: " + isOverride() + ", " + "isFinal: " + isFinal() + ", " + "isSealed: " + isSealed() + ", " + "isImplicit: " + isImplicit() + ", " + "isLazy: " + isLazy() + ", " + "isMacro: " + isMacro()+ ", isSuperAccessor:" + isSuperAccessor() + ")";
}
}

View File

@ -11,7 +11,13 @@ object ConsoleProject {
val cpImports = new Imports(extracted, state)
val bindings = ("currentState" -> state) :: ("extracted" -> extracted) :: ("cpHelpers" -> cpImports) :: Nil
val unit = extracted.currentUnit
val compiler = Compiler.compilers(ClasspathOptions.repl)(state.configuration, log).scalac
val (_, ivyConf) = extracted.runTask(Keys.ivyConfiguration, state)
val scalaInstance = {
val scalaProvider = state.configuration.provider.scalaProvider
ScalaInstance(scalaProvider.version, scalaProvider.launcher)
}
val sourcesModule = extracted.get(Keys.scalaCompilerBridgeSource)
val compiler = Compiler.scalaCompiler(scalaInstance, ClasspathOptions.repl, ivyConf, sourcesModule)(state.configuration, log)
val imports = BuildUtil.getImports(unit.unit) ++ BuildUtil.importAll(bindings.map(_._1))
val importString = imports.mkString("", ";\n", ";\n\n")
val initCommands = importString + extra

View File

@ -1036,8 +1036,7 @@ object Classpaths {
internalDependencyClasspath <<= internalDependencies,
unmanagedClasspath <<= unmanagedDependencies,
managedClasspath := managedJars(classpathConfiguration.value, classpathTypes.value, update.value),
exportedProducts <<= exportProductsTask,
exportedProductsAlways <<= trackedExportedProducts(TrackLevel.TrackAlways),
exportedProducts <<= trackedExportedProducts(TrackLevel.TrackAlways),
exportedProductsIfMissing <<= trackedExportedProducts(TrackLevel.TrackIfMissing),
exportedProductsNoTracking <<= trackedExportedProducts(TrackLevel.NoTracking),
unmanagedJars := findUnmanagedJars(configuration.value, unmanagedBase.value, includeFilter in unmanagedJars value, excludeFilter in unmanagedJars value)
@ -1148,10 +1147,14 @@ object Classpaths {
overrideBuildResolvers <<= appConfiguration(isOverrideRepositories),
externalResolvers <<= (externalResolvers.task.?, resolvers, appResolvers, useJCenter) {
case (Some(delegated), Seq(), _, _) => delegated
case (_, rs, Some(ars), uj) => task { ars ++ Resolver.reorganizeAppResolvers(rs, uj, true) }
case (_, rs, _, uj) => task { Resolver.withDefaultResolvers(rs, uj) }
case (_, rs, Some(ars), uj) => task { ars ++ rs }
case (_, rs, _, uj) => task { Resolver.withDefaultResolvers(rs, uj, true) }
},
appResolvers := {
val ac = appConfiguration.value
val uj = useJCenter.value
appRepositories(ac) map { ars => Resolver.reorganizeAppResolvers(ars, uj, true) }
},
appResolvers <<= appConfiguration apply appRepositories,
bootResolvers <<= appConfiguration map bootRepositories,
fullResolvers <<= (projectResolver, externalResolvers, sbtPlugin, sbtResolver, bootResolvers, overrideBuildResolvers) map { (proj, rs, isPlugin, sbtr, boot, overrideFlag) =>
boot match {
@ -1623,6 +1626,7 @@ object Classpaths {
}
}
@deprecated("This is no longer used.", "0.13.10")
def exportProductsTask: Initialize[Task[Classpath]] = Def.task {
val art = (artifact in packageBin).value
val module = projectID.value
@ -1742,7 +1746,7 @@ object Classpaths {
track match {
case TrackLevel.NoTracking => getClasspath(exportedProductsNoTracking, dep, conf, data)
case TrackLevel.TrackIfMissing => getClasspath(exportedProductsIfMissing, dep, conf, data)
case TrackLevel.TrackAlways => getClasspath(exportedProductsAlways, dep, conf, data)
case TrackLevel.TrackAlways => getClasspath(exportedProducts, dep, conf, data)
}
private[sbt] def unmanagedLibs0(dep: ResolvedReference, conf: String, data: Settings[Scope], track: TrackLevel): Task[Classpath] =
unmanagedLibs(dep, conf, data)

View File

@ -234,7 +234,6 @@ object Keys {
val productDirectories = TaskKey[Seq[File]]("product-directories", "Base directories of build products.", CTask)
val exportJars = SettingKey[Boolean]("export-jars", "Determines whether the exported classpath for this project contains classes (false) or a packaged jar (true).", BSetting)
val exportedProducts = TaskKey[Classpath]("exported-products", "Build products that go on the exported classpath.", CTask)
val exportedProductsAlways = TaskKey[Classpath]("exported-products-always", "Build products that go on the exported classpath for other projects.", CTask)
val exportedProductsIfMissing = TaskKey[Classpath]("exported-products-if-missing", "Build products that go on the exported classpath if missing.", CTask)
val exportedProductsNoTracking = TaskKey[Classpath]("exported-products-no-tracking", "Just the exported classpath without triggering the compilation.", CTask)
val unmanagedClasspath = TaskKey[Classpath]("unmanaged-classpath", "Classpath entries (deep) that are manually managed.", BPlusTask)

View File

@ -71,12 +71,19 @@ object Load {
if (files.isEmpty || base == globalBase) const(Nil) else buildGlobalSettings(globalBase, files, config)
config.copy(injectSettings = config.injectSettings.copy(projectLoaded = compiled))
}
// We are hiding a bug fix on global setting that was not importing auto imports.
// Because fixing this via https://github.com/sbt/sbt/pull/2399
// breaks the source compatibility: https://github.com/sbt/sbt/issues/2415
@deprecated("Remove this when we can break source compatibility.", "0.13.10")
private[sbt] def useAutoImportInGlobal = sys.props.get("sbt.global.autoimport") map { _.toLowerCase == "true" } getOrElse false
def buildGlobalSettings(base: File, files: Seq[File], config: sbt.LoadBuildConfiguration): ClassLoader => Seq[Setting[_]] =
{
val eval = mkEval(data(config.globalPluginClasspath), base, defaultEvalOptions)
val imports = BuildUtil.baseImports ++
config.detectedGlobalPlugins.imports
(// when we can beak the source compat, remove this if and use config.detectedGlobalPlugins.imports
if (useAutoImportInGlobal) config.detectedGlobalPlugins.imports
else BuildUtil.importAllRoot(config.globalPluginNames))
loader => {
val loaded = EvaluateConfigurations(eval, files, imports)(loader)

View File

@ -1,12 +0,0 @@
[@Duhemm]: http://github.com/Duhemm
[1171]: https://github.com/sbt/sbt/issues/1171
[2261]: https://github.com/sbt/sbt/pull/2261
### Fixes with compatibility implications
### Improvements
- Register signatures of method before and after erasure if they involve value classes [#2261][2261] by [@Duhemm][@Duhemm]
### Bug fixes
- Incremental compiler misses change to value class, and results to NoSuchMethodError at runtime [#1171][1171]

View File

@ -1,16 +0,0 @@
[Dotty]: https://github.com/lampepfl/dotty
[@smarter]: https://github.com/smarter
### Fixes with compatibility implications
### Improvements
- sbt is now aware of [Dotty][Dotty], it will assume
that Dotty is used when `scalaVersion` starts with `0.`, the sbt
compiler-bridge does not support Dotty but a separate compiler-bridge is being
developed at https://github.com/smarter/dotty-bridge and an example project
that uses it is available at https://github.com/smarter/dotty-example-project
by [@smarter][@smarter].
### Bug fixes

View File

@ -1,10 +0,0 @@
[1171]: https://github.com/sbt/sbt/issues/1171
[2322]: https://github.com/sbt/sbt/pull/2322
### Fixes with compatibility implications
### Improvements
- Drops `sealed` from the typeclasses in Append. [#2322][] by [@dwijnand][]
### Bug fixes

View File

@ -1,32 +0,0 @@
[@eed3si9n]: https://github.com/eed3si9n
[2266]: https://github.com/sbt/sbt/issues/2266
[2354]: https://github.com/sbt/sbt/pull/2354
### Improvements
- Adds `trackInternalDependencies` and `exportToInternal` keys. See below.
### Inter-project dependency tracking
sbt 0.13.10 adds `trackInternalDependencies` and `exportToInternal` settings. These can be used to control whether to trigger compilation of a dependent subprojects when you call `compile`. Both keys will take one of three values: `TrackLevel.NoTracking`, `TrackLevel.TrackIfMissing`, and `TrackLevel.TrackAlways`. By default they are both set to `TrackLevel.TrackAlways`.
When `trackInternalDependencies` is set to `TrackLevel.TrackIfMissing`, sbt will no longer try to compile internal (inter-project) dependencies automatically, unless there are no `*.class` files (or JAR file when `exportJars` is `true`) in the output directory. When the setting is set to `TrackLevel.NoTracking`, the compilation of internal dependencies will be skipped. Note that the classpath will still be appended, and dependency graph will still show them as dependencies. The motivation is to save the I/O overhead of checking for the changes on a build with many subprojects during development. Here's how to set all subprojects to `TrackIfMissing`.
lazy val root = (project in file(".")).
aggregate(....).
settings(
inThisBuild(Seq(
trackInternalDependencies := TrackLevel.TrackIfMissing,
exportJars := true
))
)
The `exportToInternal` setting allows the dependee subprojects to opt out of the internal tracking, which might be useful if you want to track most subprojects except for a few. The intersection of the `trackInternalDependencies` and `exportToInternal` settings will be used to determine the actual track level. Here's an example to opt-out one project:
lazy val dontTrackMe = (project in file("dontTrackMe")).
settings(
exportToInternal := TrackLevel.NoTracking
)
[#2266][2266]/[#2354][2354] by [@eed3si9n][@eed3si9n]

View File

@ -13,99 +13,124 @@
[@DavidPerezIngeniero]: https://github.com/DavidPerezIngeniero
[@romanowski]: https://github.com/romanowski
[@timcharper]: https://github.com/timcharper
[2302]: https://github.com/sbt/sbt/issues/2302
[2303]: https://github.com/sbt/sbt/pull/2303
[@smarter]: https://github.com/smarter
[@retronym]: https://github.com/retronym
[Dotty]: https://github.com/lampepfl/dotty
[JLine2]: https://github.com/jline/jline2
[14]: https://github.com/sbt/ivy/pull/14
[17]: https://github.com/sbt/ivy/pull/17
[18]: https://github.com/sbt/ivy/pull/18
[1171]: https://github.com/sbt/sbt/issues/1171
[1514]: https://github.com/sbt/sbt/issues/1514
[1616]: https://github.com/sbt/sbt/issues/1616
[1681]: https://github.com/sbt/sbt/issues/1681
[1750]: https://github.com/sbt/sbt/issues/1750
[1827]: https://github.com/sbt/sbt/issues/1827
[1933]: https://github.com/sbt/sbt/issues/1933
[1967]: https://github.com/sbt/sbt/issues/1967
[2085]: https://github.com/sbt/sbt/pull/2085
[1968]: https://github.com/sbt/sbt/issues/1968
[2041]: https://github.com/sbt/sbt/issues/2041
[2071]: https://github.com/sbt/sbt/issues/2071
[2085]: https://github.com/sbt/sbt/pull/2085
[2087]: https://github.com/sbt/sbt/issues/2087
[2091]: https://github.com/sbt/sbt/pull/2091
[2092]: https://github.com/sbt/sbt/pull/2092
[2095]: https://github.com/sbt/sbt/pull/2095
[2094]: https://github.com/sbt/sbt/pull/2094
[2112]: https://github.com/sbt/sbt/pull/2112
[2108]: https://github.com/sbt/sbt/pull/2108
[2106]: https://github.com/sbt/sbt/pull/2106
[2041]: https://github.com/sbt/sbt/issues/2041
[2087]: https://github.com/sbt/sbt/issues/2087
[2095]: https://github.com/sbt/sbt/pull/2095
[2103]: https://github.com/sbt/sbt/pull/2103
[2106]: https://github.com/sbt/sbt/pull/2106
[2107]: https://github.com/sbt/sbt/issues/2107
[2108]: https://github.com/sbt/sbt/pull/2108
[2109]: https://github.com/sbt/sbt/issues/2109
[2112]: https://github.com/sbt/sbt/pull/2112
[2114]: https://github.com/sbt/sbt/pull/2114
[2117]: https://github.com/sbt/sbt/pull/2117
[2109]: https://github.com/sbt/sbt/issues/2109
[2127]: https://github.com/sbt/sbt/pull/2127
[14]: https://github.com/sbt/ivy/pull/14
[2118]: https://github.com/sbt/sbt/issues/2118
[2120]: https://github.com/sbt/sbt/issues/2120
[2127]: https://github.com/sbt/sbt/pull/2127
[2137]: https://github.com/sbt/sbt/pull/2137
[2139]: https://github.com/sbt/sbt/pull/2139
[2142]: https://github.com/sbt/sbt/pull/2142
[2155]: https://github.com/sbt/sbt/issues/2155
[2160]: https://github.com/sbt/sbt/pull/2160
[2158]: https://github.com/sbt/sbt/pull/2158
[1681]: https://github.com/sbt/sbt/issues/1681
[2173]: https://github.com/sbt/sbt/pull/2173
[JLine2]: https://github.com/jline/jline2
[2151]: https://github.com/sbt/sbt/pull/2151
[1750]: https://github.com/sbt/sbt/issues/1750
[17]: https://github.com/sbt/ivy/pull/17
[2155]: https://github.com/sbt/sbt/issues/2155
[2158]: https://github.com/sbt/sbt/pull/2158
[2160]: https://github.com/sbt/sbt/pull/2160
[2163]: https://github.com/sbt/sbt/pull/2163
[18]: https://github.com/sbt/ivy/pull/18
[2172]: https://github.com/sbt/sbt/pull/2172
[2173]: https://github.com/sbt/sbt/pull/2173
[2186]: https://github.com/sbt/sbt/pull/2186
[2197]: https://github.com/sbt/sbt/pull/2197
[2192]: https://github.com/sbt/sbt/pull/2192
[2197]: https://github.com/sbt/sbt/pull/2197
[2201]: https://github.com/sbt/sbt/pull/2201
[2214]: https://github.com/sbt/sbt/pull/2214
[1933]: https://github.com/sbt/sbt/issues/1933
[2258]: https://github.com/sbt/sbt/pull/2258
[2228]: https://github.com/sbt/sbt/issues/2228
[2271]: https://github.com/sbt/sbt/pull/2271
[2285]: https://github.com/sbt/sbt/pull/2285
[2256]: https://github.com/sbt/sbt/issues/2256
[2272]: https://github.com/sbt/sbt/pull/2272
[1968]: https://github.com/sbt/sbt/issues/1968
[2264]: https://github.com/sbt/sbt/issues/2264
[2172]: https://github.com/sbt/sbt/pull/2172
[2217]: https://github.com/sbt/sbt/issues/2217
[2228]: https://github.com/sbt/sbt/issues/2228
[2256]: https://github.com/sbt/sbt/issues/2256
[2258]: https://github.com/sbt/sbt/pull/2258
[2261]: https://github.com/sbt/sbt/pull/2261
[2264]: https://github.com/sbt/sbt/issues/2264
[2266]: https://github.com/sbt/sbt/issues/2266
[2271]: https://github.com/sbt/sbt/pull/2271
[2272]: https://github.com/sbt/sbt/pull/2272
[2285]: https://github.com/sbt/sbt/pull/2285
[2302]: https://github.com/sbt/sbt/issues/2302
[2303]: https://github.com/sbt/sbt/pull/2303
[2311]: https://github.com/sbt/sbt/pull/2311
[2313]: https://github.com/sbt/sbt/pull/2313
[2322]: https://github.com/sbt/sbt/pull/2322
[2324]: https://github.com/sbt/sbt/issues/2324
[2325]: https://github.com/sbt/sbt/pull/2325
[2336]: https://github.com/sbt/sbt/issues/2336
[1514]: https://github.com/sbt/sbt/issues/1514
[1616]: https://github.com/sbt/sbt/issues/1616
[2313]: https://github.com/sbt/sbt/pull/2313
[2343]: https://github.com/sbt/sbt/pull/2343
[2120]: https://github.com/sbt/sbt/issues/2120
[2344]: https://github.com/sbt/sbt/pull/2344
[2354]: https://github.com/sbt/sbt/pull/2354
[2399]: https://github.com/sbt/sbt/pull/2399
[2453]: https://github.com/sbt/sbt/pull/2453
[2467]: https://github.com/sbt/sbt/pull/2467
[101]: https://github.com/sbt/sbt-launcher-package/pull/101
[105]: https://github.com/sbt/sbt-launcher-package/pull/105
### Fixes with compatibility implications
- sbt 0.13.10 adds a new setting `useJCenter`, which is set to `false` by default. When set to `true`, JCenter will be placed as the first external resolver to find library dependencies. [#2217][2217] by [@eed3si9n][@eed3si9n]
- JCenter is now opt-in. A new setting `useJCenter` can be set to `true` to re-include it, as the first external resolver to find library dependencies. [#2217][2217]/[#2467][2467] by [@eed3si9n][@eed3si9n]
- Adds `withInterProjectFirst` to the update option, which is enabled by default. When set to `true`, `inter-project` resolver will be prioritized above all resolvers and Ivy cache. [#1827][1827] by [@eed3si9n][@eed3si9n]
- Fixes update option's `withLatestSnapshots` so it handles modules without an artifact. This flag will be enabled by default.
[#1514][1514]/[#1616][1616]/[#2313][2313] by [@eed3si9n][@eed3si9n]
- sbt will no longer pass `-J<flag>` options to the local Java compiler. [#1968][1968]/[#2272][2272] by [@Duhemm][@Duhemm]
- No longer passes `-J<flag>` options to the local Java compiler. [#1968][1968]/[#2272][2272] by [@Duhemm][@Duhemm]
- Fixes auto imports for auto plugins in global configuration files. Because this is *not* source compatible with 0.13.x, the fix is enabled only when `sbt.global.autoimport` flag is `true`. [#2120][2120]/[#2399][2399] by [@timcharper][@timcharper]
### Improvements
- Adds configurable compiler bridge. See below.
- Adds initial support for [Dotty][Dotty]. See below
- Adds settings for granular inter-project dependency tracking. See below.
- Scala version used by the build is updated to 2.10.6. [#2311][2311] by [@eed3si9n][@eed3si9n]
- If `publishMavenStyle` is `true`, `update` task warns when it sees intransitive dependencies, which do not translate to Maven. [#2127][2127] by [@jsuereth][@jsuereth]
- Adds `Def.settings`, which facilitates mixing settings with seq of settings. See below.
- Adds configurable compiler bridge. See below.
- sbt Serialization is updated to 0.1.2. [2117][#2117] by [@dwijnand][@dwijnand]
- sbt Serialization is updated to 0.1.2. [#2117][2117] by [@dwijnand][@dwijnand]
- Hides the stack trace on compilation error in build definition. [#2071][2071]/[#2091][2091] by [@Duhemm][@Duhemm]
- Makes the dummy `Logger.Null` public. [#2094][2094] by [@pdalpra][@pdalpra]
- Uses diagnostic classes to get lines contents in local Java compiler. [#2108][2108]/[#2201][2201] by [@fkorotkov][@fkorotkov]
- Logs javaOptions used when forking. [#2087][2087]/[#2103][2103] by [@pdalpra][@pdalpra]
- Adds logging of javaOptions. [#2087][2087]/[#2103][2103] by [@pdalpra][@pdalpra]
- Warns when javaOptions are defined but fork is set to false. [#2041][2041]/[#2103][2103] by [@pdalpra][@pdalpra]
- Adds an `Append.Sequence` instance for `List` to allow `+=`/`++=` on `developers` setting. [#2107][2107]/[#2114][2114] by [@pdalpra][@pdalpra]
- Fixes warnings, and other clean ups. [#2112][2112]/[#2137][2137]/[#2139][2139]/[#2142][2142] by [@pdalpra][@pdalpra]
- Drops `sealed` from the typeclasses in `Append`. [#2322][2322] by [@dwijnand][@dwijnand]
- Fixes compilation warnings in sbt's codebase, and other clean ups. [#2112][2112]/[#2137][2137]/[#2139][2139]/[#2142][2142] by [@pdalpra][@pdalpra]
- Adds `localIfFile` to `MavenRepository`, to force artifacts to be copied to the cache. [#2172][2172] by [@dwijnand][@dwijnand]
- Adds `Resolver.bintrayIvyRepo(owner, repo)`. [#2285][2285] by [@dwijnand][@dwijnand]
- Non-static annotation changes are no longer tracked by the incremental compiler. [#2343][2343] by [@romanowski][@romanowski]
- Reduces the memory usage of API info extraction in the incremental compiler. [#2343][2343] by [@adriaanm][@adriaanm]
- Memory-related options can now be overridden individually via the `-J` options. [sbt/sbt-launcher-package#105][105]
### Bug fixes
- Fixes the false positive of inconsistent duplicate warnings. [#1933][1933]/[#2258][2258] by
[@Duhemm][@Duhemm]
- Fixes task scheduling performance on large builds by skipping checks in `sbt.Execute`. [#2302][2302]/[#2303][2303] by [@jrudolph][@jrudolph]
- Fixes changes in value classes by registering signatures of method before and after erasure. [#1171][1171]/[#2261][2261] by [@Duhemm][@Duhemm]
- Updated Ivy to merge IVY-1526 fix. [sbt/ivy#14][14]/[#2118][2118] by [@jsuereth][@jsuereth]
- Fixes `updateClassifiers` downloading updated snapshot sources and docs.
[#1750][1750]/[sbt/ivy#17][17]/[#2163][2163]/[sbt/ivy#18][18]/[#2186][2186] by [@dwijnand][@dwijnand]
@ -127,11 +152,50 @@
- Adds more robustness to `tasks` and `settings` command. [#2192][2192] by [@DavidPerezIngeniero][@DavidPerezIngeniero]
- Fixes Java compilation inconsistencies between sbt and `javac` by always failing if the local Java compiler reported errors. [#2228][2228]/[#2271][2271] by [@Duhemm][@Duhemm]
- Fixes `JavaErrorParser` to parse non-compile-errors [#2256][2256]/[#2272][2272] by [@Duhemm][@Duhemm]
- Fixes task scheduling performance on large builds by skipping checks in `sbt.Execute`. [#2302][2302]/[#2303][2303] by [@jrudolph][@jrudolph]
- Fixes launcher configuration to add `sbt-ivy-snapshots` repository to resolve nightly builds. [@eed3si9n][@eed3si9n]
- Fixes performance issues during tree traversal in the incremental compiler. [#2343][2343] by [@adriaanm][@adriaanm]
- Fixes the tracking of self types and F-bounded existential types in the incremental compiler. [#2343][2343] by [@adriaanm][@adriaanm]
- Fixes autoImports for AutoPlugins for global configuration files. [#2120][2120]/[#2399][2399] by [@timcharper][@timcharper]
- Avoid CCE when scalac internally uses `compileLate`. [#2453][2453] by [@retronym][@retronym]
- Fixes the memory-related options overriding `SBT_OPTS`. [sbt/sbt-launcher-package#101][101] by [@eed3si9n][@eed3si9n]
### Configurable Scala compiler bridge
sbt 0.13.11 adds `scalaCompilerBridgeSource` setting to specify the compiler brigde source. This allows different implementation of the bridge for Scala versions, and also allows future versions of Scala compiler implementation to diverge. The source module will be retrieved using library management configured by `bootIvyConfiguration` task.
[#2106][2106]/[#2197][2197]/[#2336][2336] by [@Duhemm][@Duhemm]
### Dotty awareness
sbt 0.13.11 will assume that Dotty is used when `scalaVersion` starts with `0.`.
The built-in compiler bridge in sbt does not support Dotty,
but a separate compiler bridge is being developed at [smarter/dotty-bridge](https://github.com/smarter/dotty-bridge) and
an example project that uses it is available at [smarter/dotty-example-project](https://github.com/smarter/dotty-example-project).
[#2344][2344] by [@smarter][@smarter]
### Inter-project dependency tracking
sbt 0.13.11 adds `trackInternalDependencies` and `exportToInternal` settings. These can be used to control whether to trigger compilation of a dependent subprojects when you call `compile`. Both keys will take one of three values: `TrackLevel.NoTracking`, `TrackLevel.TrackIfMissing`, and `TrackLevel.TrackAlways`. By default they are both set to `TrackLevel.TrackAlways`.
When `trackInternalDependencies` is set to `TrackLevel.TrackIfMissing`, sbt will no longer try to compile internal (inter-project) dependencies automatically, unless there are no `*.class` files (or JAR file when `exportJars` is `true`) in the output directory. When the setting is set to `TrackLevel.NoTracking`, the compilation of internal dependencies will be skipped. Note that the classpath will still be appended, and dependency graph will still show them as dependencies. The motivation is to save the I/O overhead of checking for the changes on a build with many subprojects during development. Here's how to set all subprojects to `TrackIfMissing`.
lazy val root = (project in file(".")).
aggregate(....).
settings(
inThisBuild(Seq(
trackInternalDependencies := TrackLevel.TrackIfMissing,
exportJars := true
))
)
The `exportToInternal` setting allows the dependee subprojects to opt out of the internal tracking, which might be useful if you want to track most subprojects except for a few. The intersection of the `trackInternalDependencies` and `exportToInternal` settings will be used to determine the actual track level. Here's an example to opt-out one project:
lazy val dontTrackMe = (project in file("dontTrackMe")).
settings(
exportToInternal := TrackLevel.NoTracking
)
[#2266][2266]/[#2354][2354] by [@eed3si9n][@eed3si9n]
### Def.settings
@ -143,9 +207,3 @@ Using `Def.settings` it is now possible to nicely define settings as such:
)
[#2151][2151] by [@dwijnand][@dwijnand]
### Configurable Scala compiler bridge
sbt 0.13.10 adds `scalaCompilerBridgeSource` setting to specify the compiler brigde source. This allows different implementation of the bridge for Scala versions, and also allows future versions of Scala compiler implementation to diverge. The source module will be retrieved using library management configured by `bootIvyConfiguration` task.
[#2106][2106]/[#2197][2197]/[#2336][2336] by [@Duhemm][@Duhemm]

View File

@ -3,3 +3,9 @@
> set useJCenter := true
> check2
> reload
> set resolvers += Resolver.jcenterRepo
> check2

View File

@ -1,15 +1,5 @@
package test
import sbt._
object Global {
val x = 3
}
object GlobalAutoPlugin extends AutoPlugin {
object autoImport {
lazy val globalAutoPluginSetting = settingKey[String]("A top level setting declared in a plugin.")
}
}

View File

@ -0,0 +1,11 @@
package test
import sbt._
object GlobalAutoPlugin extends AutoPlugin {
object autoImport {
lazy val globalAutoPluginSetting = settingKey[String]("A top level setting declared in a plugin.")
}
}

View File

@ -0,0 +1,3 @@
# This test is marked pending because sbt.globalsettingfix flag is off by default
# See https://github.com/sbt/sbt/issues/2415
> name

View File

@ -0,0 +1,9 @@
# Test if adding a member to a trait affects classes that refer to that trait
# by a member reference
> compile
# add `foo` method to `A`
$ copy-file changes/A1.scala src/main/scala/A.scala
# only A.scala should be recompiled
> compile
# check if there are only two compile iterations performed
> check-compilations

View File

@ -0,0 +1,3 @@
trait A {
val foo = 0
}

View File

@ -0,0 +1,5 @@
object B extends A {
def main(args: Array[String]): Unit = {
println(foo)
}
}

View File

@ -0,0 +1,4 @@
trait A {
val foo = 0 + X.a
private object X { val a = 1 }
}

View File

@ -0,0 +1,5 @@
> run
$ copy-file changes/A.scala A.scala
> run

View File

@ -0,0 +1,5 @@
trait A {
private val foo = 12
// we need to access foo to trigger AbstractMethodError
def bar: Int = foo
}

View File

@ -1,14 +1,28 @@
$ copy-file changes/A0.scala A.scala
# compile and run for the first time to verify that everything works
> run
# introduce private var and refer to it in a trait that we inherit from
# there'll be pair of getters and setters generated for private var that
# has to be implemented by a class (where you can declare corresponding field)
$ copy-file changes/A.scala A.scala
$ copy-file changes/A1.scala A.scala
# this fails with AbstractMethodError because getters and setters for
# a private var are not generated because introduction of a private var
# does not trigger recompilation of B
# B is not recompiled because incremental compiler tracks only public
# interace (members visible from outside of given trait/class)
# If the introduction of a private var did not trigger the recompilation of B,
# then this will fail with AbstractMethodError because the getters and setters
# for the private var have not been generated.
> run
# Try again with a private val
> clean
$ copy-file changes/A0.scala A.scala
# compile and run a clean project to verify that everything works
> run
# introduce a private val in the trait
$ copy-file changes/A2.scala A.scala
# Verify that B has been recompiled and that everything runs fine.
> run

View File

@ -0,0 +1,3 @@
class B {
def bar(dummy: String)(dummy2: String): A = new A(0)
}

View File

@ -0,0 +1,3 @@
object C extends App {
println(new B().bar("")("").x)
}

View File

@ -1,3 +1,4 @@
## Case 1: value class as parameter of method
$ copy-file changes/A0.scala src/main/scala/A.scala
$ copy-file changes/B0.scala src/main/scala/B.scala
$ copy-file changes/C0.scala src/main/scala/C.scala
@ -13,6 +14,8 @@ $ copy-file changes/A1.scala src/main/scala/A.scala
# This means that we have invalidated C.scala, as expected!
-> compile
## Case 2: value class as return type of method with no parameter lists
$ copy-file changes/A0.scala src/main/scala/A.scala
$ copy-file changes/B1.scala src/main/scala/B.scala
$ copy-file changes/C1.scala src/main/scala/C.scala
@ -28,3 +31,20 @@ $ copy-file changes/A1.scala src/main/scala/A.scala
# because A is now a value class.
> run
## Case 3: value class as return type of method with multiple parameter lists
$ copy-file changes/A0.scala src/main/scala/A.scala
$ copy-file changes/B2.scala src/main/scala/B.scala
$ copy-file changes/C2.scala src/main/scala/C.scala
# A is a normal class. B.bar takes two dummy arguments and returns an instance of A. C calls B.bar("")("").
> compile
> run
# Make A a value class.
$ copy-file changes/A1.scala src/main/scala/A.scala
# The code compiles. It will run iff C is recompiled because the signature of B.bar has changed,
# because A is now a value class.
> run

View File

@ -4,7 +4,7 @@
[app]
org: ${sbt.organization-org.scala-sbt}
name: sbt
version: ${sbt.version-read(sbt.version)[0.13.9]}
version: ${sbt.version-read(sbt.version)[0.13.11]}
class: sbt.xMain
components: xsbti,extra
cross-versioned: ${sbt.cross.versioned-false}

View File

@ -4,7 +4,7 @@
[app]
org: ${sbt.organization-org.scala-sbt}
name: sbt
version: ${sbt.version-read(sbt.version)[0.13.9]}
version: ${sbt.version-read(sbt.version)[0.13.11]}
class: sbt.ScriptMain
components: xsbti,extra
cross-versioned: ${sbt.cross.versioned-false}

View File

@ -4,7 +4,7 @@
[app]
org: ${sbt.organization-org.scala-sbt}
name: sbt
version: ${sbt.version-read(sbt.version)[0.13.9]}
version: ${sbt.version-read(sbt.version)[0.13.11]}
class: sbt.ConsoleMain
components: xsbti,extra
cross-versioned: ${sbt.cross.versioned-false}