Skip to content

Commit a8b6296

Browse files
Merge pull request #115 from alexarchambault/merge-upstream
Merge upstream changes
2 parents b913e57 + 1413c20 commit a8b6296

File tree

7 files changed

+207
-29
lines changed

7 files changed

+207
-29
lines changed

backend/src/main/scala/bloop/CompilerCache.scala

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import javax.tools.{JavaCompiler => JavaxCompiler}
1616
import scala.collection.mutable.HashSet
1717
import scala.concurrent.ExecutionContext
1818

19+
import bloop.CompilerCache.JavacKey
1920
import bloop.io.AbsolutePath
2021
import bloop.io.Paths
2122
import bloop.logging.Logger
@@ -43,21 +44,24 @@ import xsbti.compile.ScalaCompiler
4344
import xsbti.{Logger => XLogger}
4445
import xsbti.{Reporter => XReporter}
4546

47+
object CompilerCache {
48+
final case class JavacKey(javacBin: Option[AbsolutePath], allowLocal: Boolean)
49+
}
4650
final class CompilerCache(
4751
componentProvider: ComponentProvider,
4852
retrieveDir: AbsolutePath,
4953
logger: Logger,
5054
userResolvers: List[Resolver],
5155
userScalaCache: Option[ConcurrentHashMap[ScalaInstance, ScalaCompiler]],
52-
userJavacCache: Option[ConcurrentHashMap[Option[AbsolutePath], JavaCompiler]],
56+
userJavacCache: Option[ConcurrentHashMap[JavacKey, JavaCompiler]],
5357
scheduler: ExecutionContext
5458
) {
5559

5660
private val scalaCompilerCache =
5761
userScalaCache.getOrElse(new ConcurrentHashMap[ScalaInstance, ScalaCompiler]())
5862

5963
private val javaCompilerCache =
60-
userJavacCache.getOrElse(new ConcurrentHashMap[Option[AbsolutePath], JavaCompiler]())
64+
userJavacCache.getOrElse(new ConcurrentHashMap[JavacKey, JavaCompiler]())
6165

6266
def get(
6367
scalaInstance: ScalaInstance,
@@ -69,8 +73,12 @@ final class CompilerCache(
6973
getScalaCompiler(_, componentProvider)
7074
)
7175

76+
val allowLocal = !hasRuntimeJavacOptions(javacOptions)
7277
val javaCompiler =
73-
javaCompilerCache.computeIfAbsent(javacBin, getJavaCompiler(logger, _, javacOptions))
78+
javaCompilerCache.computeIfAbsent(
79+
JavacKey(javacBin, allowLocal),
80+
key => getJavaCompiler(logger, key.javacBin, javacOptions)
81+
)
7482

7583
val javaDoc = Javadoc.local.getOrElse(Javadoc.fork())
7684
val javaTools = JavaTools(javaCompiler, javaDoc)
@@ -94,7 +102,7 @@ final class CompilerCache(
94102
javacBin: Option[AbsolutePath],
95103
javacOptions: List[String]
96104
): JavaCompiler = {
97-
val allowLocal = !javacOptions.exists(_.startsWith("-J"))
105+
val allowLocal = !hasRuntimeJavacOptions(javacOptions)
98106
javacBin match {
99107
case Some(bin) if JavaRuntime.javac.exists(isSameCompiler(logger, _, bin)) =>
100108
// Same bin as the one derived from this VM? Prefer built-in compiler if JDK
@@ -400,4 +408,8 @@ final class CompilerCache(
400408
false
401409
}
402410
}
411+
412+
private def hasRuntimeJavacOptions(javacOptions: List[String]): Boolean = {
413+
javacOptions.exists(_.startsWith("-J"))
414+
}
403415
}

backend/src/main/scala/sbt/internal/inc/bloop/internal/BloopNameHashing.scala

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package sbt.internal.inc.bloop.internal
22

3+
import scala.collection.parallel.immutable.ParVector
4+
35
import _root_.bloop.UniqueCompileInputs
46
import _root_.bloop.tracing.BraveTracer
57
import monix.eval.Task
@@ -178,9 +180,16 @@ private final class BloopNameHashing(
178180
}
179181
}
180182
}
183+
val removedProducts =
184+
lookup.removedProducts(previousAnalysis).getOrElse {
185+
new ParVector(previous.allProducts.toVector)
186+
.filter(p => {
187+
!equivS.equiv(previous.product(p), stamps.product(p))
188+
})
189+
.toVector
190+
.toSet
191+
}
181192

