**Problem**
When using scala-native, we can't enable semanticdb etc
because of the platform-level platform.
**Solution**
Since compilerPlugin(...) is always going to be JVM,
just add an explicit JVM platform to the given ModuleID.
* Add Test configuration to evictionWarningOptions
* Add Test configuration to default evictionWarningOptions
* Deduplicate eviction errors based on callers.
* Update eviction error test for semantic versioning.
* Group evictions by configuration and update test.
**Problem**
When managedScalaInstance is set to false, we stopped creating
ScalaInstance, but the documentation says the user can
pull in their own dependencies.
**Solution**
Attempt to construct a ScalaInstance from update report
even when managedScalaInstance is set to false.
- Cache AutoPlugin.projectSettings and projectConfigurations via AutoPluginCache so they are evaluated once per plugin instance during build loading, not once per subproject (N×M → M)
- Make GroupedAutoPlugins.globalSettings a lazy val and pre-compute buildSettingsMap to avoid repeated aggregation
Rather than using the FileConverter to replace virtual paths, this uses the rootPaths directly. It only replaces a virtual path in a scalac option if the given segment of the option begins with the root path key.
**Problem**
consoleProject does not work with Scala 3 because the compiler bridge
does not implement REPL binding injection (scala/scala3#5069).
The bindings currentState, extracted, and cpHelpers are never
injected into the REPL session, causing Not found errors.
**Solution**
Work around the missing binding support by storing the three runtime
objects in a static holder (ConsoleProjectBindings) before launching
the REPL, and generating val definitions via initialCommands that
read from the holder. The original bindings are still passed to
Console to preserve Scala 2 backward compatibility.
Pass -Xrepl-interrupt-instrumentation:local to the REPL when the
consoleProject scala instance is 3.8 or newer. In local mode the
instrumented loader skips re-defining classpath classes and falls
through to standard parent-first delegation, so REPL code sees the
same singleton sbt.* and scala.* classes as the surrounding sbt
process — while still keeping interrupt support for REPL-defined code,
preserving Ctrl+C on long-running expressions like
(Compile / compile).eval.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test report listeners now receive testEvent callbacks as the underlying test framework emits events, instead of only after a whole group finishes. startGroup / endGroup timing is aligned with that streaming model for both in-process and forked test runs.
No public API changes - only listener callback timing and the internal worker <-> sbt JSON-RPC protocol.
Fixes#3137. Adds discoverable English-name alternatives for the symbolic
cross-build commands using the | parser combinator, making them more
beginner-friendly without adding separate commands.
**Problem**
Intermittent java.nio.file.FileAlreadyExistsException when publishing
classes.sbtdir.zip during action-cache packaging under parallel tasks
(#9043). Copying from a temp directory straight into the final path races
on the fixed destination name.
**Solution**
Stage the built zip next to the destination with a unique temp file, then
replace the final path via Files.move with REPLACE_EXISTING and ATOMIC_MOVE,
falling back to a non-atomic move when needed. Add a concurrent
packageDirectory test.
Closes#9043
Generated-by: Cursor (AI-assisted)
**Problem**
In sbt 2.x, if we execute a run task from the shell,
and if the program fails, it ends up taking down the entire shell
because client-side run rethrows, which is not desirable
for the sbt shell.
**Solution**
1. Omit printing out success for ClientJobParams, which is the runinfo.
2. Print out success or error on the client-side for shell usage case.
In sbt 2.x, running batch commands through the thin client (sbtn) suppresses stack traces for all tasks because the server's shell command unconditionally sets state.interactive = true. This causes LogManager.defaultTraceLevel to return -1 (suppressed) even when the client explicitly signals non-interactive (batch) mode via Attach(interactive=false).
This fixes the shell command to check the originating NetworkChannel's interactive flag before setting state.interactive, so thin client batch commands correctly get Int.MaxValue trace level and display full stack traces.
**Problem**
PomGenerator (introduced in #8873) was missing <description> and <url>
elements that the old Ivy-based MakePom included. Setting `description`
and `homepage` in build.sbt had no effect on the generated pom.xml.
**Solution**
Add makeDescription and makeHomePage helpers to PomGenerator, matching
the behavior of MakePom. Add test assertions for both fields.
Fixes#9054
**Problem**
When a file referenced during cache serialization is deleted between task
execution and cache storage, sbt crashes with an uncaught NoSuchFileException.
The IOException catch added in #8699 only wraps store.put(), but
Converter.toJsonUnsafe(result) and mkInput() also call
hashedVirtualFileRefToStr which calls Files.readAttributes — and these are
outside the try-catch.
**Solution**
Move the try/catch IOException to wrap the entire post-action cache storage
section, so NoSuchFileException from result serialization or cache key
computation is caught and handled gracefully (skip caching, return result).
Fixes#9044
Co-authored-by: bittoby <218712309+bittoby@users.noreply.github.co>
The fallback ServerHandler silently dropped requests with unknown
methods, violating the JSON-RPC spec. Clients like Metals that send
unrecognized requests would never receive a response, potentially
causing timeouts or hangs.
Return a -32601 (Method not found) error response instead.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the download URL returns an HTTP error (e.g. 404), curl without
--fail exits 0 and saves the error page HTML as the jar file. This
leaves a corrupt jar that causes confusing errors on subsequent runs.
With --fail, curl returns a non-zero exit code on HTTP errors and
does not write the response body to the output file.
Fixes#6654
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
**problem**
.previous was implemented as an inline expansion to wrapInitTask(Previous.runtime(in)(<instance of JsonFormat[A1]))
For example, the .previous on taskKey[String] gets inlined like
this, and then sbt's macro moves `Previous.runtime(...)(using StringJsonFormat)` into task input.
lazy val fingerprints = taskKey[String]("...")
val previousFingerprints = fingerprints.previous
// inlined
val previousFingerprints: Option[String] = {
InputWrapper.wrapInitTask(
Previous.runtime(...)(using StringJsonFormat)
)
}
- 6c8ee6ea37/main-settings/src/main/scala/sbt/Def.scala (L410-L412)
- 6c8ee6ea37/core-macros/src/main/scala/sbt/internal/util/appmacro/Cont.scala (L468)
However, if the return type of task is a bit more complicated like
Seq[String], it doesn't work:
Scala 3 Compiler's inliner creates a synthetic proxy symbol if the
inlining tree is an application, whose arguments are unstable path.
For example,
lazy val fingerprints = taskKey[Seq[String]]("...")
val previousFingerprints = fingerprints.previous
// inline to
val previousFingerprints: Option[Seq[String]] = {
val x$2$proxy1 = immSeqFormat(StringJsonFormat)
InputWrapper.wrapInitTask(
Previous.runtime(...)(using x$2$proxy1)
)
}
cc7d6db700/compiler/src/dotty/tools/dotc/inlines/Inliner.scala (L324-L329)
However, sbt2's Cont macro captures only `Previous.runtime(...)(using x$2$proxy1)`, while it doesn't capture the proxy definition. Consequently, while sbt macro moves the `Previous.runtime(...)` application as a task input, the proxy definition is left in the task body.
mapN(
(
link / fingerprints,
Previous.runtime(...)(using x$2$proxy1) // here x$2$proxy1 can't be found
)
) {
...
val x$2$proxy1 = ...
}
Then we get:
-- Error: /.../build.sbt:14:59
14 | val previousFingerprints = (link / fingerprints).previous
| ^
|While expanding a macro, a reference to value x$2$proxy1 was used outside the scope where it was defined
**How this PR fixed**
This commit fixes the problem by defining a dedicated Scala3 macro for .previous that summon JsonFormat[A1] inside the macro before constructing the wrapped previous.runtime(...)(using ...) by inliner. The macro insert the found given value tree directly into the previous.runtime(...)(using $found).
This way, Cont macro always moves the Previous.runtime tree along with it's given argument, without leaking compiler-generated inline proxies across scopes.