From 06658661a16bcf44241393fc4c5b78df1f49e12c Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 22 Jan 2016 14:47:37 -0500 Subject: [PATCH 01/27] Hand merged notes --- notes/0.13.10.markdown | 63 ++++++++++++++++--- .../consider-signatures-after-erasure.md | 12 ---- notes/0.13.10/dotty-awareness.md | 16 ----- ...op-sealed-from-Append-typeclasses.markdown | 10 --- notes/0.13.10/internal-tracking.md | 32 ---------- 5 files changed, 54 insertions(+), 79 deletions(-) delete mode 100644 notes/0.13.10/consider-signatures-after-erasure.md delete mode 100644 notes/0.13.10/dotty-awareness.md delete mode 100644 notes/0.13.10/drop-sealed-from-Append-typeclasses.markdown delete mode 100644 notes/0.13.10/internal-tracking.md diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index b42df40fa..7513714db 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -13,6 +13,7 @@ [@DavidPerezIngeniero]: https://github.com/DavidPerezIngeniero [@romanowski]: https://github.com/romanowski [@timcharper]: https://github.com/timcharper + [@smarter]: https://github.com/smarter [2302]: https://github.com/sbt/sbt/issues/2302 [2303]: https://github.com/sbt/sbt/pull/2303 [1967]: https://github.com/sbt/sbt/issues/1967 @@ -74,6 +75,12 @@ [2343]: https://github.com/sbt/sbt/pull/2343 [2120]: https://github.com/sbt/sbt/issues/2120 [2399]: https://github.com/sbt/sbt/pull/2399 + [1171]: https://github.com/sbt/sbt/issues/1171 + [2261]: https://github.com/sbt/sbt/pull/2261 + [2344]: https://github.com/sbt/sbt/pull/2344 + [2322]: https://github.com/sbt/sbt/pull/2322 + [2266]: https://github.com/sbt/sbt/issues/2266 + [2354]: https://github.com/sbt/sbt/pull/2354 ### Fixes with compatibility implications @@ -85,10 +92,12 @@ ### Improvements +- Adds configurable compiler bridge. See below. +- sbt is now aware of [Dotty][Dotty]. See below +- 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] - 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] @@ -96,16 +105,20 @@ - Logs javaOptions used when forking. [#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] +- Register signatures of method before and after erasure if they involve value classes [#2261][2261] by [@Duhemm][@Duhemm] ### 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] +- Incremental compiler misses change to value class, and results to NoSuchMethodError at runtime [#1171][1171] - 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,12 +140,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] +### 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] + +### Dotty awareness + +sbt 0.13.10 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.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] + ### Def.settings Using `Def.settings` it is now possible to nicely define settings as such: @@ -143,9 +194,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] diff --git a/notes/0.13.10/consider-signatures-after-erasure.md b/notes/0.13.10/consider-signatures-after-erasure.md deleted file mode 100644 index f511a5aba..000000000 --- a/notes/0.13.10/consider-signatures-after-erasure.md +++ /dev/null @@ -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] \ No newline at end of file diff --git a/notes/0.13.10/dotty-awareness.md b/notes/0.13.10/dotty-awareness.md deleted file mode 100644 index 5660f9bcd..000000000 --- a/notes/0.13.10/dotty-awareness.md +++ /dev/null @@ -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 diff --git a/notes/0.13.10/drop-sealed-from-Append-typeclasses.markdown b/notes/0.13.10/drop-sealed-from-Append-typeclasses.markdown deleted file mode 100644 index 6ad216120..000000000 --- a/notes/0.13.10/drop-sealed-from-Append-typeclasses.markdown +++ /dev/null @@ -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 diff --git a/notes/0.13.10/internal-tracking.md b/notes/0.13.10/internal-tracking.md deleted file mode 100644 index eacdd2dec..000000000 --- a/notes/0.13.10/internal-tracking.md +++ /dev/null @@ -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] From 223cb2632e1295ba7a15af89099b2a1c36bc6d6b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 22 Jan 2016 23:11:43 +0000 Subject: [PATCH 02/27] Notes: Sort issues, move ivy/jline to the top --- notes/0.13.10.markdown | 85 ++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index 7513714db..ca1813153 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -14,73 +14,76 @@ [@romanowski]: https://github.com/romanowski [@timcharper]: https://github.com/timcharper [@smarter]: https://github.com/smarter - [2302]: https://github.com/sbt/sbt/issues/2302 - [2303]: https://github.com/sbt/sbt/pull/2303 + + [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 + [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 + [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 - [2399]: https://github.com/sbt/sbt/pull/2399 - [1171]: https://github.com/sbt/sbt/issues/1171 - [2261]: https://github.com/sbt/sbt/pull/2261 [2344]: https://github.com/sbt/sbt/pull/2344 - [2322]: https://github.com/sbt/sbt/pull/2322 - [2266]: https://github.com/sbt/sbt/issues/2266 [2354]: https://github.com/sbt/sbt/pull/2354 + [2399]: https://github.com/sbt/sbt/pull/2399 ### Fixes with compatibility implications From 899ac9eb984d92e5680e768cab634fa31baa321c Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 22 Jan 2016 23:12:06 +0000 Subject: [PATCH 03/27] Notes: Fix links --- notes/0.13.10.markdown | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index ca1813153..404ebd157 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -15,6 +15,7 @@ [@timcharper]: https://github.com/timcharper [@smarter]: https://github.com/smarter + [Dotty]: https://github.com/lampepfl/dotty [JLine2]: https://github.com/jline/jline2 [14]: https://github.com/sbt/ivy/pull/14 @@ -26,6 +27,7 @@ [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 [1968]: https://github.com/sbt/sbt/issues/1968 @@ -75,6 +77,7 @@ [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 @@ -101,7 +104,7 @@ - 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. -- 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] From 8a12edbfa010c73dc457f13563887db1da41afc4 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 22 Jan 2016 23:18:31 +0000 Subject: [PATCH 04/27] Notes: Reword some passages --- notes/0.13.10.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index 404ebd157..0bacdc5ba 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -90,17 +90,17 @@ ### 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] 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` options to the local Java compiler. [#1968][1968]/[#2272][2272] by [@Duhemm][@Duhemm] +- No longer passes `-J` options to the local Java compiler. [#1968][1968]/[#2272][2272] by [@Duhemm][@Duhemm] ### Improvements - Adds configurable compiler bridge. See below. -- sbt is now aware of [Dotty][Dotty]. See below -- Inter-project dependency tracking. 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. @@ -108,7 +108,7 @@ - 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] - Drops `sealed` from the typeclasses in `Append`. [#2322][2322] by [@dwijnand][@dwijnand] @@ -124,7 +124,7 @@ - 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] -- Incremental compiler misses change to value class, and results to NoSuchMethodError at runtime [#1171][1171] +- Fixes changes in value classes by registering signatures of method before and after erasure. [#1171][1171] - 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] From 26b9d9c1abab035f48b81378bd937a55f571d016 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Fri, 22 Jan 2016 23:19:03 +0000 Subject: [PATCH 05/27] Notes: Collapse an improvement into its fix --- notes/0.13.10.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index 0bacdc5ba..572578a7a 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -117,14 +117,13 @@ - 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] -- Register signatures of method before and after erasure if they involve value classes [#2261][2261] by [@Duhemm][@Duhemm] ### 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] +- 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] From ceccbf2d5ad16814f5ef89bc05fc7624b1b9c230 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 24 Jan 2016 16:50:21 -0800 Subject: [PATCH 06/27] Fixes #2415. Hide global setting fix behind sbt.globalsettingfix We are hiding a bug fix on global setting that was not importing auto imports because fixing this via sbt/sbt#2399 breaks the source compatibility: sbt/sbt#2415 I've split out the relevant portion of the scripted test into global-settings, and marked it pending. --- main/src/main/scala/sbt/Load.scala | 9 ++++++++- .../project/global-plugin/global/plugins/A.scala | 10 ---------- .../project/global-settings/global/plugins/A.scala | 11 +++++++++++ .../global/plugins/B.scala | 0 .../global/useGlobalAutoPlugin.sbt | 0 .../global/useGlobalLegacyPlugin.sbt | 0 sbt/src/sbt-test/project/global-settings/pending | 3 +++ 7 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 sbt/src/sbt-test/project/global-settings/global/plugins/A.scala rename sbt/src/sbt-test/project/{global-plugin => global-settings}/global/plugins/B.scala (100%) rename sbt/src/sbt-test/project/{global-plugin => global-settings}/global/useGlobalAutoPlugin.sbt (100%) rename sbt/src/sbt-test/project/{global-plugin => global-settings}/global/useGlobalLegacyPlugin.sbt (100%) create mode 100644 sbt/src/sbt-test/project/global-settings/pending diff --git a/main/src/main/scala/sbt/Load.scala b/main/src/main/scala/sbt/Load.scala index e5d8a5113..ed20fb389 100755 --- a/main/src/main/scala/sbt/Load.scala +++ b/main/src/main/scala/sbt/Load.scala @@ -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.globalsettingfix") 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) diff --git a/sbt/src/sbt-test/project/global-plugin/global/plugins/A.scala b/sbt/src/sbt-test/project/global-plugin/global/plugins/A.scala index bbf9fc243..b75a623b5 100644 --- a/sbt/src/sbt-test/project/global-plugin/global/plugins/A.scala +++ b/sbt/src/sbt-test/project/global-plugin/global/plugins/A.scala @@ -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.") - } - -} diff --git a/sbt/src/sbt-test/project/global-settings/global/plugins/A.scala b/sbt/src/sbt-test/project/global-settings/global/plugins/A.scala new file mode 100644 index 000000000..ee7171f10 --- /dev/null +++ b/sbt/src/sbt-test/project/global-settings/global/plugins/A.scala @@ -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.") + } + +} diff --git a/sbt/src/sbt-test/project/global-plugin/global/plugins/B.scala b/sbt/src/sbt-test/project/global-settings/global/plugins/B.scala similarity index 100% rename from sbt/src/sbt-test/project/global-plugin/global/plugins/B.scala rename to sbt/src/sbt-test/project/global-settings/global/plugins/B.scala diff --git a/sbt/src/sbt-test/project/global-plugin/global/useGlobalAutoPlugin.sbt b/sbt/src/sbt-test/project/global-settings/global/useGlobalAutoPlugin.sbt similarity index 100% rename from sbt/src/sbt-test/project/global-plugin/global/useGlobalAutoPlugin.sbt rename to sbt/src/sbt-test/project/global-settings/global/useGlobalAutoPlugin.sbt diff --git a/sbt/src/sbt-test/project/global-plugin/global/useGlobalLegacyPlugin.sbt b/sbt/src/sbt-test/project/global-settings/global/useGlobalLegacyPlugin.sbt similarity index 100% rename from sbt/src/sbt-test/project/global-plugin/global/useGlobalLegacyPlugin.sbt rename to sbt/src/sbt-test/project/global-settings/global/useGlobalLegacyPlugin.sbt diff --git a/sbt/src/sbt-test/project/global-settings/pending b/sbt/src/sbt-test/project/global-settings/pending new file mode 100644 index 000000000..1b6bd3c6f --- /dev/null +++ b/sbt/src/sbt-test/project/global-settings/pending @@ -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 From 0993c1c7cc1103c70fb364db77dcc3e776027e7d Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 23 Jan 2016 17:50:57 +0100 Subject: [PATCH 07/27] Always invalidate API when return type is a value class Before this commit, we did not do the invalidation for methods with multiple parameter list, the comment above `hasValueClassAsReturnType` said: 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. But this is wrong: a method with signature: def foo(a: A)(b: B): C is erased to: def foo(a: A, b: B): C and not, as the comment in the code suggest, to: def foo(a: A): B => C so we do need to inspect the final result type of methods, because they can be value classes that will be erased to their underlying value. --- .../src/main/scala/xsbt/ExtractAPI.scala | 18 ++++++----------- .../value-class/changes/B2.scala | 3 +++ .../value-class/changes/C2.scala | 3 +++ .../source-dependencies/value-class/test | 20 +++++++++++++++++++ 4 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 sbt/src/sbt-test/source-dependencies/value-class/changes/B2.scala create mode 100644 sbt/src/sbt-test/source-dependencies/value-class/changes/C2.scala diff --git a/compile/interface/src/main/scala/xsbt/ExtractAPI.scala b/compile/interface/src/main/scala/xsbt/ExtractAPI.scala index 31389218b..7a0a78b2c 100644 --- a/compile/interface/src/main/scala/xsbt/ExtractAPI.scala +++ b/compile/interface/src/main/scala/xsbt/ExtractAPI.scala @@ -208,20 +208,14 @@ class ExtractAPI[GlobalType <: CallbackGlobal](val global: GlobalType, s.asMethod.paramss.flatten map (_.info) exists (t => isAnyValSubtype(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 => isAnyValSubtype(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] = { diff --git a/sbt/src/sbt-test/source-dependencies/value-class/changes/B2.scala b/sbt/src/sbt-test/source-dependencies/value-class/changes/B2.scala new file mode 100644 index 000000000..fe1136389 --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/value-class/changes/B2.scala @@ -0,0 +1,3 @@ +class B { + def bar(dummy: String)(dummy2: String): A = new A(0) +} diff --git a/sbt/src/sbt-test/source-dependencies/value-class/changes/C2.scala b/sbt/src/sbt-test/source-dependencies/value-class/changes/C2.scala new file mode 100644 index 000000000..17b70f957 --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/value-class/changes/C2.scala @@ -0,0 +1,3 @@ +object C extends App { + println(new B().bar("")("").x) +} diff --git a/sbt/src/sbt-test/source-dependencies/value-class/test b/sbt/src/sbt-test/source-dependencies/value-class/test index f78acb2d8..268274bf6 100644 --- a/sbt/src/sbt-test/source-dependencies/value-class/test +++ b/sbt/src/sbt-test/source-dependencies/value-class/test @@ -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 + From 726b5c8a30b2459727dede5061ddbbba803b9c52 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Sat, 23 Jan 2016 18:29:42 +0100 Subject: [PATCH 08/27] ExtractAPI: avoid unnecessary duplication of defs with primitive types If a method's type contains a non-primitive value class then it has two signatures: one before erasure and one after erasure. Before this commit, we checked if this was the case using `isAnyValSubtype`, but this is too crude since primitive value classes are also subtypes of `AnyVal` but do not change signature after erasure. This commit replaces `isAnyValSubtype` by `isDerivedValueClass` which excludes primitive value classes. In practice, for an empty class, this reduces the size of the output of `DefaultShowAPI` from 65 lines to 25 lines. Before: https://gist.github.com/smarter/cf1d6fe58efda88d6ee6#file-old-api After: https://gist.github.com/smarter/cf1d6fe58efda88d6ee6#file-new-api --- compile/interface/src/main/scala/xsbt/Compat.scala | 4 ++-- compile/interface/src/main/scala/xsbt/ExtractAPI.scala | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compile/interface/src/main/scala/xsbt/Compat.scala b/compile/interface/src/main/scala/xsbt/Compat.scala index 9f9fb247c..a4859275d 100644 --- a/compile/interface/src/main/scala/xsbt/Compat.scala +++ b/compile/interface/src/main/scala/xsbt/Compat.scala @@ -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 { diff --git a/compile/interface/src/main/scala/xsbt/ExtractAPI.scala b/compile/interface/src/main/scala/xsbt/ExtractAPI.scala index 7a0a78b2c..011479be6 100644 --- a/compile/interface/src/main/scala/xsbt/ExtractAPI.scala +++ b/compile/interface/src/main/scala/xsbt/ExtractAPI.scala @@ -205,14 +205,14 @@ 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)) } def hasValueClassAsReturnType(tpe: Type): Boolean = tpe match { case PolyType(_, base) => hasValueClassAsReturnType(base) case MethodType(_, resultType) => hasValueClassAsReturnType(resultType) case Nullary(resultType) => hasValueClassAsReturnType(resultType) - case resultType => isAnyValSubtype(resultType.typeSymbol) + case resultType => isDerivedValueClass(resultType.typeSymbol) } val inspectPostErasure = hasValueClassAsParameter || hasValueClassAsReturnType(viewer(in).memberInfo(s)) From 9da5fc871bd183f0a2c9d6848d770ca5d0b1abf7 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 26 Jan 2016 03:05:30 +0900 Subject: [PATCH 09/27] Changed the flag name to "sbt.global.autoimport" per review. --- main/src/main/scala/sbt/Load.scala | 2 +- notes/0.13.10.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main/src/main/scala/sbt/Load.scala b/main/src/main/scala/sbt/Load.scala index ed20fb389..ecd04cf07 100755 --- a/main/src/main/scala/sbt/Load.scala +++ b/main/src/main/scala/sbt/Load.scala @@ -75,7 +75,7 @@ object Load { // 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.globalsettingfix") map { _.toLowerCase == "true" } getOrElse false + 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) diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index 572578a7a..eb252674d 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -95,6 +95,7 @@ - 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] - No longer passes `-J` 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 @@ -148,7 +149,6 @@ - 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] ### Configurable Scala compiler bridge From 6cabb9b4cb95e1c8bdd373e89b9cf77656e7ca84 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Sun, 31 Jan 2016 17:01:55 +0100 Subject: [PATCH 10/27] Update bridge retrieval in `consoleProject` Fixes sbt/sbt#2428 --- main/src/main/scala/sbt/ConsoleProject.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/ConsoleProject.scala b/main/src/main/scala/sbt/ConsoleProject.scala index a484d4e8f..3d66cf552 100644 --- a/main/src/main/scala/sbt/ConsoleProject.scala +++ b/main/src/main/scala/sbt/ConsoleProject.scala @@ -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 From 3e50fdc825837f4dc10be1657af135387168e810 Mon Sep 17 00:00:00 2001 From: Antonio Cunei Date: Thu, 4 Feb 2016 15:11:55 +0100 Subject: [PATCH 11/27] Do not create dir, if trying to output classes to a jar --- .../src/main/scala/sbt/compiler/MixedAnalyzingCompiler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compile/integration/src/main/scala/sbt/compiler/MixedAnalyzingCompiler.scala b/compile/integration/src/main/scala/sbt/compiler/MixedAnalyzingCompiler.scala index 4081ca473..546345805 100644 --- a/compile/integration/src/main/scala/sbt/compiler/MixedAnalyzingCompiler.scala +++ b/compile/integration/src/main/scala/sbt/compiler/MixedAnalyzingCompiler.scala @@ -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) From 74ffe5d064960c04cc1c83a206110e051d0fd81b Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Tue, 2 Feb 2016 16:37:19 +0100 Subject: [PATCH 12/27] Add a pending test for a modified member of a trait The test shows that name hashing optimization is broken for members defined in traits. The problem is that modification of a member of a trait triggers change of a hash of trait's name. The behavior covered by this test regressed in 40ebc825317ed29a2ab87be07246fcdcfc6d1e3d The bug is tracked in #2436. --- .../trait-member-modified/build.sbt | 27 +++++++++++++++++++ .../trait-member-modified/changes/A1.scala | 3 +++ .../trait-member-modified/pending | 9 +++++++ .../src/main/scala/A.scala | 1 + .../src/main/scala/B.scala | 1 + 5 files changed, 41 insertions(+) create mode 100644 sbt/src/sbt-test/compiler-project/trait-member-modified/build.sbt create mode 100644 sbt/src/sbt-test/compiler-project/trait-member-modified/changes/A1.scala create mode 100644 sbt/src/sbt-test/compiler-project/trait-member-modified/pending create mode 100644 sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/A.scala create mode 100644 sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/B.scala diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/build.sbt b/sbt/src/sbt-test/compiler-project/trait-member-modified/build.sbt new file mode 100644 index 000000000..949d78231 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/trait-member-modified/build.sbt @@ -0,0 +1,27 @@ +/* Performs checks related to compilations: + * a) checks in which compilation given set of files was recompiled + * b) checks overall number of compilations performed + */ +TaskKey[Unit]("check-compilations") := { + val analysis = (compile in Compile).value + val srcDir = (scalaSource in Compile).value + def relative(f: java.io.File): java.io.File = f.relativeTo(srcDir) getOrElse f + val allCompilations = analysis.compilations.allCompilations + val recompiledFiles: Seq[Set[java.io.File]] = allCompilations map { c => + val recompiledFiles = analysis.apis.internal.collect { + case (file, api) if api.compilation.startTime == c.startTime => relative(file) + } + recompiledFiles.toSet + } + def recompiledFilesInIteration(iteration: Int, fileNames: Set[String]) = { + val files = fileNames.map(new java.io.File(_)) + assert(recompiledFiles(iteration) == files, "%s != %s".format(recompiledFiles(iteration), files)) + } + assert(allCompilations.size == 2) + // B.scala is just compiled at the beginning + recompiledFilesInIteration(0, Set("B.scala")) + // A.scala is changed and recompiled + recompiledFilesInIteration(1, Set("A.scala")) +} + +logLevel := Level.Debug diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/changes/A1.scala b/sbt/src/sbt-test/compiler-project/trait-member-modified/changes/A1.scala new file mode 100644 index 000000000..57a1f34c6 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/trait-member-modified/changes/A1.scala @@ -0,0 +1,3 @@ +trait A { + def foo: Int = 12 +} diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/pending b/sbt/src/sbt-test/compiler-project/trait-member-modified/pending new file mode 100644 index 000000000..f8f7cb076 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/trait-member-modified/pending @@ -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 diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/A.scala b/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/A.scala new file mode 100644 index 000000000..0eab80adc --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/A.scala @@ -0,0 +1 @@ +trait A diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/B.scala b/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/B.scala new file mode 100644 index 000000000..c4d3f7e97 --- /dev/null +++ b/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/B.scala @@ -0,0 +1 @@ +class B(a: A) From 207dd762f4044c05d7d7577f030dddc735d49f4c Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Wed, 3 Feb 2016 14:34:31 +0100 Subject: [PATCH 13/27] Move `trait-member-modified` to source-dependencies It's not clear what the distinction between compiler-project and source-dependencies scripted tests is so let's stick to the one that has the biggest number of tests for incremental compiler. --- .../trait-member-modified/build.sbt | 0 .../trait-member-modified/changes/A1.scala | 0 .../trait-member-modified/pending | 0 .../trait-member-modified/src/main/scala/A.scala | 0 .../trait-member-modified/src/main/scala/B.scala | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename sbt/src/sbt-test/{compiler-project => source-dependencies}/trait-member-modified/build.sbt (100%) rename sbt/src/sbt-test/{compiler-project => source-dependencies}/trait-member-modified/changes/A1.scala (100%) rename sbt/src/sbt-test/{compiler-project => source-dependencies}/trait-member-modified/pending (100%) rename sbt/src/sbt-test/{compiler-project => source-dependencies}/trait-member-modified/src/main/scala/A.scala (100%) rename sbt/src/sbt-test/{compiler-project => source-dependencies}/trait-member-modified/src/main/scala/B.scala (100%) diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/build.sbt b/sbt/src/sbt-test/source-dependencies/trait-member-modified/build.sbt similarity index 100% rename from sbt/src/sbt-test/compiler-project/trait-member-modified/build.sbt rename to sbt/src/sbt-test/source-dependencies/trait-member-modified/build.sbt diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/changes/A1.scala b/sbt/src/sbt-test/source-dependencies/trait-member-modified/changes/A1.scala similarity index 100% rename from sbt/src/sbt-test/compiler-project/trait-member-modified/changes/A1.scala rename to sbt/src/sbt-test/source-dependencies/trait-member-modified/changes/A1.scala diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/pending b/sbt/src/sbt-test/source-dependencies/trait-member-modified/pending similarity index 100% rename from sbt/src/sbt-test/compiler-project/trait-member-modified/pending rename to sbt/src/sbt-test/source-dependencies/trait-member-modified/pending diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/A.scala b/sbt/src/sbt-test/source-dependencies/trait-member-modified/src/main/scala/A.scala similarity index 100% rename from sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/A.scala rename to sbt/src/sbt-test/source-dependencies/trait-member-modified/src/main/scala/A.scala diff --git a/sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/B.scala b/sbt/src/sbt-test/source-dependencies/trait-member-modified/src/main/scala/B.scala similarity index 100% rename from sbt/src/sbt-test/compiler-project/trait-member-modified/src/main/scala/B.scala rename to sbt/src/sbt-test/source-dependencies/trait-member-modified/src/main/scala/B.scala From be8ba763fa2257224646caf70c2b8295901053f0 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 3 Feb 2016 13:49:15 +0100 Subject: [PATCH 14/27] Include ONLY non-public members in API hash of traits The previous logic was wrong and included all members of traits in their API hash, which degraded the performance of the incremental compiler. This commit changes this logic so that only the non-public members of traits are included into their API hash. Fixes #2436 --- compile/api/src/main/scala/xsbt/api/HashAPI.scala | 7 ++++++- .../trait-member-modified/{pending => test} | 0 2 files changed, 6 insertions(+), 1 deletion(-) rename sbt/src/sbt-test/source-dependencies/trait-member-modified/{pending => test} (100%) diff --git a/compile/api/src/main/scala/xsbt/api/HashAPI.scala b/compile/api/src/main/scala/xsbt/api/HashAPI.scala index 6ed4054e0..59b59797c 100644 --- a/compile/api/src/main/scala/xsbt/api/HashAPI.scala +++ b/compile/api/src/main/scala/xsbt/api/HashAPI.scala @@ -356,7 +356,12 @@ 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) { + if (isTrait && !includeDefinitions) { + def public(d: Definition): Boolean = d.access match { case _: xsbti.api.Public => true; case _ => false } + hashDefinitions(structure.declared.filterNot(public), isTrait) + hashDefinitions(structure.inherited.filterNot(public), isTrait) + } + if (includeDefinitions) { hashDefinitions(structure.declared, isTrait) hashDefinitions(structure.inherited, isTrait) } diff --git a/sbt/src/sbt-test/source-dependencies/trait-member-modified/pending b/sbt/src/sbt-test/source-dependencies/trait-member-modified/test similarity index 100% rename from sbt/src/sbt-test/source-dependencies/trait-member-modified/pending rename to sbt/src/sbt-test/source-dependencies/trait-member-modified/test From bd5453c0b07ff36c9a26322092cb23252573ef55 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 5 Feb 2016 08:28:59 -0500 Subject: [PATCH 15/27] Fixes #2427 inter-project dependency interference with sbt-web sbt-web uses exportedProducts key as an extension point. This removes exportedProductsAlways from 0.13.10-RC1, and uses exportedProducts instead. --- main/src/main/scala/sbt/Defaults.scala | 6 +++--- main/src/main/scala/sbt/Keys.scala | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index ac4a2c513..633215062 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -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) @@ -1623,6 +1622,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 +1742,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) diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 14b3b8d0f..566d8ed49 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -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) From 8e17269c97c255403be6577ab135801c7fbe7ab7 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 9 Feb 2016 14:35:12 +0100 Subject: [PATCH 16/27] Include non-public vars in API hash of traits --- .../api/src/main/scala/xsbt/api/HashAPI.scala | 26 +++-- .../xsbt/api/NameHashingSpecification.scala | 101 ++++++++++++++---- 2 files changed, 98 insertions(+), 29 deletions(-) diff --git a/compile/api/src/main/scala/xsbt/api/HashAPI.scala b/compile/api/src/main/scala/xsbt/api/HashAPI.scala index 59b59797c..02cc6aded 100644 --- a/compile/api/src/main/scala/xsbt/api/HashAPI.scala +++ b/compile/api/src/main/scala/xsbt/api/HashAPI.scala @@ -139,16 +139,29 @@ 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 = { + // If the enclosing definition is a trait, then we must include private vars in the API hash + // of the trait, because scalac will generate setters and getters for these vars in the traits + // implementors. + val traitPrivateVars = + if (!includePrivate && !topLevel && isTrait) { + def isPublic(d: Definition): Boolean = d.access match { case _: xsbti.api.Public => true; case _ => false } + ds.collect { case v: Var if !isPublic(v) => v } + } else Seq.empty + val defs = SameAPI.filterDefinitions(ds, topLevel, includePrivate) - hashSymmetric(defs, hashDefinition) + hashSymmetric(traitPrivateVars ++ defs, hashDefinition) } /** @@ -356,14 +369,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 (isTrait && !includeDefinitions) { - def public(d: Definition): Boolean = d.access match { case _: xsbti.api.Public => true; case _ => false } - hashDefinitions(structure.declared.filterNot(public), isTrait) - hashDefinitions(structure.inherited.filterNot(public), isTrait) - } if (includeDefinitions) { - hashDefinitions(structure.declared, isTrait) - hashDefinitions(structure.inherited, isTrait) + hashDefinitions(structure.declared, topLevel = false, isTrait) + hashDefinitions(structure.inherited, topLevel = false, isTrait) } } def hashParameters(parameters: Seq[TypeParameter], base: Type): Unit = diff --git a/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala b/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala index 4849838b2..470254dda 100644 --- a/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala +++ b/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala @@ -165,24 +165,25 @@ 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. + * + * NOTE: This logic is important for vars only. No other private member needs to be included. */ - "private members in traits" in { - /* trait Foo { private val x } */ + "private var in traits are included in API hash" in { + /* trait Foo { private var x } */ val fooTrait1 = simpleTrait("Foo", - simpleStructure(new Val(emptyType, "x", privateAccess, defaultModifiers, Array.empty)), + simpleStructure(new Var(emptyType, "x", privateAccess, defaultModifiers, Array.empty)), publicAccess) /* trait Foo */ @@ -198,15 +199,75 @@ class NameHashingSpecification extends Specification { } + "private vals in traits are NOT included in API hash" in { + /* trait Foo { private val x } */ + val fooTrait1 = + simpleTrait("Foo", + simpleStructure(new Val(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 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 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 } } */ + /* 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 } */ @@ -227,11 +288,11 @@ 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 } } */ + /* 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 +317,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 +335,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 = From 7d9425110852205eb2d24126aac00867fbec127f Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 9 Feb 2016 14:55:30 +0100 Subject: [PATCH 17/27] Also include private vals --- compile/api/src/main/scala/xsbt/api/HashAPI.scala | 10 +++++----- .../test/scala/xsbt/api/NameHashingSpecification.scala | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compile/api/src/main/scala/xsbt/api/HashAPI.scala b/compile/api/src/main/scala/xsbt/api/HashAPI.scala index 02cc6aded..0f0baac56 100644 --- a/compile/api/src/main/scala/xsbt/api/HashAPI.scala +++ b/compile/api/src/main/scala/xsbt/api/HashAPI.scala @@ -151,17 +151,17 @@ final class HashAPI(includePrivate: Boolean, includeParamNames: Boolean, include def hashDefinitions(ds: Seq[Definition], topLevel: Boolean, isTrait: Boolean): Unit = { - // If the enclosing definition is a trait, then we must include private vars in the API hash - // of the trait, because scalac will generate setters and getters for these vars in the traits + // If the enclosing definition is a trait, then we must include private vars and vals in the API hash + // of the trait, because scalac will generate setters, getters and fields for them in the traits // implementors. - val traitPrivateVars = + val traitPrivateFields = if (!includePrivate && !topLevel && isTrait) { def isPublic(d: Definition): Boolean = d.access match { case _: xsbti.api.Public => true; case _ => false } - ds.collect { case v: Var if !isPublic(v) => v } + ds.collect { case fl: FieldLike if !isPublic(fl) => fl } } else Seq.empty val defs = SameAPI.filterDefinitions(ds, topLevel, includePrivate) - hashSymmetric(traitPrivateVars ++ defs, hashDefinition) + hashSymmetric(traitPrivateFields ++ defs, hashDefinition) } /** diff --git a/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala b/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala index 470254dda..5d75708dd 100644 --- a/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala +++ b/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala @@ -177,7 +177,7 @@ class NameHashingSpecification extends Specification { * we get abstract method errors at runtime, because the types expected by the setter (for instance) does not * match. * - * NOTE: This logic is important for vars only. No other private member needs to be included. + * NOTE: This logic is important for vars and vals only. No other private member needs to be included. */ "private var in traits are included in API hash" in { /* trait Foo { private var x } */ @@ -199,7 +199,7 @@ class NameHashingSpecification extends Specification { } - "private vals in traits are NOT included in API hash" in { + "private vals in traits are included in API hash" in { /* trait Foo { private val x } */ val fooTrait1 = simpleTrait("Foo", @@ -215,7 +215,7 @@ class NameHashingSpecification extends Specification { val api1 = new SourceAPI(Array.empty, Array(fooTrait1)) val api2 = new SourceAPI(Array.empty, Array(fooTrait2)) - HashAPI(api1) === HashAPI(api2) + HashAPI(api1) !== HashAPI(api2) } From edc11744685fe7c439c97c6d0588561580f79fc7 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Tue, 9 Feb 2016 15:28:35 +0100 Subject: [PATCH 18/27] Extend test `trait-private-var` with vals Private vars and private vals defined in a trait impact the bytecode generated for the implementors of these traits. The scripted test `source-dependencies/trait-private-var` only accounted for private vars. It now tries the same scenario both with private vars and private vals. --- .../{A.scala => changes/A0.scala} | 0 .../changes/{A.scala => A1.scala} | 0 .../trait-private-var/changes/A2.scala | 5 ++++ .../trait-private-var/test | 26 ++++++++++++++----- 4 files changed, 25 insertions(+), 6 deletions(-) rename sbt/src/sbt-test/source-dependencies/trait-private-var/{A.scala => changes/A0.scala} (100%) rename sbt/src/sbt-test/source-dependencies/trait-private-var/changes/{A.scala => A1.scala} (100%) create mode 100644 sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A2.scala diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-var/A.scala b/sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A0.scala similarity index 100% rename from sbt/src/sbt-test/source-dependencies/trait-private-var/A.scala rename to sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A0.scala diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A.scala b/sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A1.scala similarity index 100% rename from sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A.scala rename to sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A1.scala diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A2.scala b/sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A2.scala new file mode 100644 index 000000000..60641457d --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/trait-private-var/changes/A2.scala @@ -0,0 +1,5 @@ +trait A { + private val foo = 12 + // we need to access foo to trigger AbstractMethodError + def bar: Int = foo +} diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-var/test b/sbt/src/sbt-test/source-dependencies/trait-private-var/test index d928246a9..c120697d8 100644 --- a/sbt/src/sbt-test/source-dependencies/trait-private-var/test +++ b/sbt/src/sbt-test/source-dependencies/trait-private-var/test @@ -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 From 65768446986d4e521cdb3f82f807d4886474c216 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Wed, 10 Feb 2016 18:15:44 +0100 Subject: [PATCH 19/27] Hash of traits: include private fields, objects and super accessors --- .../api/src/main/scala/sbt/ClassToAPI.scala | 2 +- .../api/src/main/scala/xsbt/api/APIUtil.scala | 2 +- .../api/src/main/scala/xsbt/api/HashAPI.scala | 22 +++++--- .../xsbt/api/NameHashingSpecification.scala | 52 ++++++++++++++++--- .../scala/sbt/inc/TestCaseGenerators.scala | 2 +- .../src/main/scala/xsbt/ExtractAPI.scala | 2 +- .../src/main/java/xsbti/api/Modifiers.java | 12 +++-- .../trait-private-object/A.scala | 3 ++ .../trait-private-object/B.scala | 5 ++ .../trait-private-object/changes/A.scala | 4 ++ .../trait-private-object/test | 5 ++ 11 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 sbt/src/sbt-test/source-dependencies/trait-private-object/A.scala create mode 100644 sbt/src/sbt-test/source-dependencies/trait-private-object/B.scala create mode 100644 sbt/src/sbt-test/source-dependencies/trait-private-object/changes/A.scala create mode 100644 sbt/src/sbt-test/source-dependencies/trait-private-object/test diff --git a/compile/api/src/main/scala/sbt/ClassToAPI.scala b/compile/api/src/main/scala/sbt/ClassToAPI.scala index 9589865ec..1eb91f44b 100644 --- a/compile/api/src/main/scala/sbt/ClassToAPI.scala +++ b/compile/api/src/main/scala/sbt/ClassToAPI.scala @@ -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 = { diff --git a/compile/api/src/main/scala/xsbt/api/APIUtil.scala b/compile/api/src/main/scala/xsbt/api/APIUtil.scala index d8c4e88cc..577d2cb8f 100644 --- a/compile/api/src/main/scala/xsbt/api/APIUtil.scala +++ b/compile/api/src/main/scala/xsbt/api/APIUtil.scala @@ -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") diff --git a/compile/api/src/main/scala/xsbt/api/HashAPI.scala b/compile/api/src/main/scala/xsbt/api/HashAPI.scala index 0f0baac56..f600d5416 100644 --- a/compile/api/src/main/scala/xsbt/api/HashAPI.scala +++ b/compile/api/src/main/scala/xsbt/api/HashAPI.scala @@ -151,17 +151,25 @@ final class HashAPI(includePrivate: Boolean, includeParamNames: Boolean, include def hashDefinitions(ds: Seq[Definition], topLevel: Boolean, isTrait: Boolean): Unit = { - // If the enclosing definition is a trait, then we must include private vars and vals in the API hash - // of the trait, because scalac will generate setters, getters and fields for them in the traits - // implementors. - val traitPrivateFields = + 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) { - def isPublic(d: Definition): Boolean = d.access match { case _: xsbti.api.Public => true; case _ => false } - ds.collect { case fl: FieldLike if !isPublic(fl) => fl } + ds filter (x => isTraitBreaker(x) && !isPublic(x)) } else Seq.empty val defs = SameAPI.filterDefinitions(ds, topLevel, includePrivate) - hashSymmetric(traitPrivateFields ++ defs, hashDefinition) + hashSymmetric(includedPrivateDefinitions ++ defs, hashDefinition) } /** diff --git a/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala b/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala index 5d75708dd..1ec910058 100644 --- a/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala +++ b/compile/api/src/test/scala/xsbt/api/NameHashingSpecification.scala @@ -176,8 +176,6 @@ class NameHashingSpecification extends Specification { * 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. - * - * NOTE: This logic is important for vars and vals only. No other private member needs to be included. */ "private var in traits are included in API hash" in { /* trait Foo { private var x } */ @@ -219,7 +217,28 @@ class NameHashingSpecification extends Specification { } - "private def in traits are not included in API hash" in { + "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", @@ -239,6 +258,27 @@ class NameHashingSpecification extends Specification { } + "private synthetic def in traits are included in API hash" in { + /* trait Foo { private 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 = @@ -262,7 +302,7 @@ class NameHashingSpecification extends Specification { /** * Checks that private vars in non-top-level traits are included as well. */ - "private members in nested traits" in { + "private variables in nested traits are include in the API hash" in { /* class A { trait Foo { private var x } } */ val classA1 = simpleClass("A", @@ -287,7 +327,7 @@ class NameHashingSpecification extends Specification { /** * Checks that private traits are NOT included in the hash. */ - "private traits" in { + "private inner traits are not included in the API hash" in { /* class Foo { private trait T { private var x } } */ val classFoo1 = simpleClass("Foo", @@ -397,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) } diff --git a/compile/inc/src/test/scala/sbt/inc/TestCaseGenerators.scala b/compile/inc/src/test/scala/sbt/inc/TestCaseGenerators.scala index 7591183b1..3379ced55 100644 --- a/compile/inc/src/test/scala/sbt/inc/TestCaseGenerators.scala +++ b/compile/inc/src/test/scala/sbt/inc/TestCaseGenerators.scala @@ -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) diff --git a/compile/interface/src/main/scala/xsbt/ExtractAPI.scala b/compile/interface/src/main/scala/xsbt/ExtractAPI.scala index 011479be6..07336d31b 100644 --- a/compile/interface/src/main/scala/xsbt/ExtractAPI.scala +++ b/compile/interface/src/main/scala/xsbt/ExtractAPI.scala @@ -438,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) diff --git a/interface/src/main/java/xsbti/api/Modifiers.java b/interface/src/main/java/xsbti/api/Modifiers.java index 5e103c7ec..c91c3ec28 100644 --- a/interface/src/main/java/xsbti/api/Modifiers.java +++ b/interface/src/main/java/xsbti/api/Modifiers.java @@ -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() + ")"; } } diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-object/A.scala b/sbt/src/sbt-test/source-dependencies/trait-private-object/A.scala new file mode 100644 index 000000000..cbcda3176 --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/trait-private-object/A.scala @@ -0,0 +1,3 @@ +trait A { + val foo = 0 +} \ No newline at end of file diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-object/B.scala b/sbt/src/sbt-test/source-dependencies/trait-private-object/B.scala new file mode 100644 index 000000000..5da0f8a71 --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/trait-private-object/B.scala @@ -0,0 +1,5 @@ +object B extends A { + def main(args: Array[String]): Unit = { + println(foo) + } +} diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-object/changes/A.scala b/sbt/src/sbt-test/source-dependencies/trait-private-object/changes/A.scala new file mode 100644 index 000000000..b5600153b --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/trait-private-object/changes/A.scala @@ -0,0 +1,4 @@ +trait A { + val foo = 0 + X.a + private object X { val a = 1 } +} \ No newline at end of file diff --git a/sbt/src/sbt-test/source-dependencies/trait-private-object/test b/sbt/src/sbt-test/source-dependencies/trait-private-object/test new file mode 100644 index 000000000..5aab7a143 --- /dev/null +++ b/sbt/src/sbt-test/source-dependencies/trait-private-object/test @@ -0,0 +1,5 @@ +> run + +$ copy-file changes/A.scala A.scala + +> run \ No newline at end of file From 7d4890b68abda301e39b233c7f79a920790742be Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 10 Feb 2016 22:48:10 +1000 Subject: [PATCH 20/27] Avoid CCE when scalac internally uses compileLate. Fixes #2452 For example, when the `--sourcepath` option is provided and the refchecks phase compiles an annotation found on a referenced symbol from the sourcepath. `compileLate` assumes that all non-sentinel compiler phases can be down cast to `GlobalPhase`. This commit changes the two phases in SBT to extend this instead of `Phase`. This has the knock on benefit of simplifying the phases by letting the `GlobalPhase.run` iterator over the list of compilation units and feed them to us one by one. I checked that the test case failed before making each change. --- .../interface/src/main/scala/xsbt/API.scala | 9 ++++++--- .../src/main/scala/xsbt/Analyzer.scala | 6 +++--- .../src/main/scala/xsbt/Dependency.scala | 6 +++--- sbt/src/sbt-test/api/source-path/build.sbt | 5 +++++ .../api/source-path/src/main/scala/test.scala | 18 ++++++++++++++++++ .../srcpath/scala/deprecatedInheritance.scala | 4 ++++ sbt/src/sbt-test/api/source-path/test | 1 + 7 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 sbt/src/sbt-test/api/source-path/build.sbt create mode 100644 sbt/src/sbt-test/api/source-path/src/main/scala/test.scala create mode 100644 sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala create mode 100644 sbt/src/sbt-test/api/source-path/test diff --git a/compile/interface/src/main/scala/xsbt/API.scala b/compile/interface/src/main/scala/xsbt/API.scala index 8af37f6b0..e556590a5 100644 --- a/compile/interface/src/main/scala/xsbt/API.scala +++ b/compile/interface/src/main/scala/xsbt/API.scala @@ -22,16 +22,19 @@ final class API(val global: CallbackGlobal) extends Compat { @inline def debug(msg: => String) = if (settings.verbose.value) inform(msg) def newPhase(prev: Phase) = new ApiPhase(prev) - class ApiPhase(prev: Phase) extends Phase(prev) { + class ApiPhase(prev: Phase) extends GlobalPhase(prev) { override def description = "Extracts the public API from source files." def name = API.name - def run: Unit = + override def run(): Unit = { val start = System.currentTimeMillis - currentRun.units.foreach(processUnit) + super.run val stop = System.currentTimeMillis debug("API phase took : " + ((stop - start) / 1000.0) + " s") } + + def apply(unit: global.CompilationUnit): Unit = processUnit(unit) + def processUnit(unit: CompilationUnit) = if (!unit.isJava) processScalaUnit(unit) def processScalaUnit(unit: CompilationUnit): Unit = { val sourceFile = unit.source.file.file diff --git a/compile/interface/src/main/scala/xsbt/Analyzer.scala b/compile/interface/src/main/scala/xsbt/Analyzer.scala index 2bf01f630..adc26ff5e 100644 --- a/compile/interface/src/main/scala/xsbt/Analyzer.scala +++ b/compile/interface/src/main/scala/xsbt/Analyzer.scala @@ -19,11 +19,11 @@ final class Analyzer(val global: CallbackGlobal) extends LocateClassFile { import global._ def newPhase(prev: Phase): Phase = new AnalyzerPhase(prev) - private class AnalyzerPhase(prev: Phase) extends Phase(prev) { + private class AnalyzerPhase(prev: Phase) extends GlobalPhase(prev) { override def description = "Finds concrete instances of provided superclasses, and application entry points." def name = Analyzer.name - def run { - for (unit <- currentRun.units if !unit.isJava) { + def apply(unit: CompilationUnit) { + if (!unit.isJava) { val sourceFile = unit.source.file.file // build list of generated classes for (iclass <- unit.icode) { diff --git a/compile/interface/src/main/scala/xsbt/Dependency.scala b/compile/interface/src/main/scala/xsbt/Dependency.scala index 80d68c5ba..edcc3bd0c 100644 --- a/compile/interface/src/main/scala/xsbt/Dependency.scala +++ b/compile/interface/src/main/scala/xsbt/Dependency.scala @@ -33,11 +33,11 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile { import global._ def newPhase(prev: Phase): Phase = new DependencyPhase(prev) - private class DependencyPhase(prev: Phase) extends Phase(prev) { + private class DependencyPhase(prev: Phase) extends GlobalPhase(prev) { override def description = "Extracts dependency information" def name = Dependency.name - def run: Unit = { - for (unit <- currentRun.units if !unit.isJava) { + def apply(unit: CompilationUnit): Unit = { + if (!unit.isJava) { // build dependencies structure val sourceFile = unit.source.file.file if (global.callback.nameHashing) { diff --git a/sbt/src/sbt-test/api/source-path/build.sbt b/sbt/src/sbt-test/api/source-path/build.sbt new file mode 100644 index 000000000..58e2a083c --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/build.sbt @@ -0,0 +1,5 @@ +scalaVersion := "2.11.7" + +scalacOptions in Compile ++= "-sourcepath" :: (baseDirectory.value / "srcpath").toString :: Nil + + diff --git a/sbt/src/sbt-test/api/source-path/src/main/scala/test.scala b/sbt/src/sbt-test/api/source-path/src/main/scala/test.scala new file mode 100644 index 000000000..18ca50b84 --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/src/main/scala/test.scala @@ -0,0 +1,18 @@ + +object Test { + // When the refchecks compiler phase checks if Tuple2 has the + // @deprecated annotation, it forces the info for the + // `@deprecatedInheritance` annotation (the only annotation on + // class Tuple2. + // + // Because we are compiling with `-sourcpath` that contains a + // source file for `deprecatedInheritance`, this triggers a + // `compileLate` of that file (which basically runs all previous + // compiler phases on that file.) + // + // `compileLate` assumes that all of the phases are subclasses + // of `GlobalPhase`, rather than just `Phase`. This triggers a + // `ClassCastException` when it encounters SBT's custom + // API phase. + new Tuple2("", "") +} diff --git a/sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala b/sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala new file mode 100644 index 000000000..8f49314ca --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/srcpath/scala/deprecatedInheritance.scala @@ -0,0 +1,4 @@ +package scala + +private[scala] // for now, this needs to be generalized to communicate other modifier deltas +class deprecatedInheritance(message: String = "", since: String = "") extends scala.annotation.StaticAnnotation diff --git a/sbt/src/sbt-test/api/source-path/test b/sbt/src/sbt-test/api/source-path/test new file mode 100644 index 000000000..5df2af1f3 --- /dev/null +++ b/sbt/src/sbt-test/api/source-path/test @@ -0,0 +1 @@ +> compile From be69daeb8db5d0f4e1e2bd58e4d5e40dea6fbf77 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 11 Feb 2016 16:32:39 -0500 Subject: [PATCH 21/27] Add notes for #2453 --- notes/0.13.10.markdown | 3 +++ 1 file changed, 3 insertions(+) diff --git a/notes/0.13.10.markdown b/notes/0.13.10.markdown index eb252674d..5f6c34fd8 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.10.markdown @@ -14,6 +14,7 @@ [@romanowski]: https://github.com/romanowski [@timcharper]: https://github.com/timcharper [@smarter]: https://github.com/smarter + [@retronym]: https://github.com/retronym [Dotty]: https://github.com/lampepfl/dotty [JLine2]: https://github.com/jline/jline2 @@ -87,6 +88,7 @@ [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 ### Fixes with compatibility implications @@ -149,6 +151,7 @@ - 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] +- Avoid CCE when scalac internally uses `compileLate`. [#2453][2453] by [@retronym][@retronym] ### Configurable Scala compiler bridge From 2a956a97df21d84d4def509681debb2b2bc6bd18 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Fri, 19 Feb 2016 16:39:37 -0500 Subject: [PATCH 22/27] launchconfig bump --- src/main/conscript/sbt/launchconfig | 2 +- src/main/conscript/scalas/launchconfig | 2 +- src/main/conscript/screpl/launchconfig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/conscript/sbt/launchconfig b/src/main/conscript/sbt/launchconfig index 033dc550b..32edfef9c 100644 --- a/src/main/conscript/sbt/launchconfig +++ b/src/main/conscript/sbt/launchconfig @@ -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.10]} class: sbt.xMain components: xsbti,extra cross-versioned: ${sbt.cross.versioned-false} diff --git a/src/main/conscript/scalas/launchconfig b/src/main/conscript/scalas/launchconfig index 0d0d5664c..4569e5afb 100644 --- a/src/main/conscript/scalas/launchconfig +++ b/src/main/conscript/scalas/launchconfig @@ -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.10]} class: sbt.ScriptMain components: xsbti,extra cross-versioned: ${sbt.cross.versioned-false} diff --git a/src/main/conscript/screpl/launchconfig b/src/main/conscript/screpl/launchconfig index afa5eb125..fb2d40b42 100644 --- a/src/main/conscript/screpl/launchconfig +++ b/src/main/conscript/screpl/launchconfig @@ -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.10]} class: sbt.ConsoleMain components: xsbti,extra cross-versioned: ${sbt.cross.versioned-false} From c5954ae156d78a8c2138df0b2028d3d04338e608 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 21 Feb 2016 04:08:12 -0500 Subject: [PATCH 23/27] Fixes #2464. Actually reorganize appResolvers Fixes #2464 and Fixes #2465 appResolvers is a set of resolvers specified in the launcher configuration. This list fluctuates depending on the version of sbt, and sbt 0.13.10 meant to stabilize it by weeding out JCenter even when it includes it, which failed when I applied the filter on the wrong list. This should correct it. --- main/src/main/scala/sbt/Defaults.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 633215062..ae6e93823 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -1147,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 { From d2cb16968cb5cc8fe2c1b81ae40c9425ef928602 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 21 Feb 2016 06:44:35 -0500 Subject: [PATCH 24/27] Adds test for #2466 per review --- .../sbt-test/dependency-management/default-resolvers/test | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sbt/src/sbt-test/dependency-management/default-resolvers/test b/sbt/src/sbt-test/dependency-management/default-resolvers/test index 2513e8edf..0d310c9f5 100644 --- a/sbt/src/sbt-test/dependency-management/default-resolvers/test +++ b/sbt/src/sbt-test/dependency-management/default-resolvers/test @@ -3,3 +3,9 @@ > set useJCenter := true > check2 + +> reload + +> set resolvers += Resolver.jcenterRepo + +> check2 From 7ebba1c54e3cdbe216eb9c81a12229b8f9d4779f Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 21 Feb 2016 18:50:17 -0500 Subject: [PATCH 25/27] sbt 0.13.11 is the new 0.13.10 --- build.sbt | 2 +- notes/{0.13.10.markdown => 0.13.11.markdown} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename notes/{0.13.10.markdown => 0.13.11.markdown} (98%) diff --git a/build.sbt b/build.sbt index c1682d13e..448656eb2 100644 --- a/build.sbt +++ b/build.sbt @@ -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", diff --git a/notes/0.13.10.markdown b/notes/0.13.11.markdown similarity index 98% rename from notes/0.13.10.markdown rename to notes/0.13.11.markdown index 5f6c34fd8..0d8d2debd 100644 --- a/notes/0.13.10.markdown +++ b/notes/0.13.11.markdown @@ -155,13 +155,13 @@ ### 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. +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.10 will assume that Dotty is used when `scalaVersion` starts with `0.`. +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). @@ -170,7 +170,7 @@ an example project that uses it is available at [smarter/dotty-example-project]( ### 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`. +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`. From 683995e64fbb983b58f7f466850eea10f9f850d8 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 21 Feb 2016 21:28:59 -0500 Subject: [PATCH 26/27] bump launchconfig --- src/main/conscript/sbt/launchconfig | 2 +- src/main/conscript/scalas/launchconfig | 2 +- src/main/conscript/screpl/launchconfig | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/conscript/sbt/launchconfig b/src/main/conscript/sbt/launchconfig index 32edfef9c..eafdc7534 100644 --- a/src/main/conscript/sbt/launchconfig +++ b/src/main/conscript/sbt/launchconfig @@ -4,7 +4,7 @@ [app] org: ${sbt.organization-org.scala-sbt} name: sbt - version: ${sbt.version-read(sbt.version)[0.13.10]} + version: ${sbt.version-read(sbt.version)[0.13.11]} class: sbt.xMain components: xsbti,extra cross-versioned: ${sbt.cross.versioned-false} diff --git a/src/main/conscript/scalas/launchconfig b/src/main/conscript/scalas/launchconfig index 4569e5afb..02d28dd3f 100644 --- a/src/main/conscript/scalas/launchconfig +++ b/src/main/conscript/scalas/launchconfig @@ -4,7 +4,7 @@ [app] org: ${sbt.organization-org.scala-sbt} name: sbt - version: ${sbt.version-read(sbt.version)[0.13.10]} + version: ${sbt.version-read(sbt.version)[0.13.11]} class: sbt.ScriptMain components: xsbti,extra cross-versioned: ${sbt.cross.versioned-false} diff --git a/src/main/conscript/screpl/launchconfig b/src/main/conscript/screpl/launchconfig index fb2d40b42..f3a2907c4 100644 --- a/src/main/conscript/screpl/launchconfig +++ b/src/main/conscript/screpl/launchconfig @@ -4,7 +4,7 @@ [app] org: ${sbt.organization-org.scala-sbt} name: sbt - version: ${sbt.version-read(sbt.version)[0.13.10]} + version: ${sbt.version-read(sbt.version)[0.13.11]} class: sbt.ConsoleMain components: xsbti,extra cross-versioned: ${sbt.cross.versioned-false} From d281c3561d330b39737e80f2a2d66550cea1435a Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Mon, 22 Feb 2016 02:22:29 -0500 Subject: [PATCH 27/27] notes --- notes/0.13.11.markdown | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/notes/0.13.11.markdown b/notes/0.13.11.markdown index 0d8d2debd..3b9d369a8 100644 --- a/notes/0.13.11.markdown +++ b/notes/0.13.11.markdown @@ -89,10 +89,13 @@ [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 -- 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] 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] @@ -120,6 +123,7 @@ - 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 @@ -152,6 +156,7 @@ - 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] - 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