182-
// Unnecessary to compute removed products because we can ensure read-only classes dir is untouched
183-
val removedProducts = Set.empty[VirtualFileRef]
184193
val changedBinaries: Set[VirtualFileRef] = tracer.traceVerbose("changed binaries") { _ =>
185194
lookup.changedBinaries(previousAnalysis).getOrElse {
186195
val detectChange = IncrementalCommon.isLibraryModified(

backend/src/test/scala/bloop/CompilerCacheSpec.scala

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import scala.concurrent.ExecutionContext
1212

1313
import bloop.io.AbsolutePath
1414
import bloop.io.Paths
15+
import bloop.logging.RecordingLogger
1516

1617
import org.junit.Assert._
1718
import org.junit.Test
1819
import org.junit.experimental.categories.Category
20+
import sbt.internal.inc.BloopComponentCompiler
1921
import sbt.internal.inc.javac.WriteReportingJavaFileObject
2022
import sbt.io.syntax.File
2123
import xsbti.compile.ClassFileManager
@@ -97,4 +99,53 @@ class CompilerCacheSpec {
9799
}
98100
}
99101

102+
@Test
103+
def noOptionsSameCompiler(): Unit = withCompilerCache { compilerCache =>
104+
val scalaInstance = ScalaInstance.resolve(
105+
"org.scala-lang",
106+
"scala-compiler",
107+
bloop.internal.build.BloopScalaInfo.scalaVersion,
108+
new RecordingLogger()
109+
)
110+
111+
val javac0 = compilerCache.get(scalaInstance, None, Nil).javaTools().javac()
112+
val javac1 = compilerCache.get(scalaInstance, None, Nil).javaTools().javac()
113+
assertTrue(javac0 + " was not eq to " + javac1, javac0 eq javac1)
114+
}
115+
116+
@Test
117+
def runtimeOptionsNeverLocal(): Unit = withCompilerCache { compilerCache =>
118+
val scalaInstance = ScalaInstance.resolve(
119+
"org.scala-lang",
120+
"scala-compiler",
121+
bloop.internal.build.BloopScalaInfo.scalaVersion,
122+
new RecordingLogger()
123+
)
124+
125+
// We first populate the compiler cache with a compiler that may be local.
126+
val javac0 = compilerCache.get(scalaInstance, None, Nil).javaTools().javac()
127+
val javac1 = compilerCache.get(scalaInstance, None, List("-J-Dfoo=bar")).javaTools().javac()
128+
129+
assertTrue(
130+
s"`javac1` was not a forked compiler, despite the runtime flag: ${javac0.getClass}",
131+
javac1.isInstanceOf[compilerCache.BloopForkedJavaCompiler]
132+
)
133+
}
134+
135+
private def withCompilerCache(op: CompilerCache => Unit): Unit = {
136+
val tempDir = AbsolutePath(Files.createTempDirectory("compiler-cache-spec"))
137+
try {
138+
val ec = ExecutionContext.global
139+
val logger = new RecordingLogger()
140+
val componentProvider =
141+
BloopComponentCompiler.getComponentProvider(tempDir.resolve("components"))
142+
val compilerCache =
143+
new CompilerCache(componentProvider, tempDir, logger, List.empty, None, None, ec)
144+
op(compilerCache)
145+
} finally {
146+
Paths.delete(tempDir)
147+
}
148+
149+
}
150+
100151
}

bridges/scalajs-1/src/main/scala/bloop/scalajs/JsBridge.scala

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package bloop.scalajs
22

33
import java.nio.file.Path
44

5+
import scala.collection.concurrent.TrieMap
56
import scala.concurrent.Await
67
import scala.concurrent.ExecutionContext
78
import scala.concurrent.duration.Duration
9+
import scala.ref.SoftReference
810

911
import bloop.config.Config.JsConfig
1012
import bloop.config.Config.LinkerMode
@@ -51,6 +53,40 @@ object JsBridge {
5153
}
5254
override def trace(t: => Throwable): Unit = logger.trace(t)
5355
}
56+
private object ScalaJSLinker {
57+
private val cache = TrieMap.empty[Path, SoftReference[(JsConfig, Linker)]]
58+
def reuseOrCreate(config: JsConfig, target: Path): Linker =
59+
if (config.mode == LinkerMode.Release) createLinker(config)
60+
else
61+
cache.get(target) match {
62+
case Some(SoftReference((`config`, linker))) => linker
63+
case _ =>
64+
val newLinker = createLinker(config)
65+
cache.update(target, SoftReference((config, newLinker)))
66+
newLinker
67+
}
68+
private def createLinker(config: JsConfig): Linker = {
69+
val isFullLinkJS = config.mode == LinkerMode.Release
70+
val semantics =
71+
if (isFullLinkJS) Semantics.Defaults.optimized
72+
else Semantics.Defaults
73+
val scalaJSModuleKind = config.kind match {
74+
case ModuleKindJS.NoModule => ScalaJSModuleKind.NoModule
75+
case ModuleKindJS.CommonJSModule => ScalaJSModuleKind.CommonJSModule
76+
case ModuleKindJS.ESModule => ScalaJSModuleKind.ESModule
77+
}
78+
79+
val useClosure = isFullLinkJS && config.kind != ModuleKindJS.ESModule
80+
81+
val linkerConfig = StandardConfig()
82+
.withClosureCompiler(useClosure)
83+
.withSemantics(semantics)
84+
.withModuleKind(scalaJSModuleKind)
85+
.withSourceMap(config.emitSourceMaps)
86+
87+
StandardImpl.clearableLinker(linkerConfig)
88+
}
89+
}
5490

5591
def link(
5692
config: JsConfig,
@@ -64,17 +100,7 @@ object JsBridge {
64100
): Unit = {
65101
implicit val ec = executionContext
66102
implicit val logFilter: DebugFilter = DebugFilter.Link
67-
val enableOptimizer = config.mode == LinkerMode.Release
68-
val semantics = config.mode match {
69-
case LinkerMode.Debug => Semantics.Defaults
70-
case LinkerMode.Release => Semantics.Defaults.optimized
71-
}
72-
73-
val moduleKind = config.kind match {
74-
case ModuleKindJS.NoModule => ScalaJSModuleKind.NoModule
75-
case ModuleKindJS.CommonJSModule => ScalaJSModuleKind.CommonJSModule
76-
case ModuleKindJS.ESModule => ScalaJSModuleKind.ESModule
77-
}
103+
val linker = ScalaJSLinker.reuseOrCreate(config, target)
78104

79105
val cache = StandardImpl.irFileCache().newCache
80106
val irContainersPairs = PathIRContainer.fromClasspath(classpath)
@@ -101,18 +127,10 @@ object JsBridge {
101127
}
102128

103129
val output = LinkerOutput(PathOutputFile(target))
104-
val jsConfig = StandardConfig()
105-
.withOptimizer(enableOptimizer)
106-
.withClosureCompilerIfAvailable(enableOptimizer)
107-
.withSemantics(semantics)
108-
.withModuleKind(moduleKind)
109-
.withSourceMap(config.emitSourceMaps)
110130

111131
val resultFuture = for {
112132
libraryIRs <- libraryIrsFuture
113-
_ <- StandardImpl
114-
.linker(jsConfig)
115-
.link(libraryIRs, moduleInitializers, output, new Logger(logger))
133+
_ <- linker.link(libraryIRs, moduleInitializers, output, new Logger(logger))
116134
} yield ()
117135

118136
Await.result(resultFuture, Duration.Inf)

frontend/src/test/scala/bloop/BaseCompileSpec.scala

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ abstract class BaseCompileSpec extends bloop.testing.BaseSuite {
463463
| public void entrypoint(String[] args) {
464464
| A$ a = A$.MODULE$;
465465
| System.out.println(a.HelloWorld());
466-
| }
466+
| }
467467
|}""".stripMargin
468468
val `C.scala` =
469469
"""/C.scala
@@ -1829,4 +1829,50 @@ abstract class BaseCompileSpec extends bloop.testing.BaseSuite {
18291829
assertExitStatus(compiledState, ExitStatus.Ok)
18301830
}
18311831
}
1832+
1833+
test("detects removed products") {
1834+
TestUtil.withinWorkspace { workspace =>
1835+
object Sources {
1836+
val `A.scala` =
1837+
"""/a/A.scala
1838+
|package a
1839+
|class A
1840+
""".stripMargin
1841+
1842+
val `B.scala` =
1843+
"""/a/B.scala
1844+
|package a
1845+
|class B extends A
1846+
""".stripMargin
1847+
1848+
val `B2.scala` =
1849+
"""/a/B.scala
1850+
|package a
1851+
|class B extends A {
1852+
| def foo: Int = ???
1853+
|}
1854+
""".stripMargin
1855+
}
1856+
val logger = new RecordingLogger(ansiCodesSupported = false)
1857+
val `A` = TestProject(workspace, "a", List(Sources.`A.scala`, Sources.`B.scala`))
1858+
1859+
val projects = List(`A`)
1860+
val state = loadState(workspace, projects, logger)
1861+
1862+
val firstState = state.compile(`A`)
1863+
assertExitStatus(firstState, ExitStatus.Ok)
1864+
1865+
writeFile(`A`.srcFor("a/B.scala"), Sources.`B2.scala`)
1866+
def deleteAProduct(classesDir: AbsolutePath): Unit = {
1867+
val productA = classesDir.resolve("a").resolve("A.class")
1868+
Files.delete(productA.underlying)
1869+
}
1870+
1871+
deleteAProduct(firstState.getLastClassesDir(`A`).get)
1872+
1873+
val secondState = firstState.compile(`A`)
1874+
assertExitStatus(secondState, ExitStatus.Ok)
1875+
1876+
}
1877+
}
18321878
}

notes/v1.5.3.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# bloop `v1.5.3`
2+
3+
Bloop v1.5.3 is a bugfix release.
4+
5+
## Installing Bloop
6+
7+
For more details about installing Bloop, please see
8+
[Bloop's Installation Guide](https://scalacenter.github.io/bloop/setup))
9+
10+
## Merged pull requests
11+
12+
Here's a list of pull requests that were merged:
13+
14+
- Add sbt-vspp for publishing the BLOOP SBT plug-in in a Maven-consistent format
15+
[#1766]
16+
- Fix: limit the amount of logs that launcher keeps in memory [#1764]
17+
- Stop shading stuff in sbt-bloop plugins [#1754]
18+
- Cache ScalaJS linkers for incremental linking [#1761]
19+
- Don't give a local compiler when disallowed [#1762]
20+
- Bump dependency submission [#1760]
21+
- Bump debug adapter library to 2.2.0 [#1758]
22+
- Correctly pick up test-jar dependency sources [#1756]
23+
- Sbt-bloop and buildpress don't depend on launcher [#1751]
24+
- Fix resolution of test-jar artifacts [#1747]
25+
26+
[#1766]: https://github.com/scalacenter/bloop/pull/1766
27+
[#1764]: https://github.com/scalacenter/bloop/pull/1764
28+
[#1754]: https://github.com/scalacenter/bloop/pull/1754
29+
[#1761]: https://github.com/scalacenter/bloop/pull/1761
30+
[#1762]: https://github.com/scalacenter/bloop/pull/1762
31+
[#1760]: https://github.com/scalacenter/bloop/pull/1760
32+
[#1758]: https://github.com/scalacenter/bloop/pull/1758
33+
[#1756]: https://github.com/scalacenter/bloop/pull/1756
34+
[#1751]: https://github.com/scalacenter/bloop/pull/1751
35+
[#1747]: https://github.com/scalacenter/bloop/pull/1747
36+
37+
## Contributors
38+
39+
According to `git shortlog -sn --no-merges v1.5.2..v1.5.3`, the following people
40+
have contributed to this `v1.5.3` release: Adrien Piquerez, Alexandre
41+
Archambault, Anton Sviridov, Lorenzo Gabriele, Martin Duhem, ScalaWilliam,
42+
Tomasz Godzik, Vadim Chelyshov.

project/Dependencies.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object Dependencies {
1111
val javaDebugVersion = "0.21.0+1-7f1080f1"
1212

1313
val scalazVersion = "7.2.20"
14-
val lmVersion = "1.0.0"
14+
val lmVersion = "1.1.5"
1515
val caseAppVersion = "2.0.6"
1616
val sourcecodeVersion = "0.1.4"
1717
val sbtTestInterfaceVersion = "1.0"
@@ -30,7 +30,7 @@ object Dependencies {
3030
val zipkinSenderVersion = "2.7.15"
3131
val asmVersion = "7.0"
3232
val snailgunVersion = "0.4.1-sc2"
33-
val debugAdapterVersion = "2.2.0-M3"
33+
val debugAdapterVersion = "2.2.0"
3434
val coursierInterfaceVersion = "1.0.7"
3535

3636
import sbt.librarymanagement.syntax.stringToOrganization

0 commit comments

Comments
 (0)