Default to cached task

This flips the default `:=` operation to the cached task.
To opt out of the cache, use `Def.uncached(...)` or
mark the key with `@cacheLevel(include = Array.empty)`
This commit is contained in:
Eugene Yokota 2025-06-09 02:04:42 -04:00
parent 580c357124
commit 6a7b56a645
103 changed files with 781 additions and 503 deletions

View File

@ -94,17 +94,25 @@ trait Cont:
import conv.qctx import conv.qctx
import qctx.reflect.* import qctx.reflect.*
given qctx.type = qctx given qctx.type = qctx
def msg: String =
s"given evidence sjsonnew.HashWriter[${TypeRepr.of[A].show}] is not found; " +
"opt out of caching by annotating the key with @cacheLevel(include = Array.empty), or as" +
"foo := Def.uncached(...), or provide a given value"
Expr Expr
.summon[HashWriter[A]] .summon[HashWriter[A]]
.getOrElse(sys.error(s"HashWriter[A] not found for ${TypeRepr.of[A].show}")) .getOrElse(report.errorAndAbort(msg))
def summonJsonFormat[A: Type]: Expr[JsonFormat[A]] = def summonJsonFormat[A: Type]: Expr[JsonFormat[A]] =
import conv.qctx import conv.qctx
import qctx.reflect.* import qctx.reflect.*
given qctx.type = qctx given qctx.type = qctx
def msg: String =
s"given evidence sjsonnew.JsonFormat[${TypeRepr.of[A].show}] is not found; " +
"opt out of caching by annotating the key with @cacheLevel(include = Array.empty), or as" +
"foo := Def.uncached(...), or provide a given value"
Expr Expr
.summon[JsonFormat[A]] .summon[JsonFormat[A]]
.getOrElse(sys.error(s"JsonFormat[A] not found for ${TypeRepr.of[A].show}")) .getOrElse(report.errorAndAbort(msg))
def summonClassTag[A: Type]: Expr[ClassTag[A]] = def summonClassTag[A: Type]: Expr[ClassTag[A]] =
import conv.qctx import conv.qctx
@ -112,7 +120,7 @@ trait Cont:
given qctx.type = qctx given qctx.type = qctx
Expr Expr
.summon[ClassTag[A]] .summon[ClassTag[A]]
.getOrElse(sys.error(s"ClassTag[A] not found for ${TypeRepr.of[A].show}")) .getOrElse(report.errorAndAbort(s"ClassTag[A] not found for ${TypeRepr.of[A].show}"))
/** /**
* Implementation of a macro that provides a direct syntax for applicative functors and monads. * Implementation of a macro that provides a direct syntax for applicative functors and monads.
@ -334,7 +342,11 @@ trait Cont:
cacheConfigExpr: Expr[BuildWideCacheConfiguration], cacheConfigExpr: Expr[BuildWideCacheConfiguration],
tags: List[CacheLevelTag], tags: List[CacheLevelTag],
)(body: Expr[A1], input: Expr[A2]): Expr[A1] = )(body: Expr[A1], input: Expr[A2]): Expr[A1] =
val codeContentHash = Expr[Long](body.show.##) val codeContentHash =
try Expr[Long](body.show.##)
catch
case e: Throwable =>
Expr[Long](Printer.TreeStructure.show(body.asTerm).##)
val extraHash = Expr[Long](0L) val extraHash = Expr[Long](0L)
val aJsonFormat = summonJsonFormat[A1] val aJsonFormat = summonJsonFormat[A1]
val aClassTag = summonClassTag[A1] val aClassTag = summonClassTag[A1]

View File

@ -102,6 +102,28 @@ trait ContextUtil[C <: Quotes & scala.Singleton](val valStart: Int):
case Apply(_, List(arg)) => extractTags(arg) case Apply(_, List(arg)) => extractTags(arg)
case _ => extractTags0(tree) case _ => extractTags0(tree)
def cacheLevels(tree: Term): Seq[CacheLevelTag] =
tree.underlying match
// handles foo / bar cases
case Apply(TypeApply(_, _), List(t @ Ident(_))) =>
t.symbol.getAnnotation(cacheLevelSym) match
case Some(_) => cacheLevelsForSym(t.symbol)
case None => CacheLevelTag.all.toList
case u =>
u.symbol.getAnnotation(cacheLevelSym) match
case Some(_) => cacheLevelsForSym(u.symbol)
case None => CacheLevelTag.all.toList
def cacheLevelsForSym(sym: Symbol): Seq[CacheLevelTag] =
sym.getAnnotation(cacheLevelSym) match
case Some(annot) =>
annot.asExprOf[cacheLevel] match
case '{ cacheLevel(include = Array.empty[CacheLevelTag](using $_)) } => Nil
case '{ cacheLevel(include = Array[CacheLevelTag]($include*)) } =>
include.value.get
case _ => report.errorAndAbort(Printer.TreeStructure.show(annot) + " does not match")
case None => CacheLevelTag.all.toList
enum OutputType: enum OutputType:
case File case File
case Directory case Directory
@ -178,5 +200,15 @@ end ContextUtil
object ContextUtil: object ContextUtil:
def appendScalacOptions(options: Seq[String]): Unit = def appendScalacOptions(options: Seq[String]): Unit =
Attic.appendItems(options.asJava); Attic.appendItems(options.asJava)
def isTaskCacheByDefault: Boolean =
val atticValues = Attic.getItems().asScala.toSet
val noDefaultMacroSetting = atticValues.contains("-Xmacro-settings:sbt:no-default-task-cache")
!noDefaultMacroSetting
end ContextUtil end ContextUtil
class ContextUtil0[C <: Quotes & scala.Singleton](override val qctx: C, valStart: Int)
extends ContextUtil[C](valStart):
// import qctx.reflect.*
end ContextUtil0

View File

@ -20,7 +20,8 @@ import sbt.util.{
AggregateActionCacheStore, AggregateActionCacheStore,
BuildWideCacheConfiguration, BuildWideCacheConfiguration,
cacheLevel, cacheLevel,
DiskActionCacheStore DiskActionCacheStore,
Uncached,
} }
import Util.* import Util.*
import sbt.util.Show import sbt.util.Show
@ -301,6 +302,9 @@ object Def extends BuildSyntax with Init with InitializeImplicits:
inline def cachedTask[A1](inline a1: A1): Def.Initialize[Task[A1]] = inline def cachedTask[A1](inline a1: A1): Def.Initialize[Task[A1]] =
${ TaskMacro.taskMacroImpl[A1]('a1, cached = true) } ${ TaskMacro.taskMacroImpl[A1]('a1, cached = true) }
inline def uncachedTask[A1](inline a1: A1): Def.Initialize[Task[A1]] =
${ TaskMacro.taskMacroImpl[A1]('a1, cached = false) }
inline def task[A1](inline a1: A1): Def.Initialize[Task[A1]] = inline def task[A1](inline a1: A1): Def.Initialize[Task[A1]] =
${ TaskMacro.taskMacroImpl[A1]('a1, cached = false) } ${ TaskMacro.taskMacroImpl[A1]('a1, cached = false) }
@ -465,6 +469,11 @@ object Def extends BuildSyntax with Init with InitializeImplicits:
private[sbt] def isDummy(t: Task[?]): Boolean = private[sbt] def isDummy(t: Task[?]): Boolean =
t.get(isDummyTask).getOrElse(false) t.get(isDummyTask).getOrElse(false)
/**
* Marker function to make the task uncached.
*/
inline def uncached[A1](inline a: A1): A1 = Uncached(a)
end Def end Def
sealed trait InitializeImplicits { self: Def.type => sealed trait InitializeImplicits { self: Def.type =>

View File

@ -157,6 +157,9 @@ sealed abstract class TaskKey[A1]
private[sbt] final inline def rescope(scope: Scope): TaskKey[A1] = private[sbt] final inline def rescope(scope: Scope): TaskKey[A1] =
Scoped.scopedTask(Scope.replaceThis(this.scope)(scope), this.key) Scoped.scopedTask(Scope.replaceThis(this.scope)(scope), this.key)
/**
* Appends a single value to the task key.
*/
inline def +=[A2](inline v: A2)(using Append.Value[A1, A2]): Setting[Task[A1]] = inline def +=[A2](inline v: A2)(using Append.Value[A1, A2]): Setting[Task[A1]] =
append1[A2](taskMacro(v)) append1[A2](taskMacro(v))
@ -165,6 +168,9 @@ sealed abstract class TaskKey[A1]
): Setting[Task[A1]] = ): Setting[Task[A1]] =
make(v)(ev.appendValue) make(v)(ev.appendValue)
/**
* Appends a sequence of values to the task key.
*/
inline def ++=[A2](inline vs: A2)(using Append.Values[A1, A2]): Setting[Task[A1]] = inline def ++=[A2](inline vs: A2)(using Append.Values[A1, A2]): Setting[Task[A1]] =
appendN(taskMacro[A2](vs)) appendN(taskMacro[A2](vs))
@ -427,8 +433,8 @@ object Scoped:
sealed trait DefinableTask[A1] { self: TaskKey[A1] => sealed trait DefinableTask[A1] { self: TaskKey[A1] =>
/** Internal function for the task macro. */ /** Internal function for the task macro. */
inline def taskMacro[A](inline a: A): Initialize[Task[A]] = inline def taskMacro[A2](inline a: A2): Initialize[Task[A2]] =
${ TaskMacro.taskMacroImpl[A]('a, cached = false) } ${ TaskMacro.taskMacroImpl[A2]('a, 'this) }
private[sbt] inline def :==(app: A1): Setting[Task[A1]] = private[sbt] inline def :==(app: A1): Setting[Task[A1]] =
set(Def.valueStrict(std.TaskExtra.constant(app))) set(Def.valueStrict(std.TaskExtra.constant(app)))

View File

@ -15,10 +15,9 @@ import sbt.internal.util.appmacro.{
Cont, Cont,
// Instance, // Instance,
// LinterDSL, // LinterDSL,
// MixedBuilder, ContextUtil,
// MonadInstance ContextUtil0,
} }
// import Instance.Transform
import sbt.internal.util.{ LinePosition, NoPosition, SourcePosition } import sbt.internal.util.{ LinePosition, NoPosition, SourcePosition }
import language.experimental.macros import language.experimental.macros
@ -49,6 +48,42 @@ object TaskMacro:
// import LinterDSL.{ Empty => EmptyLinter } // import LinterDSL.{ Empty => EmptyLinter }
def taskMacroImpl[A1: Type](t: Expr[A1], key: Expr[TaskKey[?]])(using
qctx: Quotes
): Expr[Initialize[Task[A1]]] =
import qctx.reflect.*
var isUncacheApplied = false
object appTransformer extends TreeMap:
override def transformTerm(tree: Term)(owner: Symbol): Term =
tree match
case Apply(TypeApply(s @ Select(Ident("Uncached"), "apply"), targ :: Nil), qual :: Nil)
if "sbt.util.Uncached$.apply" == s.symbol.fullName =>
isUncacheApplied = true
super.transformTerm(tree)(owner)
case _ =>
super.transformTerm(tree)(owner)
end appTransformer
val _ = appTransformer.transformTerm(t.asTerm)(Symbol.spliceOwner)
val cu0 = ContextUtil0(qctx, 0)
val cl = cu0.cacheLevels(key.asTerm)
val cached = ContextUtil.isTaskCacheByDefault && !isUncacheApplied && cl.nonEmpty
t match
case '{ if ($cond) then $thenp else $elsep } => taskIfImpl[A1](t, cached)
case _ =>
val convert1 = new FullConvert(qctx, 0)
if cached then
convert1.contMapN[A1, F, Id](
t,
convert1.appExpr,
Some('{
InputWrapper.`wrapInitTask_\u2603\u2603`[BuildWideCacheConfiguration](
Def.cacheConfiguration
)
})
)
else convert1.contMapN[A1, F, Id](t, convert1.appExpr, None)
def taskMacroImpl[A1: Type](t: Expr[A1], cached: Boolean)(using def taskMacroImpl[A1: Type](t: Expr[A1], cached: Boolean)(using
qctx: Quotes qctx: Quotes
): Expr[Initialize[Task[A1]]] = ): Expr[Initialize[Task[A1]]] =

View File

@ -10,6 +10,7 @@ package sbt.test
import java.io.File import java.io.File
import sjsonnew.* import sjsonnew.*
import sbt.Def
import sbt.Def.{ Setting, inputKey, settingKey, taskKey } import sbt.Def.{ Setting, inputKey, settingKey, taskKey }
import sbt.Scope.Global import sbt.Scope.Global
import sbt.ScopeAxis.Zero import sbt.ScopeAxis.Zero
@ -56,7 +57,7 @@ object SlashSyntaxTest extends sbt.SlashSyntax {
Compile / bar := { Compile / bar := {
(Compile / foo).previous.getOrElse(2) (Compile / foo).previous.getOrElse(2)
}, },
Test / buildInfo := Nil, Test / buildInfo := Def.uncached(Nil),
baz := { baz := {
val _ = (Test / buildInfo).taskValue val _ = (Test / buildInfo).taskValue
(Compile / run).evaluated (Compile / run).evaluated

View File

@ -73,7 +73,7 @@ object Assign {
// ak += z.value + (if (y.value) set.value else plain.value), // ak += z.value + (if (y.value) set.value else plain.value),
ck := new File(ck.value, "asdf"), ck := new File(ck.value, "asdf"),
ak := sk.value.size, ak := Def.uncached(sk.value.size),
// bk ++= Seq(z.value) // bk ++= Seq(z.value)
intTask := ak.previous.get, intTask := ak.previous.get,
bgList := { mk.value.toString.toList.map(_.toInt) }, bgList := { mk.value.toString.toList.map(_.toInt) },

View File

@ -399,12 +399,12 @@ object Cross {
val scope = Scope(Select(project), Zero, Zero, Zero) val scope = Scope(Select(project), Zero, Zero, Zero)
instance match { instance match {
case Some((home, inst)) => case Some((home, inst1)) =>
Seq( Seq(
scope / scalaVersion := version, scope / scalaVersion := version,
scope / crossScalaVersions := scalaVersions, scope / crossScalaVersions := scalaVersions,
scope / scalaHome := Some(home), scope / scalaHome := Some(home),
scope / scalaInstance := inst, scope / scalaInstance := Def.uncached(inst1),
) )
case None => case None =>
Seq( Seq(

File diff suppressed because it is too large Load Diff

View File

@ -629,7 +629,7 @@ object EvaluateTask {
// if the return type Seq[Setting[_]] is not explicitly given, scalac hangs // if the return type Seq[Setting[_]] is not explicitly given, scalac hangs
val injectStreams: ScopedKey[?] => Seq[Setting[?]] = scoped => val injectStreams: ScopedKey[?] => Seq[Setting[?]] = scoped =>
if (scoped.key == streams.key) { if (scoped.key == streams.key) {
Seq(scoped.scope / streams := { Seq(scoped.scope / streams := Def.uncached {
(streamsManager.map { mgr => (streamsManager.map { mgr =>
val stream = mgr(scoped) val stream = mgr(scoped)
stream.open() stream.open()

View File

@ -180,8 +180,12 @@ object Keys {
// Output paths // Output paths
@cacheLevel(include = Array.empty) @cacheLevel(include = Array.empty)
val classDirectory = settingKey[File]("Directory for compiled classes and copied resources.").withRank(AMinusSetting) val classDirectory = settingKey[File]("Directory for compiled classes and copied resources.").withRank(AMinusSetting)
@cacheLevel(include = Array.empty)
val earlyOutput = settingKey[VirtualFile]("JAR file for pickles used for build pipelining") val earlyOutput = settingKey[VirtualFile]("JAR file for pickles used for build pipelining")
val backendOutput = settingKey[VirtualFile]("Output directory of the compiler backend") val backendOutput = settingKey[VirtualFile]("Output directory of the compiler backend")
@cacheLevel(include = Array.empty)
val cleanFiles = taskKey[Seq[File]]("The files to recursively delete during a clean.").withRank(BSetting) val cleanFiles = taskKey[Seq[File]]("The files to recursively delete during a clean.").withRank(BSetting)
val cleanKeepFiles = settingKey[Seq[File]]("Files or directories to keep during a clean. Must be direct children of target.").withRank(CSetting) val cleanKeepFiles = settingKey[Seq[File]]("Files or directories to keep during a clean. Must be direct children of target.").withRank(CSetting)
val cleanKeepGlobs = settingKey[Seq[Glob]]("Globs to keep during a clean. Must be direct children of target.").withRank(CSetting) val cleanKeepGlobs = settingKey[Seq[Glob]]("Globs to keep during a clean. Must be direct children of target.").withRank(CSetting)
@ -209,6 +213,7 @@ object Keys {
val compileInputs = taskKey[Inputs]("Collects all inputs needed for compilation.").withRank(DTask) val compileInputs = taskKey[Inputs]("Collects all inputs needed for compilation.").withRank(DTask)
val compileInputs2 = taskKey[CompileInputs2]("") val compileInputs2 = taskKey[CompileInputs2]("")
val scalaHome = settingKey[Option[File]]("If Some, defines the local Scala installation to use for compilation, running, and testing.").withRank(ASetting) val scalaHome = settingKey[Option[File]]("If Some, defines the local Scala installation to use for compilation, running, and testing.").withRank(ASetting)
@cacheLevel(include = Array.empty)
val scalaInstance = taskKey[ScalaInstance]("Defines the Scala instance to use for compilation, running, and testing.").withRank(DTask) val scalaInstance = taskKey[ScalaInstance]("Defines the Scala instance to use for compilation, running, and testing.").withRank(DTask)
val scalaOrganization = settingKey[String]("Organization/group ID of the Scala used in the project. Default value is 'org.scala-lang'. This is an advanced setting used for clones of the Scala Language. It should be disregarded in standard use cases.").withRank(CSetting) val scalaOrganization = settingKey[String]("Organization/group ID of the Scala used in the project. Default value is 'org.scala-lang'. This is an advanced setting used for clones of the Scala Language. It should be disregarded in standard use cases.").withRank(CSetting)
val scalaVersion = settingKey[String]("The version of Scala used for building.").withRank(APlusSetting) val scalaVersion = settingKey[String]("The version of Scala used for building.").withRank(APlusSetting)
@ -301,7 +306,11 @@ object Keys {
val artifact = settingKey[Artifact]("Describes an artifact.").withRank(BMinusSetting) val artifact = settingKey[Artifact]("Describes an artifact.").withRank(BMinusSetting)
val artifactClassifier = settingKey[Option[String]]("Sets the classifier used by the default artifact definition.").withRank(BSetting) val artifactClassifier = settingKey[Option[String]]("Sets the classifier used by the default artifact definition.").withRank(BSetting)
val artifactName = settingKey[(ScalaVersion, ModuleID, Artifact) => String]("Function that produces the artifact name from its definition.").withRank(CSetting) val artifactName = settingKey[(ScalaVersion, ModuleID, Artifact) => String]("Function that produces the artifact name from its definition.").withRank(CSetting)
@cacheLevel(include = Array.empty)
val mappings = taskKey[Seq[(HashedVirtualFileRef, String)]]("Defines the mappings from a file to a path, used by packaging, for example.").withRank(BTask) val mappings = taskKey[Seq[(HashedVirtualFileRef, String)]]("Defines the mappings from a file to a path, used by packaging, for example.").withRank(BTask)
@cacheLevel(include = Array.empty)
val fileMappings = taskKey[Seq[(File, File)]]("Defines the mappings from a file to a file, used for copying files, for example.").withRank(BMinusTask) val fileMappings = taskKey[Seq[(File, File)]]("Defines the mappings from a file to a file, used for copying files, for example.").withRank(BMinusTask)
// Run Keys // Run Keys
@ -356,6 +365,8 @@ object Keys {
val testOptions = taskKey[Seq[TestOption]]("Options for running tests.").withRank(BPlusTask) val testOptions = taskKey[Seq[TestOption]]("Options for running tests.").withRank(BPlusTask)
private[sbt] val testOptionDigests = taskKey[Seq[Digest]]("Digest for testOptions").withRank(DTask) private[sbt] val testOptionDigests = taskKey[Seq[Digest]]("Digest for testOptions").withRank(DTask)
val testFrameworks = settingKey[Seq[TestFramework]]("Registered, although not necessarily present, test frameworks.").withRank(CTask) val testFrameworks = settingKey[Seq[TestFramework]]("Registered, although not necessarily present, test frameworks.").withRank(CTask)
@cacheLevel(include = Array.empty)
val testListeners = taskKey[Seq[TestReportListener]]("Defines test listeners.").withRank(DTask) val testListeners = taskKey[Seq[TestReportListener]]("Defines test listeners.").withRank(DTask)
val testForkedParallel = settingKey[Boolean]("Whether forked tests should be executed in parallel").withRank(CTask) val testForkedParallel = settingKey[Boolean]("Whether forked tests should be executed in parallel").withRank(CTask)
val testExecution = taskKey[Tests.Execution]("Settings controlling test execution").withRank(DTask) val testExecution = taskKey[Tests.Execution]("Settings controlling test execution").withRank(DTask)
@ -486,6 +497,8 @@ object Keys {
val csrExtraProjects = taskKey[Seq[lmcoursier.definitions.Project]]("").withRank(CTask) val csrExtraProjects = taskKey[Seq[lmcoursier.definitions.Project]]("").withRank(CTask)
val csrFallbackDependencies = taskKey[Seq[FallbackDependency]]("") val csrFallbackDependencies = taskKey[Seq[FallbackDependency]]("")
val csrLogger = taskKey[Option[CacheLogger]]("") val csrLogger = taskKey[Option[CacheLogger]]("")
@cacheLevel(include = Array.empty)
val csrExtraCredentials = taskKey[Seq[lmcoursier.credentials.Credentials]]("") val csrExtraCredentials = taskKey[Seq[lmcoursier.credentials.Credentials]]("")
val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("") val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("")
val csrReconciliations = settingKey[Seq[(ModuleMatchers, Reconciliation)]]("Strategy to reconcile version conflicts.") val csrReconciliations = settingKey[Seq[(ModuleMatchers, Reconciliation)]]("Strategy to reconcile version conflicts.")
@ -535,7 +548,10 @@ object Keys {
val packagedArtifacts = taskKey[Map[Artifact, HashedVirtualFileRef]]("Packages all artifacts for publishing and maps the Artifact definition to the generated file.").withRank(CTask) val packagedArtifacts = taskKey[Map[Artifact, HashedVirtualFileRef]]("Packages all artifacts for publishing and maps the Artifact definition to the generated file.").withRank(CTask)
val publishMavenStyle = settingKey[Boolean]("Configures whether to generate and publish a pom (true) or Ivy file (false).").withRank(BSetting) val publishMavenStyle = settingKey[Boolean]("Configures whether to generate and publish a pom (true) or Ivy file (false).").withRank(BSetting)
val sbtPluginPublishLegacyMavenStyle = settingKey[Boolean]("Configuration for generating the legacy pom of sbt plugins, to publish to Maven").withRank(CSetting) val sbtPluginPublishLegacyMavenStyle = settingKey[Boolean]("Configuration for generating the legacy pom of sbt plugins, to publish to Maven").withRank(CSetting)
@cacheLevel(include = Array.empty)
val credentials = taskKey[Seq[Credentials]]("The credentials to use for updating and publishing.").withRank(BMinusTask) val credentials = taskKey[Seq[Credentials]]("The credentials to use for updating and publishing.").withRank(BMinusTask)
@cacheLevel(include = Array.empty)
val allCredentials = taskKey[Seq[Credentials]]("Aggregated credentials across current and root subprojects. Do not rewire this task.").withRank(DTask) val allCredentials = taskKey[Seq[Credentials]]("Aggregated credentials across current and root subprojects. Do not rewire this task.").withRank(DTask)
val makePom = taskKey[HashedVirtualFileRef]("Generates a pom for publishing when publishing Maven-style.").withRank(BPlusTask) val makePom = taskKey[HashedVirtualFileRef]("Generates a pom for publishing when publishing Maven-style.").withRank(BPlusTask)
@ -564,9 +580,15 @@ object Keys {
val appResolvers = settingKey[Option[Seq[Resolver]]]("The resolvers configured for this application by the sbt launcher.").withRank(BMinusSetting) val appResolvers = settingKey[Option[Seq[Resolver]]]("The resolvers configured for this application by the sbt launcher.").withRank(BMinusSetting)
val externalResolvers = taskKey[Seq[Resolver]]("The external resolvers for automatically managed dependencies.").withRank(BMinusSetting) val externalResolvers = taskKey[Seq[Resolver]]("The external resolvers for automatically managed dependencies.").withRank(BMinusSetting)
val resolvers = settingKey[Seq[Resolver]]("The user-defined additional resolvers for automatically managed dependencies.").withRank(BMinusTask) val resolvers = settingKey[Seq[Resolver]]("The user-defined additional resolvers for automatically managed dependencies.").withRank(BMinusTask)
@cacheLevel(include = Array.empty)
val projectResolver = taskKey[Resolver]("Resolver that handles inter-project dependencies.").withRank(DTask) val projectResolver = taskKey[Resolver]("Resolver that handles inter-project dependencies.").withRank(DTask)
val fullResolvers = taskKey[Seq[Resolver]]("Combines the project resolver, default resolvers, and user-defined resolvers.").withRank(CTask) val fullResolvers = taskKey[Seq[Resolver]]("Combines the project resolver, default resolvers, and user-defined resolvers.").withRank(CTask)
@cacheLevel(include = Array.empty)
val otherResolvers = taskKey[Seq[Resolver]]("Resolvers not included in the main resolver chain, such as those in module configurations.").withRank(CSetting) val otherResolvers = taskKey[Seq[Resolver]]("Resolvers not included in the main resolver chain, such as those in module configurations.").withRank(CSetting)
@cacheLevel(include = Array.empty)
val scalaCompilerBridgeResolvers = taskKey[Seq[Resolver]]("Resolvers used to resolve compiler bridges.").withRank(CSetting) val scalaCompilerBridgeResolvers = taskKey[Seq[Resolver]]("Resolvers used to resolve compiler bridges.").withRank(CSetting)
val includePluginResolvers = settingKey[Boolean]("Include the resolvers from the metabuild.").withRank(CSetting) val includePluginResolvers = settingKey[Boolean]("Include the resolvers from the metabuild.").withRank(CSetting)
val moduleConfigurations = settingKey[Seq[ModuleConfiguration]]("Defines module configurations, which override resolvers on a per-module basis.").withRank(BMinusSetting) val moduleConfigurations = settingKey[Seq[ModuleConfiguration]]("Defines module configurations, which override resolvers on a per-module basis.").withRank(BMinusSetting)
@ -585,6 +607,8 @@ object Keys {
val scalaModuleInfo = settingKey[Option[ScalaModuleInfo]]("Configures how Scala dependencies are checked, filtered, and injected.").withRank(CSetting) val scalaModuleInfo = settingKey[Option[ScalaModuleInfo]]("Configures how Scala dependencies are checked, filtered, and injected.").withRank(CSetting)
val ivyValidate = settingKey[Boolean]("Enables/disables Ivy validation of module metadata.").withRank(BSetting) val ivyValidate = settingKey[Boolean]("Enables/disables Ivy validation of module metadata.").withRank(BSetting)
val ivyLoggingLevel = settingKey[UpdateLogging]("The logging level for updating.").withRank(BSetting) val ivyLoggingLevel = settingKey[UpdateLogging]("The logging level for updating.").withRank(BSetting)
@cacheLevel(include = Array.empty)
val publishTo = taskKey[Option[Resolver]]("The resolver to publish to.").withRank(ASetting) val publishTo = taskKey[Option[Resolver]]("The resolver to publish to.").withRank(ASetting)
val artifacts = settingKey[Seq[Artifact]]("The artifact definitions for the current module. Must be consistent with " + packagedArtifacts.key.label + ".").withRank(BSetting) val artifacts = settingKey[Seq[Artifact]]("The artifact definitions for the current module. Must be consistent with " + packagedArtifacts.key.label + ".").withRank(BSetting)
val projectDescriptors = taskKey[Map[ModuleRevisionId, ModuleDescriptor]]("Project dependency map for the inter-project resolver.").withRank(DTask) val projectDescriptors = taskKey[Map[ModuleRevisionId, ModuleDescriptor]]("Project dependency map for the inter-project resolver.").withRank(DTask)
@ -641,6 +665,8 @@ object Keys {
val streams = taskKey[TaskStreams]("Provides streams for logging and persisting data.").withRank(DTask) val streams = taskKey[TaskStreams]("Provides streams for logging and persisting data.").withRank(DTask)
val taskDefinitionKey = Def.taskDefinitionKey val taskDefinitionKey = Def.taskDefinitionKey
val (executionRoots, dummyRoots) = Def.dummy[Seq[ScopedKey[?]]]("executionRoots", "The list of root tasks for this task execution. Roots are the top-level tasks that were directly requested to be run.") val (executionRoots, dummyRoots) = Def.dummy[Seq[ScopedKey[?]]]("executionRoots", "The list of root tasks for this task execution. Roots are the top-level tasks that were directly requested to be run.")
@cacheLevel(include = Array.empty)
val state = Def.stateKey val state = Def.stateKey
val streamsManager = Def.streamsManagerKey val streamsManager = Def.streamsManagerKey
// wrapper to work around SI-2915 // wrapper to work around SI-2915

View File

@ -90,7 +90,7 @@ object DefaultOptions {
def credentials(state: State): Credentials = def credentials(state: State): Credentials =
Credentials(getGlobalSettingsDirectory(state, getGlobalBase(state)) / ".credentials") Credentials(getGlobalSettingsDirectory(state, getGlobalBase(state)) / ".credentials")
def addCredentials: Setting[?] = Keys.credentials += { credentials(Keys.state.value) } def addCredentials: Setting[?] = Keys.credentials += credentials(Keys.state.value)
def shellPrompt(version: String): State => String = def shellPrompt(version: String): State => String =
s => s"${s.configuration.provider.id.name}:${Project.extract(s).currentProject.id}:${version}> " s => s"${s.configuration.provider.id.name}:${Project.extract(s).currentProject.id}:${version}> "

View File

@ -37,6 +37,7 @@ import sbt.nio.Keys.{ inputFileStamps, outputFileStamps }
import sbt.std.TaskExtra.* import sbt.std.TaskExtra.*
import sbt.util.InterfaceUtil.toOption import sbt.util.InterfaceUtil.toOption
import sbt.util.{ DiskActionCacheStore, Logger } import sbt.util.{ DiskActionCacheStore, Logger }
import sbt.util.CacheImplicits.given
import sjsonnew.JsonFormat import sjsonnew.JsonFormat
import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFileRef } import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFileRef }
import xsbti.compile.CompileAnalysis import xsbti.compile.CompileAnalysis
@ -74,7 +75,7 @@ object RemoteCache {
lazy val globalSettings: Seq[Def.Setting[?]] = Seq( lazy val globalSettings: Seq[Def.Setting[?]] = Seq(
remoteCacheId := "", remoteCacheId := "",
remoteCacheIdCandidates := Nil, remoteCacheIdCandidates :== Nil,
pushRemoteCacheTo :== None, pushRemoteCacheTo :== None,
localCacheDirectory :== defaultCacheLocation, localCacheDirectory :== defaultCacheLocation,
pushRemoteCache / ivyPaths := { pushRemoteCache / ivyPaths := {
@ -139,14 +140,14 @@ object RemoteCache {
} }
}) })
.value, .value,
pushRemoteCacheConfiguration / remoteCacheArtifacts := { pushRemoteCacheConfiguration / remoteCacheArtifacts := Def.uncached {
enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value enabledOnly(remoteCacheArtifact.toSettingKey, defaultArtifactTasks).apply(_.join).value
}, },
pushRemoteCacheConfiguration / publishMavenStyle := true, pushRemoteCacheConfiguration / publishMavenStyle := true,
Compile / packageCache / pushRemoteCacheArtifact := true, Compile / packageCache / pushRemoteCacheArtifact := true,
Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier), Compile / packageCache / artifact := Artifact(moduleName.value, cachedCompileClassifier),
remoteCachePom / pushRemoteCacheArtifact := true, remoteCachePom / pushRemoteCacheArtifact := true,
remoteCachePom := { remoteCachePom := Def.uncached {
val s = streams.value val s = streams.value
val converter = fileConverter.value val converter = fileConverter.value
val config = (remoteCachePom / makePomConfiguration).value val config = (remoteCachePom / makePomConfiguration).value
@ -163,14 +164,14 @@ object RemoteCache {
val out = converter.toPath((remoteCachePom / artifactPath).value) val out = converter.toPath((remoteCachePom / artifactPath).value)
config.withFile(out.toFile()) config.withFile(out.toFile())
}, },
remoteCachePom / remoteCacheArtifact := { remoteCachePom / remoteCacheArtifact := Def.uncached {
PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom) PomRemoteCacheArtifact((makePom / artifact).value, remoteCachePom)
}, },
remoteCacheResolvers := pushRemoteCacheTo.value.toVector, remoteCacheResolvers := pushRemoteCacheTo.value.toVector,
) ++ inTask(pushRemoteCache)( ) ++ inTask(pushRemoteCache)(
Seq( Seq(
ivyPaths := (Scope.Global / pushRemoteCache / ivyPaths).value, ivyPaths := (Scope.Global / pushRemoteCache / ivyPaths).value,
ivyConfiguration := { ivyConfiguration := Def.uncached {
val config0 = Classpaths.mkIvyConfiguration.value val config0 = Classpaths.mkIvyConfiguration.value
config0 config0
.withResolvers(remoteCacheResolvers.value.toVector) .withResolvers(remoteCacheResolvers.value.toVector)
@ -179,7 +180,7 @@ object RemoteCache {
.withPaths(ivyPaths.value) .withPaths(ivyPaths.value)
.withUpdateOptions(UpdateOptions().withGigahorse(true)) .withUpdateOptions(UpdateOptions().withGigahorse(true))
}, },
ivySbt := { ivySbt := Def.uncached {
Credentials.register(credentials.value, streams.value.log) Credentials.register(credentials.value, streams.value.log)
val config0 = ivyConfiguration.value val config0 = ivyConfiguration.value
new IvySbt(config0) new IvySbt(config0)
@ -187,8 +188,8 @@ object RemoteCache {
) )
) ++ inTask(pullRemoteCache)( ) ++ inTask(pullRemoteCache)(
Seq( Seq(
dependencyResolution := Defaults.dependencyResolutionTask.value, dependencyResolution := Def.uncached(Defaults.dependencyResolutionTask.value),
csrConfiguration := { csrConfiguration := Def.uncached {
val rs = pushRemoteCacheTo.value.toVector ++ remoteCacheResolvers.value.toVector val rs = pushRemoteCacheTo.value.toVector ++ remoteCacheResolvers.value.toVector
LMCoursier.scalaCompilerBridgeConfigurationTask.value LMCoursier.scalaCompilerBridgeConfigurationTask.value
.withResolvers(rs) .withResolvers(rs)
@ -207,7 +208,7 @@ object RemoteCache {
): Seq[Def.Setting[?]] = ): Seq[Def.Setting[?]] =
inTask(packageCache)( inTask(packageCache)(
Seq( Seq(
(Defaults.TaskZero / packageCache) := { (Defaults.TaskZero / packageCache) := Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val original = (Defaults.TaskZero / packageBin).value val original = (Defaults.TaskZero / packageBin).value
val originalFile = converter.toPath(original) val originalFile = converter.toPath(original)
@ -233,13 +234,13 @@ object RemoteCache {
converter.toVirtualFile(artpFile) converter.toVirtualFile(artpFile)
}, },
pushRemoteCacheArtifact := true, pushRemoteCacheArtifact := true,
remoteCacheArtifact := cacheArtifactTask.value, remoteCacheArtifact := Def.uncached(cacheArtifactTask.value),
packagedArtifact := (artifact.value -> packageCache.value), packagedArtifact := Def.uncached(artifact.value -> packageCache.value),
artifactPath := Defaults.artifactPathSetting(artifact).value artifactPath := Defaults.artifactPathSetting(artifact).value
) )
) ++ inTask(pushRemoteCache)( ) ++ inTask(pushRemoteCache)(
Seq( Seq(
moduleSettings := { moduleSettings := Def.uncached {
val smi = scalaModuleInfo.value val smi = scalaModuleInfo.value
ModuleDescriptorConfiguration(remoteCacheProjectId.value, projectInfo.value) ModuleDescriptorConfiguration(remoteCacheProjectId.value, projectInfo.value)
.withScalaModuleInfo(smi) .withScalaModuleInfo(smi)
@ -257,7 +258,7 @@ object RemoteCache {
) )
) ++ Seq( ) ++ Seq(
remoteCacheIdCandidates := List(remoteCacheId.value), remoteCacheIdCandidates := List(remoteCacheId.value),
remoteCacheProjectId := { remoteCacheProjectId := Def.uncached {
val o = organization.value val o = organization.value
val m = moduleName.value val m = moduleName.value
val id = remoteCacheId.value val id = remoteCacheId.value
@ -265,7 +266,7 @@ object RemoteCache {
val v = toVersion(id) val v = toVersion(id)
ModuleID(o, m, v).cross(c) ModuleID(o, m, v).cross(c)
}, },
remoteCacheId := { remoteCacheId := Def.uncached {
val inputs = (unmanagedSources / inputFileStamps).value val inputs = (unmanagedSources / inputFileStamps).value
val cp = (externalDependencyClasspath / outputFileStamps).?.value.getOrElse(Nil) val cp = (externalDependencyClasspath / outputFileStamps).?.value.getOrElse(Nil)
val extraInc = (extraIncOptions.value) flatMap { (k, v) => val extraInc = (extraIncOptions.value) flatMap { (k, v) =>
@ -273,7 +274,7 @@ object RemoteCache {
} }
combineHash(extractHash(inputs) ++ extractHash(cp) ++ extraInc) combineHash(extractHash(inputs) ++ extractHash(cp) ++ extraInc)
}, },
pushRemoteCacheConfiguration := { pushRemoteCacheConfiguration := Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val artifacts = val artifacts =
(pushRemoteCacheConfiguration / packagedArtifacts).value.toVector.map { (a, vf) => (pushRemoteCacheConfiguration / packagedArtifacts).value.toVector.map { (a, vf) =>
@ -291,7 +292,7 @@ object RemoteCache {
isSnapshot.value isSnapshot.value
) )
}, },
pushRemoteCacheConfiguration / packagedArtifacts := pushRemoteCacheConfiguration / packagedArtifacts := Def.uncached(
(Def (Def
.task { (pushRemoteCacheConfiguration / remoteCacheArtifacts).value }) .task { (pushRemoteCacheConfiguration / remoteCacheArtifacts).value })
.flatMapTask { case artifacts => .flatMapTask { case artifacts =>
@ -300,11 +301,12 @@ object RemoteCache {
.join .join
.apply(_.join.map(_.toMap)) .apply(_.join.map(_.toMap))
} }
.value, .value
pushRemoteCacheConfiguration / remoteCacheArtifacts := { ),
pushRemoteCacheConfiguration / remoteCacheArtifacts := Def.uncached {
List((packageCache / remoteCacheArtifact).value) List((packageCache / remoteCacheArtifact).value)
}, },
pullRemoteCache := { pullRemoteCache := Def.uncached {
import scala.jdk.CollectionConverters.* import scala.jdk.CollectionConverters.*
val log = streams.value.log val log = streams.value.log
val r = remoteCacheResolvers.value.head val r = remoteCacheResolvers.value.head

View File

@ -62,16 +62,18 @@ object ScriptedPlugin extends AutoPlugin {
override lazy val projectSettings: Seq[Setting[?]] = Seq( override lazy val projectSettings: Seq[Setting[?]] = Seq(
ivyConfigurations ++= Seq(ScriptedConf, ScriptedLaunchConf), ivyConfigurations ++= Seq(ScriptedConf, ScriptedLaunchConf),
scriptedSbt := (pluginCrossBuild / sbtVersion).value, scriptedSbt := (pluginCrossBuild / sbtVersion).value,
sbtLauncher := getJars(ScriptedLaunchConf) sbtLauncher := Def.uncached(
.map(_.get().head) getJars(ScriptedLaunchConf)
.value, .map(_.get().head)
.value
),
sbtTestDirectory := sourceDirectory.value / "sbt-test", sbtTestDirectory := sourceDirectory.value / "sbt-test",
libraryDependencies ++= Seq( libraryDependencies ++= Seq(
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % ScriptedConf, "org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % ScriptedConf,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % ScriptedLaunchConf "org.scala-sbt" % "sbt-launch" % scriptedSbt.value % ScriptedLaunchConf
), ),
scriptedClasspath := getJars(ScriptedConf).value, scriptedClasspath := Def.uncached(getJars(ScriptedConf).value),
scriptedTests := scriptedTestsTask.value, scriptedTests := Def.uncached(scriptedTestsTask.value),
scriptedParallelInstances := 1, scriptedParallelInstances := 1,
scriptedBatchExecution := { scriptedBatchExecution := {
val binVersion = CrossVersionUtil.binarySbtVersion(scriptedSbt.value) val binVersion = CrossVersionUtil.binarySbtVersion(scriptedSbt.value)
@ -82,8 +84,8 @@ object ScriptedPlugin extends AutoPlugin {
case _ => false case _ => false
} }
}, },
scriptedRun := scriptedRunTask.value, scriptedRun := Def.uncached(scriptedRunTask.value),
scriptedDependencies := { scriptedDependencies := Def.uncached {
def use[A](@deprecated("unused", "") x: A*): Unit = () // avoid unused warnings def use[A](@deprecated("unused", "") x: A*): Unit = () // avoid unused warnings
val analysis = (Test / Keys.compile).value val analysis = (Test / Keys.compile).value
val pub = publishLocal.all(ScopeFilter(projects = inDependencies(ThisProject))).value val pub = publishLocal.all(ScopeFilter(projects = inDependencies(ThisProject))).value

View File

@ -257,7 +257,9 @@ object LMCoursier {
} }
def publicationsSetting(packageConfigs: Seq[(Configuration, CConfiguration)]): Def.Setting[?] = { def publicationsSetting(packageConfigs: Seq[(Configuration, CConfiguration)]): Def.Setting[?] = {
csrPublications := CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs*).value csrPublications := Def.uncached(
CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs*).value
)
} }
// This emulates Ivy's credential registration which basically keeps mutating global registry // This emulates Ivy's credential registration which basically keeps mutating global registry

View File

@ -16,6 +16,7 @@ import Def.Setting
import sbt.io.Hash import sbt.io.Hash
import sbt.internal.util.{ Attributed, StringAttributeMap } import sbt.internal.util.{ Attributed, StringAttributeMap }
import sbt.internal.inc.{ FileAnalysisStore, ReflectUtilities } import sbt.internal.inc.{ FileAnalysisStore, ReflectUtilities }
import sbt.util.CacheImplicits.given
import xsbti.{ FileConverter, VirtualFileRef } import xsbti.{ FileConverter, VirtualFileRef }
import xsbti.compile.CompileAnalysis import xsbti.compile.CompileAnalysis

View File

@ -97,6 +97,8 @@ object BuildUtil {
:: "import _root_.sbt.BareBuildSyntax.*" :: "import _root_.sbt.BareBuildSyntax.*"
:: "import _root_.sbt.Keys.*" :: "import _root_.sbt.Keys.*"
:: "import _root_.sbt.nio.Keys.*" :: "import _root_.sbt.nio.Keys.*"
:: "import _root_.sbt.util.CacheImplicits.given"
:: "import _root_.sbt.librarymanagement.LibraryManagementCodec.given"
:: Nil) :: Nil)
def getImports(unit: BuildUnit): Seq[String] = def getImports(unit: BuildUnit): Seq[String] =

View File

@ -22,6 +22,7 @@ import Keys.*
import Configurations.{ Compile, Runtime } import Configurations.{ Compile, Runtime }
import sbt.ProjectExtra.{ extract, runUnloadHooks, setProject } import sbt.ProjectExtra.{ extract, runUnloadHooks, setProject }
import sbt.SlashSyntax0.* import sbt.SlashSyntax0.*
import sbt.librarymanagement.LibraryManagementCodec.given
import java.io.File import java.io.File
import org.apache.ivy.core.module.{ descriptor, id } import org.apache.ivy.core.module.{ descriptor, id }
import descriptor.ModuleDescriptor, id.ModuleRevisionId import descriptor.ModuleDescriptor, id.ModuleRevisionId

View File

@ -52,7 +52,7 @@ object IvyConsole {
val depSettings: Seq[Setting[?]] = Seq( val depSettings: Seq[Setting[?]] = Seq(
libraryDependencies ++= managed.reverse, libraryDependencies ++= managed.reverse,
resolvers ++= repos.reverse.toVector, resolvers ++= repos.reverse.toVector,
Compile / unmanagedJars ++= { Compile / unmanagedJars ++= Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val u = unmanaged.reverse.map(_.toPath).map(converter.toVirtualFile) val u = unmanaged.reverse.map(_.toPath).map(converter.toVirtualFile)
u: Seq[HashedVirtualFileRef] u: Seq[HashedVirtualFileRef]

View File

@ -1331,7 +1331,7 @@ private[sbt] object Load {
Seq( Seq(
sbtPlugin :== true, sbtPlugin :== true,
isMetaBuild :== true, isMetaBuild :== true,
pluginData := { pluginData := Def.uncached {
val prod = (Configurations.Runtime / exportedProducts).value val prod = (Configurations.Runtime / exportedProducts).value
val cp = (Configurations.Runtime / fullClasspath).value val cp = (Configurations.Runtime / fullClasspath).value
val opts = (Configurations.Compile / scalacOptions).value val opts = (Configurations.Compile / scalacOptions).value
@ -1357,7 +1357,7 @@ private[sbt] object Load {
converter, converter,
) )
}, },
scalacOptions += "-Wconf:cat=unused-nowarn:s", scalacOptions += Def.uncached("-Wconf:cat=unused-nowarn:s"),
onLoadMessage := ("loading project definition from " + baseDirectory.value) onLoadMessage := ("loading project definition from " + baseDirectory.value)
) )
) )

View File

@ -54,8 +54,9 @@ object Script {
val embeddedSettings = blocks(script).flatMap { block => val embeddedSettings = blocks(script).flatMap { block =>
evaluate(eval(), vf, block.lines, currentUnit.imports, block.offset + 1)(currentLoader) evaluate(eval(), vf, block.lines, currentUnit.imports, block.offset + 1)(currentLoader)
} }
val scriptAsSource = (Compile / sources) := script :: Nil val scriptAsSource = (Compile / sources) := Def.uncached(script :: Nil)
val asScript = scalacOptions ++= Seq("-Xscript", script.getName.stripSuffix(".scala")) val asScript =
scalacOptions ++= Def.uncached(Seq("-Xscript", script.getName.stripSuffix(".scala")))
val scriptSettings = Seq( val scriptSettings = Seq(
asScript, asScript,
scriptAsSource, scriptAsSource,

View File

@ -193,7 +193,7 @@ object IvyXml {
task: TaskKey[T], task: TaskKey[T],
shadedConfigOpt: Option[Configuration] shadedConfigOpt: Option[Configuration]
): Setting[Task[T]] = ): Setting[Task[T]] =
task := task.dependsOnTask { task := Def.uncached(task.dependsOnTask {
Def.task { Def.task {
val currentProject = { val currentProject = {
val proj = csrProject.value val proj = csrProject.value
@ -207,7 +207,7 @@ object IvyXml {
sbt.Keys.streams.value.log sbt.Keys.streams.value.log
) )
} }
}.value }.value)
private lazy val needsIvyXmlLocal = Seq(publishLocalConfiguration) ++ getPubConf( private lazy val needsIvyXmlLocal = Seq(publishLocalConfiguration) ++ getPubConf(
"makeIvyXmlLocalConfiguration" "makeIvyXmlLocalConfiguration"

View File

@ -336,7 +336,7 @@ object BuildServerProtocol {
bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value, bspInternalDependencyConfigurations := internalDependencyConfigurationsSetting.value,
bspScalaTestClassesItem := scalaTestClassesTask.value, bspScalaTestClassesItem := scalaTestClassesTask.value,
bspScalaMainClassesItem := scalaMainClassesTask.value, bspScalaMainClassesItem := scalaMainClassesTask.value,
Keys.compile / bspReporter := { Keys.compile / bspReporter := Def.uncached {
val targetId = bspTargetIdentifier.value val targetId = bspTargetIdentifier.value
val bspCompileStateInstance = bspCompileState.value val bspCompileStateInstance = bspCompileState.value
val converter = fileConverter.value val converter = fileConverter.value

View File

@ -20,6 +20,7 @@ import sbt.internal.util.AttributeKey
import sbt.internal.util.complete.Parser import sbt.internal.util.complete.Parser
import sbt.nio.file.{ FileAttributes, FileTreeView, Glob, PathFilter } import sbt.nio.file.{ FileAttributes, FileTreeView, Glob, PathFilter }
import sbt.* import sbt.*
import sbt.util.cacheLevel
import scala.concurrent.duration.FiniteDuration import scala.concurrent.duration.FiniteDuration
@ -39,6 +40,8 @@ object Keys {
settingKey[PathFilter]("A filter to apply to the input sources of a task.") settingKey[PathFilter]("A filter to apply to the input sources of a task.")
val fileInputExcludeFilter = val fileInputExcludeFilter =
settingKey[PathFilter]("An exclusion filter to apply to the input sources of a task.") settingKey[PathFilter]("An exclusion filter to apply to the input sources of a task.")
@cacheLevel(include = Array.empty)
val inputFileStamper = settingKey[FileStamper]( val inputFileStamper = settingKey[FileStamper](
"Toggles the file stamping implementation used to determine whether or not a file has been modified." "Toggles the file stamping implementation used to determine whether or not a file has been modified."
) )
@ -169,9 +172,13 @@ object Keys {
private[sbt] val allInputPathsAndAttributes = private[sbt] val allInputPathsAndAttributes =
taskKey[Seq[(Path, FileAttributes)]]("Get all of the file inputs for a task") taskKey[Seq[(Path, FileAttributes)]]("Get all of the file inputs for a task")
.withRank(Invisible) .withRank(Invisible)
@cacheLevel(include = Array.empty)
private[sbt] val unmanagedFileStampCache = taskKey[FileStamp.Cache]( private[sbt] val unmanagedFileStampCache = taskKey[FileStamp.Cache](
"Map of managed file stamps that may be cleared between task evaluation runs." "Map of managed file stamps that may be cleared between task evaluation runs."
).withRank(Invisible) ).withRank(Invisible)
@cacheLevel(include = Array.empty)
private[sbt] val managedFileStampCache = taskKey[FileStamp.Cache]( private[sbt] val managedFileStampCache = taskKey[FileStamp.Cache](
"Map of managed file stamps that may be cleared between task evaluation runs." "Map of managed file stamps that may be cleared between task evaluation runs."
).withRank(Invisible) ).withRank(Invisible)

View File

@ -127,7 +127,7 @@ private[sbt] object Settings {
scopedKey.scope.task.toOption.toSeq.map { key => scopedKey.scope.task.toOption.toSeq.map { key =>
val updatedKey = Def.ScopedKey(scopedKey.scope.copy(task = Zero), key) val updatedKey = Def.ScopedKey(scopedKey.scope.copy(task = Zero), key)
scopedKey.scope / transitiveDynamicInputs := scopedKey.scope / transitiveDynamicInputs :=
WatchTransitiveDependencies.task(updatedKey).value Def.uncached(WatchTransitiveDependencies.task(updatedKey).value)
} }
case dynamicDependency.key => (scopedKey.scope / dynamicDependency := { () }) :: Nil case dynamicDependency.key => (scopedKey.scope / dynamicDependency := { () }) :: Nil
case transitiveClasspathDependency.key => case transitiveClasspathDependency.key =>
@ -158,7 +158,7 @@ private[sbt] object Settings {
private[sbt] def inputPathSettings(setting: Def.Setting[?]): Seq[Def.Setting[?]] = { private[sbt] def inputPathSettings(setting: Def.Setting[?]): Seq[Def.Setting[?]] = {
val scopedKey = setting.key val scopedKey = setting.key
val scope = scopedKey.scope val scope = scopedKey.scope
(scope / Keys.allInputPathsAndAttributes := { (scope / Keys.allInputPathsAndAttributes := Def.uncached {
val view = (scope / fileTreeView).value val view = (scope / fileTreeView).value
val inputs = (scope / fileInputs).value val inputs = (scope / fileInputs).value
val stamper = (scope / inputFileStamper).value val stamper = (scope / inputFileStamper).value
@ -186,7 +186,7 @@ private[sbt] object Settings {
* @return a task definition that retrieves all of the input paths scoped to the input key. * @return a task definition that retrieves all of the input paths scoped to the input key.
*/ */
private def allFilesImpl(scope: Scope): Def.Setting[?] = { private def allFilesImpl(scope: Scope): Def.Setting[?] = {
addTaskDefinition(scope / Keys.allInputFiles := { addTaskDefinition(scope / Keys.allInputFiles := Def.uncached {
val filter = val filter =
(scope / fileInputIncludeFilter).value && !(scope / fileInputExcludeFilter).value (scope / fileInputIncludeFilter).value && !(scope / fileInputExcludeFilter).value
(scope / Keys.allInputPathsAndAttributes).value.collect { (scope / Keys.allInputPathsAndAttributes).value.collect {
@ -218,7 +218,7 @@ private[sbt] object Settings {
changeKey: TaskKey[Seq[(Path, FileStamp)] => FileChanges], changeKey: TaskKey[Seq[(Path, FileStamp)] => FileChanges],
stampKey: TaskKey[Seq[(Path, FileStamp)]] stampKey: TaskKey[Seq[(Path, FileStamp)]]
): Def.Setting[?] = ): Def.Setting[?] =
addTaskDefinition(scope / changeKey := { addTaskDefinition(scope / changeKey := Def.uncached {
val current = (scope / stampKey).value val current = (scope / stampKey).value
changedFiles(_, current) changedFiles(_, current)
}) })
@ -262,7 +262,7 @@ private[sbt] object Settings {
* @return a task specific clean implementation * @return a task specific clean implementation
*/ */
private[sbt] def cleanImpl(scope: Scope): Def.Setting[?] = addTaskDefinition { private[sbt] def cleanImpl(scope: Scope): Def.Setting[?] = addTaskDefinition {
scope / sbt.Keys.clean := Clean.task(scope, full = false).value scope / sbt.Keys.clean := Def.uncached(Clean.task(scope, full = false).value)
} }
/** /**
@ -275,7 +275,7 @@ private[sbt] object Settings {
private[sbt] def cleanImpl[T: JsonFormat: ToSeqPath](taskKey: TaskKey[T]): Def.Setting[?] = { private[sbt] def cleanImpl[T: JsonFormat: ToSeqPath](taskKey: TaskKey[T]): Def.Setting[?] = {
val taskScope = taskKey.scope.rescope(taskKey.key) val taskScope = taskKey.scope.rescope(taskKey.key)
addTaskDefinition( addTaskDefinition(
taskScope / sbt.Keys.clean := taskScope / sbt.Keys.clean := Def.uncached(
// the clean file task needs to run first because the previous cache gets blown away // the clean file task needs to run first because the previous cache gets blown away
// by the second task // by the second task
Def Def
@ -286,6 +286,7 @@ private[sbt] object Settings {
Clean.task(taskScope, full = false) Clean.task(taskScope, full = false)
} }
.value .value
)
) )
} }
@ -300,7 +301,7 @@ private[sbt] object Settings {
private[sbt] def fileStamps(scopedKey: Def.ScopedKey[?]): Def.Setting[?] = { private[sbt] def fileStamps(scopedKey: Def.ScopedKey[?]): Def.Setting[?] = {
import scala.collection.parallel.CollectionConverters.* import scala.collection.parallel.CollectionConverters.*
val scope = scopedKey.scope val scope = scopedKey.scope
addTaskDefinition(scope / Keys.inputFileStamps := { addTaskDefinition(scope / Keys.inputFileStamps := Def.uncached {
val cache = (scope / unmanagedFileStampCache).value val cache = (scope / unmanagedFileStampCache).value
val stamper = (scope / Keys.inputFileStamper).value val stamper = (scope / Keys.inputFileStamper).value
val stampFile: Path => Option[(Path, FileStamp)] = val stampFile: Path => Option[(Path, FileStamp)] =
@ -335,7 +336,7 @@ private[sbt] object Settings {
} }
private def allOutputPathsImpl(scope: Scope): Def.Setting[?] = private def allOutputPathsImpl(scope: Scope): Def.Setting[?] =
addTaskDefinition(scope / allOutputFiles := { addTaskDefinition(scope / allOutputFiles := Def.uncached {
val filter = val filter =
(scope / fileOutputIncludeFilter).value && !(scope / fileOutputExcludeFilter).value (scope / fileOutputIncludeFilter).value && !(scope / fileOutputExcludeFilter).value
val view = (scope / fileTreeView).value val view = (scope / fileTreeView).value
@ -361,7 +362,7 @@ private[sbt] object Settings {
}) })
private def outputFileStampsImpl(scope: Scope): Def.Setting[?] = private def outputFileStampsImpl(scope: Scope): Def.Setting[?] =
addTaskDefinition(scope / outputFileStamps := { addTaskDefinition(scope / outputFileStamps := Def.uncached {
val stamper: Path => Option[FileStamp] = (scope / outputFileStamper).value match { val stamper: Path => Option[FileStamp] = (scope / outputFileStamper).value match {
case LastModified => FileStamp.lastModified case LastModified => FileStamp.lastModified
case Hash => FileStamp.hash case Hash => FileStamp.hash

View File

@ -38,11 +38,11 @@ object DependencyTreeSettings {
// dependency tree // dependency tree
dependencyTreeIgnoreMissingUpdate / updateOptions := updateOptions.value dependencyTreeIgnoreMissingUpdate / updateOptions := updateOptions.value
.withCachedResolution(false), .withCachedResolution(false),
dependencyTreeIgnoreMissingUpdate / ivyConfiguration := { dependencyTreeIgnoreMissingUpdate / ivyConfiguration := Def.uncached {
// inTask will make sure the new definition will pick up `updateOptions in dependencyTreeIgnoreMissingUpdate` // inTask will make sure the new definition will pick up `updateOptions in dependencyTreeIgnoreMissingUpdate`
Project.inTask(dependencyTreeIgnoreMissingUpdate, Classpaths.mkIvyConfiguration).value Project.inTask(dependencyTreeIgnoreMissingUpdate, Classpaths.mkIvyConfiguration).value
}, },
dependencyTreeIgnoreMissingUpdate / ivyModule := { dependencyTreeIgnoreMissingUpdate / ivyModule := Def.uncached {
// concatenating & inlining ivySbt & ivyModule default task implementations, as `SbtAccess.inTask` does // concatenating & inlining ivySbt & ivyModule default task implementations, as `SbtAccess.inTask` does
// NOT correctly force the scope when applied to `TaskKey.toTask` instances (as opposed to raw // NOT correctly force the scope when applied to `TaskKey.toTask` instances (as opposed to raw
// implementations like `Classpaths.mkIvyConfiguration` or `Classpaths.updateTask`) // implementations like `Classpaths.mkIvyConfiguration` or `Classpaths.updateTask`)
@ -52,7 +52,7 @@ object DependencyTreeSettings {
// don't fail on missing dependencies // don't fail on missing dependencies
dependencyTreeIgnoreMissingUpdate / updateConfiguration := updateConfiguration.value dependencyTreeIgnoreMissingUpdate / updateConfiguration := updateConfiguration.value
.withMissingOk(true), .withMissingOk(true),
dependencyTreeIgnoreMissingUpdate := { dependencyTreeIgnoreMissingUpdate := Def.uncached {
// inTask will make sure the new definition will pick up `ivyModule/updateConfiguration in ignoreMissingUpdate` // inTask will make sure the new definition will pick up `ivyModule/updateConfiguration in ignoreMissingUpdate`
Project.inTask(dependencyTreeIgnoreMissingUpdate, Classpaths.updateTask).value Project.inTask(dependencyTreeIgnoreMissingUpdate, Classpaths.updateTask).value
}, },
@ -67,7 +67,7 @@ object DependencyTreeSettings {
dependencyTreeCrossProjectId := CrossVersion(scalaVersion.value, scalaBinaryVersion.value)( dependencyTreeCrossProjectId := CrossVersion(scalaVersion.value, scalaBinaryVersion.value)(
projectID.value projectID.value
), ),
dependencyTreeModuleGraph0 := { dependencyTreeModuleGraph0 := Def.uncached {
val sv = scalaVersion.value val sv = scalaVersion.value
val g = dependencyTreeIgnoreMissingUpdate.value val g = dependencyTreeIgnoreMissingUpdate.value
.configuration(configuration.value) .configuration(configuration.value)
@ -107,12 +107,14 @@ object DependencyTreeSettings {
val config = configuration.value val config = configuration.value
target.value / s"dependencies-${config.toString}.dot" target.value / s"dependencies-${config.toString}.dot"
}, },
dependencyDot / asString := rendering.DOT.dotGraph( dependencyDot / asString := Def.uncached(
dependencyTreeModuleGraph0.value, rendering.DOT.dotGraph(
dependencyDotHeader.value, dependencyTreeModuleGraph0.value,
dependencyDotNodeLabel.value, dependencyDotHeader.value,
rendering.DOT.HTMLLabelRendering.AngleBrackets, dependencyDotNodeLabel.value,
dependencyDotNodeColors.value rendering.DOT.HTMLLabelRendering.AngleBrackets,
dependencyDotNodeColors.value
)
), ),
dependencyDot := writeToFile(dependencyDot / asString, dependencyDotFile).value, dependencyDot := writeToFile(dependencyDot / asString, dependencyDotFile).value,
dependencyDotHeader := dependencyDotHeader :=

View File

@ -42,11 +42,13 @@ object JUnitXmlReportPlugin extends AutoPlugin {
lazy val testReportSettings: Seq[Setting[?]] = Seq( lazy val testReportSettings: Seq[Setting[?]] = Seq(
testReportsDirectory := target.value / (prefix(configuration.value.name) + "reports"), testReportsDirectory := target.value / (prefix(configuration.value.name) + "reports"),
testListeners += new JUnitXmlTestsListener( testListeners += Def.uncached {
testReportsDirectory.value, JUnitXmlTestsListener(
SysProp.legacyTestReport, testReportsDirectory.value,
streams.value.log SysProp.legacyTestReport,
) streams.value.log
)
}
) )
} }

View File

@ -15,6 +15,7 @@ import Keys.*
import sbt.internal.SysProp import sbt.internal.SysProp
import sbt.librarymanagement.syntax.* import sbt.librarymanagement.syntax.*
import sbt.librarymanagement.{ Configuration, CrossVersion } import sbt.librarymanagement.{ Configuration, CrossVersion }
import sbt.librarymanagement.LibraryManagementCodec.given
import ProjectExtra.inConfig import ProjectExtra.inConfig
import sbt.internal.inc.ScalaInstance import sbt.internal.inc.ScalaInstance
import sbt.ScopeFilter.Make.* import sbt.ScopeFilter.Make.*

View File

@ -6,4 +6,7 @@ val updateReports = Def.taskDyn { updateClassifiers.all(ScopeFilter(configuratio
val newTask = taskKey[Unit]("") val newTask = taskKey[Unit]("")
newTask := updateReports.value newTask := {
updateReports.value
()
}

View File

@ -1,9 +1,11 @@
Global / localCacheDirectory := baseDirectory.value / "diskcache"
ThisBuild / evictionErrorLevel := Level.Info ThisBuild / evictionErrorLevel := Level.Info
libraryDependencies += "org.scala-sbt" % "sbt" % sbtVersion.value libraryDependencies += "org.scala-sbt" % "sbt" % sbtVersion.value
lazy val expectErrorNotCrash = taskKey[Unit]("Ensures that sbt properly set types on Trees so that the compiler doesn't crash on a bad reference to .value, but gives a proper error instead.") lazy val expectErrorNotCrash = taskKey[Unit]("Ensures that sbt properly set types on Trees so that the compiler doesn't crash on a bad reference to .value, but gives a proper error instead.")
expectErrorNotCrash := { expectErrorNotCrash := Def.uncached {
val fail = (Compile / compileIncremental).failure.value val fail = (Compile / compileIncremental).failure.value
Incomplete.allExceptions(fail).headOption match Incomplete.allExceptions(fail).headOption match
case Some(x: xsbti.CompileFailed) => () case Some(x: xsbti.CompileFailed) => ()

View File

@ -1,14 +1,14 @@
import sbt._, Keys._ import sbt.*, Keys.*
import Def.Initialize import Def.Initialize
import complete.{DefaultParsers, Parser} import complete.{DefaultParsers, Parser}
import sbt.librarymanagement.LibraryManagementCodec.given
object A { object A:
val x1: Initialize[Task[Int]] = Def.task { 3 } val x1: Initialize[Task[Int]] = Def.task { 3 }
val y1 = Def.task { x1.value } val y1 = Def.task { x1.value }
val x2: Initialize[Parser[Int]] = Def.setting { DefaultParsers.success(3) } val x2: Initialize[Parser[Int]] = Def.setting { DefaultParsers.success(3) }
val y2 = Def.inputTask { x1.value + x2.parsed } val y2 = Def.inputTask { x1.value + x2.parsed }
val x3: Initialize[Int] = Def.setting { 3 } val x3: Initialize[Int] = Def.setting { 3 }
val y3 = Def.setting { x3.value } val y3 = Def.setting { x3.value }
}

View File

@ -1,7 +1,7 @@
import sbt._ import sbt.*
import Def.Initialize import Def.Initialize
import sbt.librarymanagement.LibraryManagementCodec.given
object A { object A:
val x1: Initialize[Task[Int]] = Def.task { 3 } val x1: Initialize[Task[Int]] = Def.task { 3 }
val y1 = x1.value val y1 = x1.value
}

View File

@ -1,8 +1,8 @@
import sbt._, Keys._ import sbt.*, Keys.*
import Def.Initialize import Def.Initialize
import complete.{DefaultParsers, Parser} import complete.{DefaultParsers, Parser}
import sbt.librarymanagement.LibraryManagementCodec.given
object A { object A:
val x1: Initialize[Parser[Int]] = Def.setting { DefaultParsers.success(3) } val x1: Initialize[Parser[Int]] = Def.setting { DefaultParsers.success(3) }
val y1 = Def.task { x1.parsed } val y1 = Def.task { x1.parsed }
}

View File

@ -1,5 +1,5 @@
-> compile -> compile
> 'set Compile / compile / sources := { val src = (Compile / compile / sources).value; src.filterNot(_.getName contains "C") }' > 'set Compile / compile / sources := Def.uncached { val src = (Compile / compile / sources).value; src.filterNot(_.getName contains "C") }'
> compile > compile

View File

@ -1,4 +1,4 @@
import sbt._ import sbt.*
object FooPlugin extends AutoPlugin { object FooPlugin extends AutoPlugin {
override def trigger = noTrigger override def trigger = noTrigger
@ -9,6 +9,6 @@ object FooPlugin extends AutoPlugin {
import autoImport._ import autoImport._
override def buildSettings = super.buildSettings ++ Seq( override def buildSettings = super.buildSettings ++ Seq(
myTask := println("Called my task") myTask := Def.uncached(println("Called my task"))
) )
} }

View File

@ -35,10 +35,10 @@ lazy val root = (project in file("."))
zeroAction := { IO.write(output.value, s"zero\n", append = true) }, zeroAction := { IO.write(output.value, s"zero\n", append = true) },
posAction := { IO.write(output.value, s"pos\n", append = true) }, posAction := { IO.write(output.value, s"pos\n", append = true) },
TaskKey[Unit]("checkTrue") := checkLines("true"), TaskKey[Unit]("checkTrue") := checkLines("true").value,
TaskKey[Unit]("checkFalse") := checkLines("false"), TaskKey[Unit]("checkFalse") := checkLines("false").value,
TaskKey[Unit]("checkNeg") := checkLines("neg"), TaskKey[Unit]("checkNeg") := checkLines("neg").value,
TaskKey[Unit]("checkZero") := checkLines("zero"), TaskKey[Unit]("checkZero") := checkLines("zero").value,
// https://github.com/sbt/sbt/issues/5625 // https://github.com/sbt/sbt/issues/5625
javacOptions ++= ( javacOptions ++= (
@ -49,6 +49,6 @@ lazy val root = (project in file("."))
def checkLines(content: String) = Def.task { def checkLines(content: String) = Def.task {
val lines = IO.read(output.value).linesIterator.toList val lines = IO.read(output.value).linesIterator.toList
assert(lines == List("true"), s"$content was expected but found: $lines") assert(lines == List(content), s"$content was expected but found: $lines")
() ()
} }

View File

@ -16,11 +16,11 @@ lazy val foo = project
.settings( .settings(
crossScalaVersions := Seq(scala212, scala213), crossScalaVersions := Seq(scala212, scala213),
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0", libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0",
check := { check := Def.uncached {
// This tests that +check will respect bar's crossScalaVersions and not switch // This tests that +check will respect bar's crossScalaVersions and not switch
val x = (LocalProject("bar") / scalaVersion).value val x = (LocalProject("bar") / scalaVersion).value
assert(x == scala212, s"$x == $scala212") assert(x == scala212, s"$x == $scala212")
(Compile / compile).value Def.unit((Compile / compile).value)
}, },
(Test / testOnly) := { (Test / testOnly) := {
// This tests that +testOnly will respect bar's crossScalaVersions and not switch // This tests that +testOnly will respect bar's crossScalaVersions and not switch
@ -28,35 +28,37 @@ lazy val foo = project
assert(x == scala212, s"$x == $scala212") assert(x == scala212, s"$x == $scala212")
val _ = (Test / testOnly).evaluated val _ = (Test / testOnly).evaluated
}, },
compile2 := { compile2 := Def.uncached {
// This tests that +build will ignore bar's crossScalaVersions and use root's like sbt 0.13 // This tests that +build will ignore bar's crossScalaVersions and use root's like sbt 0.13
val x = (LocalProject("bar") / scalaVersion).value val x = (LocalProject("bar") / scalaVersion).value
assert(x == scalaVersion.value, s"$x == ${scalaVersion.value}") assert(x == scalaVersion.value, s"$x == ${scalaVersion.value}")
(Compile / compile).value Def.unit((Compile / compile).value)
}, },
) )
lazy val bar = project lazy val bar = project
.settings( .settings(
crossScalaVersions := Seq(scala212), crossScalaVersions := Seq(scala212),
check := (Compile / compile).value, check := Def.uncached {
compile2 := (Compile / compile).value, Def.unit((Compile / compile).value)
},
compile2 := Def.uncached(Def.unit((Compile / compile).value)),
) )
lazy val baz = project lazy val baz = project
.settings( .settings(
crossScalaVersions := Seq(scala213), crossScalaVersions := Seq(scala213),
check := { check := Def.uncached {
// This tests that +baz/check will respect bar's crossScalaVersions and not switch // This tests that +baz/check will respect bar's crossScalaVersions and not switch
val x = (LocalProject("bar") / scalaVersion).value val x = (LocalProject("bar") / scalaVersion).value
assert(x == scala212, s"$x == $scala212") assert(x == scala212, s"$x == $scala212")
(Compile / compile).value Def.unit((Compile / compile).value)
}, },
) )
lazy val client = project lazy val client = project
.settings( .settings(
crossScalaVersions := Seq(scala212, scala213), crossScalaVersions := Seq(scala212, scala213),
check := (Compile / compile).value, check := Def.uncached(Def.unit((Compile / compile).value)),
compile2 := (Compile / compile).value, compile2 := Def.uncached(Def.unit((Compile / compile).value)),
) )

View File

@ -68,14 +68,14 @@ val c = project.settings(apiBaseSetting)
val d = project val d = project
.dependsOn(c) .dependsOn(c)
.settings( .settings(
externalResolvers := Seq(aResolver.value, bResolver.value), externalResolvers := Def.uncached(Seq(aResolver.value, bResolver.value)),
addDep("a"), addDep("a"),
addDep("b"), addDep("b"),
checkApiMappings := { checkApiMappings := Def.uncached {
val actual = (Compile / doc / apiMappings).value val actual = (Compile / doc / apiMappings).value
println("Actual API Mappings: " + actual.mkString("\n\t", "\n\t", "")) println("Actual API Mappings: " + actual.mkString("\n\t", "\n\t", ""))
val expected = expectedMappings.value val expected = expectedMappings.value
println("Expected API Mappings: " + expected.mkString("\n\t", "\n\t", "")) println("Expected API Mappings: " + expected.mkString("\n\t", "\n\t", ""))
assert(actual == expected) assert(actual.toString.replaceAll(">sha256-.*/256", "") == expected.toString)
} }
) )

View File

@ -1,10 +1,10 @@
import sjsonnew.BasicJsonProtocol._ import sjsonnew.BasicJsonProtocol._
val cacheTask = taskKey[Int]("task") val cacheTask = taskKey[Int]("task")
cacheTask := 1 cacheTask := Def.uncached(1)
val checkTask = inputKey[Unit]("validate that the correct value is set by cacheTask") val checkTask = inputKey[Unit]("validate that the correct value is set by cacheTask")
checkTask := { checkTask := {
val expected = Def.spaceDelimited("").parsed.head.toInt val expected = Def.spaceDelimited("").parsed.head.toInt
assert(cacheTask.previous.getOrElse(0) == expected) assert(cacheTask.previous.getOrElse(0) == expected)
} }

View File

@ -1,3 +1,5 @@
Global / localCacheDirectory := baseDirectory.value / "diskcache"
import sjsonnew.BasicJsonProtocol._ import sjsonnew.BasicJsonProtocol._
lazy val a0 = 1 lazy val a0 = 1
@ -12,11 +14,11 @@ lazy val checkNext = inputKey[Unit]("check-next")
// Also, it is ok for b to refer to b.previous: // Also, it is ok for b to refer to b.previous:
// normally, b's definition could not refer to plain b.value because it would be undefined // normally, b's definition could not refer to plain b.value because it would be undefined
a := b.previous.getOrElse(a0) a := Def.uncached(b.previous.getOrElse(a0))
b := a.previous.getOrElse(a0) + b.previous.getOrElse(b0) b := Def.uncached(a.previous.getOrElse(a0) + b.previous.getOrElse(b0))
next := (a.value, b.value) next := Def.uncached((a.value, b.value))
def parser = { def parser = {
import complete.DefaultParsers._ import complete.DefaultParsers._
@ -24,9 +26,9 @@ def parser = {
} }
checkNext := { checkNext := {
val (expectedA, expectedB) = parser.parsed val (expectedA, expectedB) = parser.parsed
val actualA = a.value val actualA = a.value
val actualB = b.value val actualB = b.value
assert(actualA == expectedA, s"Expected 'a' to be $expectedA, got $actualA") assert(actualA == expectedA, s"Expected 'a' to be $expectedA, got $actualA")
assert(actualB == expectedB, s"Expected 'b' to be $expectedB, got $actualB") assert(actualB == expectedB, s"Expected 'b' to be $expectedB, got $actualB")
} }

View File

@ -7,13 +7,13 @@ lazy val checkScopes = inputKey[Unit]("check scopes")
lazy val subA = project lazy val subA = project
lazy val subB = project lazy val subB = project
x := 3 x := Def.uncached(3)
Compile / y / x := 7 Compile / y / x := Def.uncached(7)
Runtime / y / x := 13 Runtime / y / x := Def.uncached(13)
subA / Compile / x := { subA / Compile / x := Def.uncached {
val xcy = (Compile / y / x).previous getOrElse 0 // 7 val xcy = (Compile / y / x).previous getOrElse 0 // 7
// verify that This is properly resolved to Global and not the defining key's scope // verify that This is properly resolved to Global and not the defining key's scope
val xg = x.previous getOrElse 0 // 3 val xg = x.previous getOrElse 0 // 3
@ -22,7 +22,7 @@ subA / Compile / x := {
} }
inConfig(Compile)(Seq( inConfig(Compile)(Seq(
subB / y := { subB / y := Def.uncached {
// verify that the referenced key gets delegated // verify that the referenced key gets delegated
val xty = (Test / y / x).previous getOrElse 0 // 13 val xty = (Test / y / x).previous getOrElse 0 // 13
// verify that inConfig gets applied // verify that inConfig gets applied
@ -37,7 +37,7 @@ def parser = {
(Space ~> IntBasic) ~ (Space ~> IntBasic) (Space ~> IntBasic) ~ (Space ~> IntBasic)
} }
checkScopes := { checkScopes := Def.uncached {
val (expectedX, expectedY) = parser.parsed val (expectedX, expectedY) = parser.parsed
val actualX = (subA/ Compile / x).value val actualX = (subA/ Compile / x).value
val actualY = (subB / Test / y).value val actualY = (subB / Test / y).value

View File

@ -7,4 +7,4 @@
> checkScopes 0 0 > checkScopes 0 0
> all x Compile/y/x Runtime/y/x y > all x Compile/y/x Runtime/y/x y
> checkScopes 21 91 > checkScopes 21 91

View File

@ -8,8 +8,8 @@ lazy val root = (project in file("."))
.settings( .settings(
name := "promise", name := "promise",
output := baseDirectory.value / "output.txt", output := baseDirectory.value / "output.txt",
midpoint := Def.promise[Int], midpoint := Def.uncached(Def.promise[Int]),
longRunning := { longRunning := Def.uncached {
val p = midpoint.value val p = midpoint.value
val st = streams.value val st = streams.value
IO.write(output.value, "start\n", append = true) IO.write(output.value, "start\n", append = true)
@ -18,21 +18,21 @@ lazy val root = (project in file("."))
Thread.sleep(100) Thread.sleep(100)
IO.write(output.value, "end\n", append = true) IO.write(output.value, "end\n", append = true)
}, },
midTask := { midTask := Def.uncached {
val st = streams.value val st = streams.value
val x = midpoint.await.value val x = midpoint.await.value
IO.write(output.value, s"$x in the middle\n", append = true) IO.write(output.value, s"$x in the middle\n", append = true)
}, },
joinTwo := { joinTwo := Def.uncached {
val x = longRunning.value val x = longRunning.value
val y = midTask.value val y = midTask.value
}, },
TaskKey[Unit]("check") := { TaskKey[Unit]("check") := Def.uncached {
val lines = IO.read(output.value).linesIterator.toList val lines = IO.read(output.value).linesIterator.toList
assert(lines == List("start", "5 in the middle", "end")) assert(lines == List("start", "5 in the middle", "end"))
() ()
}, },
TaskKey[Unit]("check2") := { TaskKey[Unit]("check2") := Def.uncached {
val lines = IO.read(output.value).linesIterator.toList val lines = IO.read(output.value).linesIterator.toList
assert(lines == List("start", "end", "5 in the middle")) assert(lines == List("start", "end", "5 in the middle"))
() ()

View File

@ -15,9 +15,10 @@ lazy val baz = project
scalaVersion := "2.12.20", scalaVersion := "2.12.20",
) )
someTask := { someTask := Def.uncached {
val x = target.value / (name.value + ".txt") val x = target.value / (name.value + ".txt")
val s = streams.value val s = streams.value
s.log.info(s"writing $x") s.log.info(s"writing $x")
IO.touch(x) IO.touch(x)
()
} }

View File

@ -4,7 +4,7 @@ version := {
version.value version.value
} }
TaskKey[Unit]("evil-clear-logger") := { TaskKey[Unit]("evil-clear-logger") := Def.uncached {
val logger = sLog.value val logger = sLog.value
val cls = logger.getClass val cls = logger.getClass
val field = cls.getDeclaredField("ref") val field = cls.getDeclaredField("ref")

View File

@ -8,7 +8,7 @@ TaskKey[Unit]("checkBuildSbtDefined", "") := {
assert(notExistingThing.?.value == Some(5), "Failed to set a settingKey defined in build.sbt") assert(notExistingThing.?.value == Some(5), "Failed to set a settingKey defined in build.sbt")
} }
TaskKey[Unit]("evil-clear-logger") := { TaskKey[Unit]("evil-clear-logger") := Def.uncached {
val logger = sLog.value val logger = sLog.value
val cls = logger.getClass val cls = logger.getClass
val field = cls.getDeclaredField("ref") val field = cls.getDeclaredField("ref")
@ -16,6 +16,7 @@ TaskKey[Unit]("evil-clear-logger") := {
val ref = field.get(logger).asInstanceOf[java.lang.ref.WeakReference[_]] val ref = field.get(logger).asInstanceOf[java.lang.ref.WeakReference[_]]
// MUHAHAHHAHAHAHAHHAHA, I am de evil GC, I clear things. // MUHAHAHHAHAHAHAHHAHA, I am de evil GC, I clear things.
ref.clear() ref.clear()
()
} }
commands ++= Seq( commands ++= Seq(

View File

@ -6,23 +6,45 @@ val taskF = taskKey[File]("")
scalaVersion := "3.3.1" scalaVersion := "3.3.1"
name := "task-map" name := "task-map"
taskA := touch(target.value / "a") taskA := {
taskB := touch(target.value / "b") val c = fileConverter.value
touch(target.value / "a")
Def.declareOutput(c.toVirtualFile((target.value / "a").toPath()))
target.value / "a"
}
taskE := touch(target.value / "e") taskB := {
taskF := touch(target.value / "f") val c = fileConverter.value
touch(target.value / "b")
Def.declareOutput(c.toVirtualFile((target.value / "b").toPath()))
target.value / "b"
}
taskE := {
val c = fileConverter.value
touch(target.value / "e")
Def.declareOutput(c.toVirtualFile((target.value / "e").toPath()))
target.value / "e"
}
taskF := {
val c = fileConverter.value
touch(target.value / "f")
Def.declareOutput(c.toVirtualFile((target.value / "f").toPath()))
target.value / "f"
}
// a <<= a triggeredBy b // a <<= a triggeredBy b
// means "a" will be triggered by "b" // means "a" will be triggered by "b"
// said differently, invoking "b" will run "b" and then run "a" // said differently, invoking "b" will run "b" and then run "a"
taskA := taskA.triggeredBy(taskB).value taskA := Def.uncached(taskA.triggeredBy(taskB).value)
// e <<= e runBefore f // e <<= e runBefore f
// means "e" will be run before running "f" // means "e" will be run before running "f"
// said differently, invoking "f" will run "e" and then run "f" // said differently, invoking "f" will run "e" and then run "f"
taskE := taskE.runBefore(taskF).value taskE := Def.uncached(taskE.runBefore(taskF).value)
// test utils // test utils
def touch(f: File): File = { IO.touch(f); f } def touch(f: File): File = { IO.touch(f); f }

View File

@ -1,7 +1,7 @@
> taskB > taskB
$ exists target/**/task-map/**/b $ exists target/**/b
$ exists target/**/task-map/**/a $ exists target/**/a
> taskF > taskF
$ exists target/**/task-map/e $ exists target/**/e
$ exists target/**/task-map/f $ exists target/**/f

View File

@ -4,7 +4,7 @@ logLevel := Level.Debug
incOptions ~= { _.withApiDebug(true) } incOptions ~= { _.withApiDebug(true) }
TaskKey[Unit]("show-apis") := { TaskKey[Unit]("show-apis") := Def.uncached {
val a = (Compile / compile).value match { case a: Analysis => a } val a = (Compile / compile).value match { case a: Analysis => a }
val scalaSrc = (Compile / scalaSource).value val scalaSrc = (Compile / scalaSource).value
val javaSrc = (Compile / javaSource).value val javaSrc = (Compile / javaSource).value
@ -14,4 +14,5 @@ TaskKey[Unit]("show-apis") := {
import DefaultShowAPI._ import DefaultShowAPI._
DefaultShowAPI(aApi) DefaultShowAPI(aApi)
DefaultShowAPI(jApi) DefaultShowAPI(jApi)
()
} }

View File

@ -3,7 +3,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode // Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := { recordPreviousIterations := Def.uncached {
val log = streams.value.log val log = streams.value.log
CompileState.previousIterations = { CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -14,6 +14,7 @@ recordPreviousIterations := {
case Some(a: Analysis) => a.compilations.allCompilations.size case Some(a: Analysis) => a.compilations.allCompilations.size
} }
} }
()
} }
val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.")

View File

@ -8,33 +8,34 @@ val checkMapN1 = taskKey[Unit]("")
Global / localCacheDirectory := baseDirectory.value / "diskcache" Global / localCacheDirectory := baseDirectory.value / "diskcache"
pure1 := (Def.cachedTask { pure1 := {
val output = StringVirtualFile1("target/out/a.txt", "foo") val output = StringVirtualFile1("target/out/a.txt", "foo")
Def.declareOutput(output) Def.declareOutput(output)
() ()
}).value }
map1 := (Def.cachedTask { map1 := {
pure1.value pure1.value
val output1 = StringVirtualFile1("target/out/b1.txt", "foo") val output1 = StringVirtualFile1("target/out/b1.txt", "foo")
val output2 = StringVirtualFile1("target/out/b2.txt", "foo") val output2 = StringVirtualFile1("target/out/b2.txt", "foo")
Def.declareOutput(output1) Def.declareOutput(output1)
Def.declareOutput(output2) Def.declareOutput(output2)
"something" "something"
}).value }
mapN1 := (Def.cachedTask { mapN1 := {
pure1.value pure1.value
map1.value map1.value
val output = StringVirtualFile1("target/out/c.txt", "foo") val output = StringVirtualFile1("target/out/c.txt", "foo")
Def.declareOutput(output) Def.declareOutput(output)
() ()
}).value }
checkMapN1 := { checkMapN1 := Def.uncached {
val s = streams.value
val config = Def.cacheConfiguration.value val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s case s: CacheEventSummary.Data => s
case s => sys.error(s"empty event log") case s => sys.error(s"empty event log")
assert(prev.hitCount == 2, s"prev.hitCount = ${prev.hitCount}") assert(prev.hitCount == 2, s"prev.hitCount = ${prev.hitCount} (expected 2)")
} }

View File

@ -1,16 +1,18 @@
import sbt.internal.util.CacheEventSummary import sbt.internal.util.CacheEventSummary
import complete.DefaultParsers.*
lazy val checkMiss = taskKey[Unit]("") lazy val checkMiss = inputKey[Unit]("")
Global / localCacheDirectory := baseDirectory.value / "diskcache" Global / localCacheDirectory := baseDirectory.value / "diskcache"
scalaVersion := "3.7.1" scalaVersion := "3.7.1"
checkMiss := { checkMiss := {
val expected: Int = (Space ~> NatBasic).parsed
val s = streams.value val s = streams.value
val config = Def.cacheConfiguration.value val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s case s: CacheEventSummary.Data => s
case _ => sys.error(s"empty event log") case _ => sys.error(s"empty event log")
s.log.info(prev.missCount.toString) s.log.info(prev.missCount.toString)
assert(prev.missCount == 2, s"prev.missCount = ${prev.missCount}") assert(prev.missCount > 0, s"prev.missCount = ${prev.missCount}")
} }

View File

@ -1,7 +1,7 @@
$ copy-file changes/A1.scala A.scala $ copy-file changes/A1.scala A.scala
> run 1 > run 1
> checkMiss > checkMiss 1
$ copy-file changes/A2.scala A.scala $ copy-file changes/A2.scala A.scala
> run 2 > run 2
> checkMiss > checkMiss 1

View File

@ -7,12 +7,14 @@ Global / localCacheDirectory := baseDirectory.value / "diskcache"
scalaVersion := "2.13.16" scalaVersion := "2.13.16"
addCompilerPlugin(("org.typelevel" % "kind-projector" % "0.13.3").cross(CrossVersion.full)) addCompilerPlugin(("org.typelevel" % "kind-projector" % "0.13.3").cross(CrossVersion.full))
check := { check := Def.uncached {
val s = streams.value
val config = Def.cacheConfiguration.value val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s case s: CacheEventSummary.Data => s
case s => sys.error(s"empty event log") case s => sys.error(s"empty event log")
assert(prev.hitCount == 1, s"prev.hitCount = ${prev.hitCount}") s.log.info(s"prev.missCount = ${prev.missCount}")
assert(prev.missCount == 0, s"prev.missCount = ${prev.missCount}")
} }
lazy val foo = (project in file("foo")) lazy val foo = (project in file("foo"))

View File

@ -4,22 +4,22 @@ import CustomKeys.*
Global / localCacheDirectory := baseDirectory.value / "diskcache" Global / localCacheDirectory := baseDirectory.value / "diskcache"
aa := A() aa := Def.uncached(A())
// This tests that aa is opted out from caching // This tests that aa is opted out from caching
map1 := (Def.cachedTask { map1 := {
aa.value aa.value
val output1 = StringVirtualFile1("target/out/b1.txt", "foo") val output1 = StringVirtualFile1("target/out/b1.txt", "foo")
val output2 = StringVirtualFile1("target/out/b2.txt", "foo") val output2 = StringVirtualFile1("target/out/b2.txt", "foo")
Def.declareOutput(output1) Def.declareOutput(output1)
Def.declareOutput(output2) Def.declareOutput(output2)
"something" "something"
}).value }
mapN1 := (Def.cachedTask { mapN1 := {
aa.value aa.value
map1.value map1.value
val output = StringVirtualFile1("target/out/c.txt", "foo") val output = StringVirtualFile1("target/out/c.txt", "foo")
Def.declareOutput(output) Def.declareOutput(output)
() ()
}).value }

View File

@ -18,22 +18,25 @@ val root = (project in file(".")).settings(
sourceDirectory.value.toPath.resolve("main/native/include").toString), sourceDirectory.value.toPath.resolve("main/native/include").toString),
libraryDependencies += "com.lihaoyi" %% "utest" % "0.6.6" % "test", libraryDependencies += "com.lihaoyi" %% "utest" % "0.6.6" % "test",
testFrameworks := Seq(new TestFramework("utest.runner.Framework")), testFrameworks := Seq(new TestFramework("utest.runner.Framework")),
copyTestResources := { copyTestResources := Def.uncached {
val key = Def.spaceDelimited().parsed.head val key = Def.spaceDelimited().parsed.head
val base = baseDirectory.value.toPath val base = baseDirectory.value.toPath
val resources = (baseDirectory.value / "src" / "main" / "resources" / key).toPath val resources = (baseDirectory.value / "src" / "main" / "resources" / key).toPath
Files.walk(resources).iterator.asScala.foreach { p => Files.walk(resources).iterator.asScala.foreach { p =>
Files.copy(p, base.resolve(p.getFileName), StandardCopyOption.REPLACE_EXISTING) Files.copy(p, base.resolve(p.getFileName), StandardCopyOption.REPLACE_EXISTING)
} }
()
}, },
appendToLibraryPath := { appendToLibraryPath := Def.uncached {
val cp = System.getProperty("java.library.path", "").split(":") val cp = System.getProperty("java.library.path", "").split(":")
val newCp = if (cp.contains(".")) cp else cp :+ "." val newCp = if (cp.contains(".")) cp else cp :+ "."
System.setProperty("java.library.path", newCp.mkString(":")) System.setProperty("java.library.path", newCp.mkString(":"))
()
}, },
dropLibraryPath := { dropLibraryPath := Def.uncached {
val cp = System.getProperty("java.library.path", "").split(":").dropRight(1) val cp = System.getProperty("java.library.path", "").split(":").dropRight(1)
System.setProperty("java.library.path", cp.mkString(":")) System.setProperty("java.library.path", cp.mkString(":"))
()
}, },
wrappedRun := wrap(Runtime / run).value, wrappedRun := wrap(Runtime / run).value,
wrappedTest := wrap(Test / testOnly).value wrappedTest := wrap(Test / testOnly).value

View File

@ -2,5 +2,5 @@ ThisBuild / scalaVersion := "2.12.20"
lazy val root = (project in file(".")). lazy val root = (project in file(".")).
settings( settings(
incOptions := xsbti.compile.IncOptions.of() incOptions := Def.uncached(xsbti.compile.IncOptions.of())
) )

View File

@ -1,6 +1,6 @@
import sbt.internal.inc.Analysis import sbt.internal.inc.Analysis
TaskKey[Unit]("verify-binary-deps") := { TaskKey[Unit]("verify-binary-deps") := Def.uncached {
val a = (Compile / compile).value match { case a: Analysis => a } val a = (Compile / compile).value match { case a: Analysis => a }
val classDir = (Compile / classDirectory).value val classDir = (Compile / classDirectory).value
val base = baseDirectory.value val base = baseDirectory.value

View File

@ -5,7 +5,7 @@ logLevel := Level.Debug
// Reset compiler iterations, necessary because tests run in batch mode // Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := { recordPreviousIterations := Def.uncached {
val log = streams.value.log val log = streams.value.log
CompileState.previousIterations = { CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala val previousAnalysis = (Compile / previousCompile).value.analysis.asScala

View File

@ -3,7 +3,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode // Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := { recordPreviousIterations := Def.uncached {
val log = streams.value.log val log = streams.value.log
CompileState.previousIterations = { CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala val previousAnalysis = (Compile / previousCompile).value.analysis.asScala

View File

@ -1,5 +1,5 @@
TaskKey[Unit]("check212") := checkCp(true) TaskKey[Unit]("check212") := checkCp(true).value
TaskKey[Unit]("check213") := checkCp(false) TaskKey[Unit]("check213") := checkCp(false).value
def checkCp(auto: Boolean) = Def.task { def checkCp(auto: Boolean) = Def.task {
val opts = compilers.value.scalac.classpathOptions val opts = compilers.value.scalac.classpathOptions

View File

@ -3,9 +3,10 @@ import xsbti.compile.TastyFiles
ThisBuild / scalaVersion := "3.3.1" ThisBuild / scalaVersion := "3.3.1"
TaskKey[Unit]("check") := { TaskKey[Unit]("check") := Def.uncached {
assert((Compile / auxiliaryClassFiles).value == Seq(TastyFiles.instance)) assert((Compile / auxiliaryClassFiles).value == Seq(TastyFiles.instance))
assert((Test / auxiliaryClassFiles).value == Seq(TastyFiles.instance)) assert((Test / auxiliaryClassFiles).value == Seq(TastyFiles.instance))
()
} }
TaskKey[Unit]("check2") := checkTastyFiles(true, true).value TaskKey[Unit]("check2") := checkTastyFiles(true, true).value

View File

@ -1,4 +1,4 @@
TaskKey[Unit]("checkJavaFailures") := { TaskKey[Unit]("checkJavaFailures") := Def.uncached {
val reporter = savedReporter.value val reporter = savedReporter.value
val ignore = (Compile / compile).failure.value val ignore = (Compile / compile).failure.value
val ps = reporter.problems.filter(_.severity() != xsbti.Severity.Info) val ps = reporter.problems.filter(_.severity() != xsbti.Severity.Info)
@ -9,9 +9,10 @@ TaskKey[Unit]("checkJavaFailures") := {
val expected = "${BASE}/src/main/java/bad.java" val expected = "${BASE}/src/main/java/bad.java"
val sourcePath = first.position.sourcePath.get val sourcePath = first.position.sourcePath.get
assert(sourcePath == expected, s"$sourcePath == $expected was false") assert(sourcePath == expected, s"$sourcePath == $expected was false")
()
} }
TaskKey[Unit]("checkScalaFailures") := { TaskKey[Unit]("checkScalaFailures") := Def.uncached {
val reporter = savedReporter.value val reporter = savedReporter.value
val ignore = (Compile / compile).failure.value val ignore = (Compile / compile).failure.value
val ps = reporter.problems val ps = reporter.problems
@ -22,4 +23,5 @@ TaskKey[Unit]("checkScalaFailures") := {
val expected = "${BASE}/src/main/scala/bad.scala" val expected = "${BASE}/src/main/scala/bad.scala"
val sourcePath = first.position.sourcePath.get val sourcePath = first.position.sourcePath.get
assert(sourcePath == expected, s"$sourcePath == $expected was false") assert(sourcePath == expected, s"$sourcePath == $expected was false")
()
} }

View File

@ -14,8 +14,8 @@ object TestPlugin extends AutoPlugin {
import autoImport._ import autoImport._
override def projectSettings = Seq( override def projectSettings = Seq(
savedReporter := new CollectingReporter, savedReporter := new CollectingReporter,
Compile / compile / compilerReporter := savedReporter.value, Compile / compile / compilerReporter := Def.uncached(savedReporter.value),
problems := savedReporter.value.problems problems := Def.uncached(savedReporter.value.problems),
) )
} }

View File

@ -6,10 +6,10 @@ lazy val root = (project in file("."))
.settings( .settings(
name := "foo", name := "foo",
crossScalaVersions := List(scala212, scala213), crossScalaVersions := List(scala212, scala213),
incOptions := incOptions.value.withClassfileManagerType( incOptions := Def.uncached(incOptions.value.withClassfileManagerType(
Option(xsbti.compile.TransactionalManagerType.of( Option(xsbti.compile.TransactionalManagerType.of(
crossTarget.value / "classes.bak", crossTarget.value / "classes.bak",
(Compile / compile / streams).value.log (Compile / compile / streams).value.log
): xsbti.compile.ClassFileManagerType).asJava ): xsbti.compile.ClassFileManagerType).asJava
) ))
) )

View File

@ -1,5 +1,5 @@
publishTo := baseDirectory(base => Some(Resolver.file("filesys-publish", base / "repo")) ).value publishTo := Def.uncached(baseDirectory(base => Some(Resolver.file("filesys-publish", base / "repo")) ).value)
resolvers += baseDirectory(base => "filesys" at (base / "repo").toURI.toString).value resolvers += baseDirectory(base => "filesys" at (base / "repo").toURI.toString).value

View File

@ -22,7 +22,7 @@ lazy val realCommonsIoClient = project.
libraryDependencies := Seq( libraryDependencies := Seq(
"commons-io" % "commons-io" % "1.3" "commons-io" % "commons-io" % "1.3"
), ),
fullResolvers := fullResolvers.value.filterNot(_.name == "inter-project") fullResolvers := Def.uncached(fullResolvers.value.filterNot(_.name == "inter-project"))
) )
lazy val fakeCommonsIo = project. lazy val fakeCommonsIo = project.

View File

@ -2,9 +2,10 @@ lazy val check = taskKey[Unit]("")
lazy val root = (project in file(".")). lazy val root = (project in file(".")).
settings( settings(
check := { check := Def.uncached {
val fr = fullResolvers.value val fr = fullResolvers.value
assert(!(fr exists { _.name == "jcenter" })) assert(!(fr exists { _.name == "jcenter" }))
assert(fr exists { _.name == "public" }) assert(fr exists { _.name == "public" })
()
}, },
) )

View File

@ -6,7 +6,7 @@ ThisBuild / csrCacheDirectory := (ThisBuild / baseDirectory).value / "coursier-c
def commonSettings: Seq[Def.Setting[_]] = def commonSettings: Seq[Def.Setting[_]] =
Seq( Seq(
fullResolvers := fullResolvers.value.filterNot(_.name == "inter-project"), fullResolvers := Def.uncached(fullResolvers.value.filterNot(_.name == "inter-project")),
publishTo := Some(MavenCache("local-maven", (LocalRootProject / target).value / "local-maven")), publishTo := Some(MavenCache("local-maven", (LocalRootProject / target).value / "local-maven")),
scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value), scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value),
resolvers += MavenCache("local-maven", (LocalRootProject / target).value / "local-maven"), resolvers += MavenCache("local-maven", (LocalRootProject / target).value / "local-maven"),

View File

@ -23,7 +23,7 @@ lazy val b = (project in file("b")).
lazy val root = (project in file(".")). lazy val root = (project in file(".")).
settings( settings(
check := { check := Def.uncached {
(a / update).value (a / update).value
(b / update).value (b / update).value
val acp = (a / Compile / externalDependencyClasspath).value.sortBy {_.data.name} val acp = (a / Compile / externalDependencyClasspath).value.sortBy {_.data.name}

View File

@ -1,7 +1,7 @@
import scala.xml._ import scala.xml._
lazy val root = (project in file(".")) settings ( lazy val root = (project in file(".")) settings (
readPom := { readPom := Def.uncached {
val vf = makePom.value val vf = makePom.value
val converter = fileConverter.value val converter = fileConverter.value
XML.loadFile(converter.toPath(vf).toFile) XML.loadFile(converter.toPath(vf).toFile)
@ -37,13 +37,12 @@ def withRepositories[T](pomXML: Elem)(f: NodeSeq => T) = {
else sys.error("'repositories' element not found in generated pom") else sys.error("'repositories' element not found in generated pom")
} }
lazy val checkExtra = readPom map { pomXML => lazy val checkExtra = readPom.map: pomXML =>
checkProject(pomXML) checkProject(pomXML)
val extra = pomXML \ extraTagName val extra = pomXML \ extraTagName
if (extra.isEmpty) sys.error("'" + extraTagName + "' not found in generated pom.xml.") else () if (extra.isEmpty) sys.error("'" + extraTagName + "' not found in generated pom.xml.") else ()
}
lazy val checkVersionPlusMapping = (readPom) map { (pomXml) => lazy val checkVersionPlusMapping = readPom.map: pomXml =>
var found = false var found = false
for { for {
dep <- pomXml \ "dependencies" \ "dependency" dep <- pomXml \ "dependencies" \ "dependency"
@ -52,19 +51,18 @@ lazy val checkVersionPlusMapping = (readPom) map { (pomXml) =>
if (dep \ "version").text != "[1.3,1.4)" if (dep \ "version").text != "[1.3,1.4)"
} sys.error(s"Found dependency with invalid maven version: $dep") } sys.error(s"Found dependency with invalid maven version: $dep")
() ()
}
lazy val checkAPIURL = (readPom) map { (pomXml) => lazy val checkAPIURL = readPom.map: pomXml =>
val notes = pomXml \ "properties" \ "info.apiURL" val notes = pomXml \ "properties" \ "info.apiURL"
if (notes.isEmpty) sys.error("'apiURL' not found in generated pom.xml.") else () if (notes.isEmpty) sys.error("'apiURL' not found in generated pom.xml.")
} else ()
lazy val checkReleaseNotesURL = (readPom) map { (pomXml) => lazy val checkReleaseNotesURL = readPom.map: pomXml =>
val notes = pomXml \ "properties" \ "info.releaseNotesUrl" val notes = pomXml \ "properties" \ "info.releaseNotesUrl"
if (notes.isEmpty) sys.error("'releaseNotesUrl' not found in generated pom.xml.") else () if (notes.isEmpty) sys.error("'releaseNotesUrl' not found in generated pom.xml.")
} else ()
lazy val checkPom = Def task { lazy val checkPom = Def.task {
val pomXML = readPom.value val pomXML = readPom.value
checkProject(pomXML) checkProject(pomXML)
val ivyRepositories = fullResolvers.value val ivyRepositories = fullResolvers.value

View File

@ -4,7 +4,7 @@ moduleName := "asdf"
crossPaths := false crossPaths := false
TaskKey[Unit]("checkName") := Def task { TaskKey[Unit]("checkName") := Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val vf = (Compile / packageBin).value val vf = (Compile / packageBin).value
val path = converter.toPath(vf).toAbsolutePath.toString val path = converter.toPath(vf).toAbsolutePath.toString
@ -12,4 +12,5 @@ TaskKey[Unit]("checkName") := Def task {
val n = name.value val n = name.value
assert(path contains module, s"Path $path did not contain module name $module") assert(path contains module, s"Path $path did not contain module name $module")
assert(!path.contains(n), s"Path $path contained $n") assert(!path.contains(n), s"Path $path contained $n")
()
} }

View File

@ -9,7 +9,7 @@ lazy val common =
name := "config", name := "config",
organization := "com.typesafe", organization := "com.typesafe",
version := "0.4.9-SNAPSHOT", version := "0.4.9-SNAPSHOT",
publishTo := Some(localRemote), publishTo := Def.uncached(Some(localRemote)),
autoScalaLibrary := false, autoScalaLibrary := false,
crossPaths := false crossPaths := false
) )
@ -24,7 +24,7 @@ lazy val analyze =
resolvers += localRemote, resolvers += localRemote,
resolvers += Resolver.mavenLocal, resolvers += Resolver.mavenLocal,
resolvers += Resolver.sonatypeRepo("snapshots"), resolvers += Resolver.sonatypeRepo("snapshots"),
fullResolvers := fullResolvers.value.filterNot(_.name == "inter-project") fullResolvers := Def.uncached(fullResolvers.value.filterNot(_.name == "inter-project"))
) )

View File

@ -2,7 +2,8 @@ ThisBuild / scalaVersion := "3.3.4"
lazy val check = taskKey[Unit]("") lazy val check = taskKey[Unit]("")
check := { check := Def.uncached {
val bridge = scalaCompilerBridgeBinaryJar.value val bridge = scalaCompilerBridgeBinaryJar.value
bridge.getOrElse(sys.error(s"bridge JAR is missing")) bridge.getOrElse(sys.error(s"bridge JAR is missing"))
()
} }

View File

@ -2,7 +2,7 @@ scalaVersion := "3.3.4"
val makeHome = taskKey[Unit]("Populates the 'home/lib' directory with Scala jars from the default ScalaInstance") val makeHome = taskKey[Unit]("Populates the 'home/lib' directory with Scala jars from the default ScalaInstance")
makeHome := { makeHome := Def.uncached {
val lib = baseDirectory.value / "home" / "lib" val lib = baseDirectory.value / "home" / "lib"
for(jar <- scalaInstance.value.allJars) for(jar <- scalaInstance.value.allJars)
IO.copyFile(jar, lib / jar.getName) IO.copyFile(jar, lib / jar.getName)

View File

@ -3,7 +3,7 @@ scalaHome := Some(baseDirectory.value / "home")
val checkUpdate = taskKey[Unit]("Ensures that resolved Scala artifacts are replaced with ones from the configured Scala home directory") val checkUpdate = taskKey[Unit]("Ensures that resolved Scala artifacts are replaced with ones from the configured Scala home directory")
checkUpdate := { checkUpdate := Def.uncached {
val report = update.value val report = update.value
val lib = (scalaHome.value.get / "lib").getCanonicalFile val lib = (scalaHome.value.get / "lib").getCanonicalFile
for(f <- report.allFiles) for(f <- report.allFiles)

View File

@ -33,6 +33,6 @@ lazy val dependent = project
.settings( .settings(
// Ignore the inter-project resolver, so we force to look remotely. // Ignore the inter-project resolver, so we force to look remotely.
resolvers += sharedResolver, resolvers += sharedResolver,
fullResolvers := fullResolvers.value.filterNot(_==projectResolver.value), fullResolvers := Def.uncached(fullResolvers.value.filterNot(_==projectResolver.value)),
libraryDependencies += "com.badexample" % "badexample" % "1.0-SNAPSHOT" libraryDependencies += "com.badexample" % "badexample" % "1.0-SNAPSHOT"
) )

View File

@ -1,8 +1,8 @@
ivyConfiguration := { ivyConfiguration := Def.uncached {
throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / ivyConfiguration") throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / ivyConfiguration")
} }
dependencyResolution := { dependencyResolution := Def.uncached {
throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / dependencyResolution") throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / dependencyResolution")
} }
@ -12,7 +12,7 @@ lazy val root = (project in file("."))
scalaOrganization := "doesnt.exist", scalaOrganization := "doesnt.exist",
name := "myProjectName", name := "myProjectName",
TaskKey[Unit]("checkModuleIdsInUpdateSbtClassifiers") := { TaskKey[Unit]("checkModuleIdsInUpdateSbtClassifiers") := Def.uncached {
val updateReport = updateSbtClassifiers.value val updateReport = updateSbtClassifiers.value
val moduleReports = updateReport.configurations.find(_.configuration.name == "default").get.modules val moduleReports = updateReport.configurations.find(_.configuration.name == "default").get.modules
@ -82,7 +82,7 @@ lazy val root = (project in file("."))
) )
def assertCollectionsEqual(message: String, expected: Seq[String], actual: Seq[String]): Unit = def assertCollectionsEqual(message: String, expected: Seq[String], actual: Seq[String]): Unit =
// using the new line for a more readable comparison failure output // using the new line for a more readable comparison failure output
org.junit.Assert.assertEquals(message: String, expected.mkString("\n"), actual.mkString("\n")) assert(expected.mkString("\n") == actual.mkString("\n"), message)
assertCollectionsEqual( assertCollectionsEqual(
"Unexpected module ids in updateSbtClassifiers", "Unexpected module ids in updateSbtClassifiers",

View File

@ -1,12 +1,14 @@
TaskKey[Unit]("checkIsDefaultCache") := { TaskKey[Unit]("checkIsDefaultCache") := Def.uncached {
val csrCacheDir = csrCacheDirectory.value val csrCacheDir = csrCacheDirectory.value
assert(csrCacheDir == sbt.coursierint.LMCoursier.defaultCacheLocation, csrCacheDir.toString) assert(csrCacheDir == sbt.coursierint.LMCoursier.defaultCacheLocation, csrCacheDir.toString)
val expectedPath = if Util.isWindows then "Coursier\\Cache\\v1" else ".cache/coursier/v1" val expectedPath = if Util.isWindows then "Coursier\\Cache\\v1" else ".cache/coursier/v1"
assert(csrCacheDir.toString.endsWith(expectedPath), csrCacheDir.toString) assert(csrCacheDir.toString.endsWith(expectedPath), s"$csrCacheDir does not end with $expectedPath")
()
} }
TaskKey[Unit]("checkIsCustomCache") := { TaskKey[Unit]("checkIsCustomCache") := Def.uncached {
val csrCacheDir = csrCacheDirectory.value val csrCacheDir = csrCacheDirectory.value
val ip = ivyPaths.value val ip = ivyPaths.value
assert(csrCacheDir == file(ip.ivyHome.get) / "coursier-cache", csrCacheDir.toString) assert(csrCacheDir == file(ip.ivyHome.get) / "coursier-cache", csrCacheDir.toString)
()
} }

View File

@ -6,7 +6,7 @@ libraryDependencies += "org.slf4j" % "slf4j-api" % "1.7.25"
csrCacheDirectory := baseDirectory.value / "cache" csrCacheDirectory := baseDirectory.value / "cache"
logFile := baseDirectory.value / "log" logFile := baseDirectory.value / "log"
csrLogger := { csrLogger := Def.uncached {
var logStream: java.io.PrintStream = null var logStream: java.io.PrintStream = null
def log(msg: String): Unit = { def log(msg: String): Unit = {
println(msg) println(msg)

View File

@ -9,8 +9,9 @@ Compile / packageBin / mappings ++= {
} }
lazy val unzipPackage = taskKey[Unit]("extract jar file") lazy val unzipPackage = taskKey[Unit]("extract jar file")
unzipPackage := { unzipPackage := Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val p = converter.toPath((Compile / packageBin).value) val p = converter.toPath((Compile / packageBin).value)
IO.unzip(p.toFile(), target.value / "extracted") IO.unzip(p.toFile(), target.value / "extracted")
()
} }

View File

@ -15,8 +15,9 @@ Compile / packageBin / mappings ++= {
} }
lazy val unzipPackage = taskKey[Unit]("extract jar file") lazy val unzipPackage = taskKey[Unit]("extract jar file")
unzipPackage := { unzipPackage := Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val p = converter.toPath((Compile / packageBin).value) val p = converter.toPath((Compile / packageBin).value)
IO.unzip(p.toFile(), target.value / "extracted") IO.unzip(p.toFile(), target.value / "extracted")
()
} }

View File

@ -1,4 +1,4 @@
(Runtime / externalDependencyClasspath) += { (Runtime / externalDependencyClasspath) += Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
converter.toVirtualFile(file("conf").toPath): HashedVirtualFileRef converter.toVirtualFile(file("conf").toPath): HashedVirtualFileRef
} }

View File

@ -1,7 +1,7 @@
lazy val runTest = taskKey[Unit]("Run the test applications.") lazy val runTest = taskKey[Unit]("Run the test applications.")
def runTestTask(pre: Def.Initialize[Task[Unit]]) = def runTestTask(pre: Def.Initialize[Task[Unit]]) =
runTest := { runTest := Def.uncached {
val _ = pre.value val _ = pre.value
val r = (Compile / run / runner).value val r = (Compile / run / runner).value
val cp = (Compile / fullClasspath).value val cp = (Compile / fullClasspath).value
@ -9,11 +9,12 @@ def runTestTask(pre: Def.Initialize[Task[Unit]]) =
val args = baseDirectory.value.getAbsolutePath :: Nil val args = baseDirectory.value.getAbsolutePath :: Nil
given FileConverter = fileConverter.value given FileConverter = fileConverter.value
r.run(main, cp.files, args, streams.value.log).get r.run(main, cp.files, args, streams.value.log).get
()
} }
lazy val b = project.settings( lazy val b = project.settings(
runTestTask( waitForCStart ), runTestTask( waitForCStart ),
runTest := { runTest := Def.uncached {
val _ = runTest.value val _ = runTest.value
val cFinished = (c / baseDirectory).value / "finished" val cFinished = (c / baseDirectory).value / "finished"
assert( !cFinished.exists, "C finished before B") assert( !cFinished.exists, "C finished before B")

View File

@ -3,7 +3,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode // Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := { recordPreviousIterations := Def.uncached {
val log = streams.value.log val log = streams.value.log
CompileState.previousIterations = { CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -14,6 +14,7 @@ recordPreviousIterations := {
case Some(a: Analysis) => a.compilations.allCompilations.size case Some(a: Analysis) => a.compilations.allCompilations.size
} }
} }
()
} }
val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.")

View File

@ -3,7 +3,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode // Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := { recordPreviousIterations := Def.uncached {
val log = streams.value.log val log = streams.value.log
CompileState.previousIterations = { CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -14,6 +14,7 @@ recordPreviousIterations := {
case Some(a: Analysis) => a.compilations.allCompilations.size case Some(a: Analysis) => a.compilations.allCompilations.size
} }
} }
()
} }
val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.")

View File

@ -1,4 +1,4 @@
TaskKey[Unit]("outputEmpty") := { TaskKey[Unit]("outputEmpty") := Def.uncached {
val c = fileConverter.value val c = fileConverter.value
val dir = c.toPath((Compile / backendOutput).value).toFile() val dir = c.toPath((Compile / backendOutput).value).toFile()
def classes = dir.**("*.class").get() def classes = dir.**("*.class").get()

View File

@ -5,7 +5,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode // Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.") val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := { recordPreviousIterations := Def.uncached {
val log = streams.value.log val log = streams.value.log
CompileState.previousIterations = { CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -17,6 +17,7 @@ recordPreviousIterations := {
case Some(_) => -1 // should be unreachable but causes warnings case Some(_) => -1 // should be unreachable but causes warnings
} }
} }
()
} }
val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.") val checkIterations = inputKey[Unit]("Verifies the accumulated number of iterations of incremental compilation.")

View File

@ -3,7 +3,7 @@ import sbt.internal.inc.Analysis
import xsbti.compile.{PreviousResult, CompileAnalysis, MiniSetup} import xsbti.compile.{PreviousResult, CompileAnalysis, MiniSetup}
import xsbti.compile.analysis.{ Compilation => XCompilation } import xsbti.compile.analysis.{ Compilation => XCompilation }
(Compile / previousCompile) := { (Compile / previousCompile) := Def.uncached {
val previous = (Compile / previousCompile).value val previous = (Compile / previousCompile).value
if (!CompileState.isNew) { if (!CompileState.isNew) {
val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava) val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava)
@ -16,7 +16,7 @@ import xsbti.compile.analysis.{ Compilation => XCompilation }
* a) checks in which compilation given set of files was recompiled * a) checks in which compilation given set of files was recompiled
* b) checks overall number of compilations performed * b) checks overall number of compilations performed
*/ */
TaskKey[Unit]("checkCompilations") := { TaskKey[Unit]("checkCompilations") := Def.uncached {
val analysis = (Compile / compile).value match { case a: Analysis => a } val analysis = (Compile / compile).value match { case a: Analysis => a }
val srcDir = (Compile / scalaSource).value val srcDir = (Compile / scalaSource).value
def findFile(className: String): VirtualFileRef = { def findFile(className: String): VirtualFileRef = {

View File

@ -7,7 +7,7 @@ import xsbti.compile.analysis.{ Compilation => XCompilation }
logLevel := Level.Debug logLevel := Level.Debug
// Reset compile status because scripted tests are run in batch mode // Reset compile status because scripted tests are run in batch mode
(Compile / previousCompile) := { (Compile / previousCompile) := Def.uncached {
val previous = (Compile / previousCompile).value val previous = (Compile / previousCompile).value
if (!CompileState.isNew) { if (!CompileState.isNew) {
val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava) val res = PreviousResult.of(none[CompileAnalysis].asJava, none[MiniSetup].asJava)
@ -20,7 +20,7 @@ logLevel := Level.Debug
// some fraction (e.g. 50%) of files is scheduled to be recompiled // some fraction (e.g. 50%) of files is scheduled to be recompiled
// in this test we want precise information about recompiled files // in this test we want precise information about recompiled files
// which that heuristic would distort // which that heuristic would distort
incOptions := incOptions.value.withRecompileAllFraction(1.0) incOptions := Def.uncached(incOptions.value.withRecompileAllFraction(1.0))
Global / allowMachinePath := false Global / allowMachinePath := false
@ -28,7 +28,7 @@ Global / allowMachinePath := false
* a) checks in which compilation given set of files was recompiled * a) checks in which compilation given set of files was recompiled
* b) checks overall number of compilations performed * b) checks overall number of compilations performed
*/ */
TaskKey[Unit]("checkCompilations") := { TaskKey[Unit]("checkCompilations") := Def.uncached {
val log = streams.value.log val log = streams.value.log
val c = fileConverter.value val c = fileConverter.value
val vs = (Compile / sources).value.toVector map { x => val vs = (Compile / sources).value.toVector map { x =>
@ -66,4 +66,5 @@ TaskKey[Unit]("checkCompilations") := {
// Note that Y.scala is not recompiled because it depends just on X through member reference dependency // Note that Y.scala is not recompiled because it depends just on X through member reference dependency
recompiledFilesInIteration(2, Set("B.scala", "C.scala", "D.scala")) recompiledFilesInIteration(2, Set("B.scala", "C.scala", "D.scala"))
assert(allCompilations.size == 3) assert(allCompilations.size == 3)
()
} }

View File

@ -16,7 +16,7 @@ lazy val root = (project in file("."))
// testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-f", "result.txt", "-eNDXEHLO") // testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-f", "result.txt", "-eNDXEHLO")
Configurations.Test / testOptions ++= { Configurations.Test / testOptions ++= {
def args(path: String, args: String*): Seq[TestOption] = def args(path: String, args: String*): Seq[TestOption] =
if(file(path).exists) Tests.Argument(args : _*) :: Nil if file(path).exists then Tests.Argument(args*) :: Nil
else Nil else Nil
args("success1", "-n", "test2 test3") ++ args("success1", "-n", "test2 test3") ++
args("success2", "-n", "test2") ++ args("success2", "-n", "test2") ++

View File

@ -1,5 +1,7 @@
// https://github.com/sbt/sbt/issues/1673#issuecomment-537327439 // https://github.com/sbt/sbt/issues/1673#issuecomment-537327439
Global / localCacheDirectory := baseDirectory.value / "diskcache"
val Config_0 = config("config-0").extend(Compile) val Config_0 = config("config-0").extend(Compile)
val Config_1 = config("config-1").extend(Compile) val Config_1 = config("config-1").extend(Compile)
val Config_2 = config("config-2").extend(Compile) val Config_2 = config("config-2").extend(Compile)
@ -23,7 +25,7 @@ val t = taskKey[Unit]("")
val p1 = project val p1 = project
.configs(CustomConfigs: _*) .configs(CustomConfigs: _*)
.settings( .settings(
t := { t := Def.uncached {
(Config_0 / compile).value (Config_0 / compile).value
(Config_1 / compile).value (Config_1 / compile).value
(Config_2 / compile).value (Config_2 / compile).value
@ -40,6 +42,7 @@ val p1 = project
(Config_13 / compile).value (Config_13 / compile).value
(Config_14 / compile).value (Config_14 / compile).value
(Config_15 / compile).value (Config_15 / compile).value
()
} }
) )
.settings(CustomConfigs.flatMap(c => inConfig(c)(Defaults.testSettings))) .settings(CustomConfigs.flatMap(c => inConfig(c)(Defaults.testSettings)))

View File

@ -1,4 +1,4 @@
testGrouping := { testGrouping := Def.uncached {
val tests = (Test / definedTests).value val tests = (Test / definedTests).value
tests map { test => tests map { test =>
new Tests.Group( new Tests.Group(

View File

@ -8,7 +8,7 @@ Global / concurrentRestrictions := Seq(Tags.limit(TestATypeTag, 1), Tags.limit(T
libraryDependencies += specs % Test libraryDependencies += specs % Test
inConfig(Test)(Seq( inConfig(Test)(Seq(
testGrouping := { testGrouping := Def.uncached {
val home = javaHome.value val home = javaHome.value
val strategy = outputStrategy.value val strategy = outputStrategy.value
val baseDir = baseDirectory.value val baseDir = baseDirectory.value
@ -29,5 +29,8 @@ inConfig(Test)(Seq(
), Seq((if (test.name.contains("TestA")) TestATypeTag else TestBTypeTag) -> 1)) ), Seq((if (test.name.contains("TestA")) TestATypeTag else TestBTypeTag) -> 1))
} }
}, },
TaskKey[Unit]("test-failure") := testFull.failure.value TaskKey[Unit]("test-failure") := Def.uncached {
testFull.failure.value
()
}
)) ))

View File

@ -4,7 +4,7 @@ ThisBuild / scalaVersion := "2.12.20"
Global / concurrentRestrictions := Seq(Tags.limitAll(4)) Global / concurrentRestrictions := Seq(Tags.limitAll(4))
libraryDependencies += specs % Test libraryDependencies += specs % Test
inConfig(Test)(Seq( inConfig(Test)(Seq(
testGrouping := { testGrouping := Def.uncached {
val home = javaHome.value val home = javaHome.value
val strategy = outputStrategy.value val strategy = outputStrategy.value
val baseDir = baseDirectory.value val baseDir = baseDirectory.value
@ -23,5 +23,8 @@ inConfig(Test)(Seq(
) )
))} ))}
}, },
TaskKey[Unit]("test-failure") := testFull.failure.value TaskKey[Unit]("test-failure") := Def.uncached {
testFull.failure.value
()
}
)) ))

View File

@ -16,7 +16,7 @@ ThisBuild / organization := "org.example"
lazy val root = (project in file(".")) lazy val root = (project in file("."))
.settings( .settings(
Test / testGrouping := { Test / testGrouping := Def.uncached {
val tests = (Test / definedTests).value val tests = (Test / definedTests).value
assert(tests.size == 3) assert(tests.size == 3)
for (idx <- 0 until groups) yield for (idx <- 0 until groups) yield
@ -26,7 +26,7 @@ lazy val root = (project in file("."))
SubProcess(ForkOptions().withRunJVMOptions(Vector("-Dgroup.prefix=" + groupPrefix(idx)))) SubProcess(ForkOptions().withRunJVMOptions(Vector("-Dgroup.prefix=" + groupPrefix(idx))))
) )
}, },
check := { check := Def.uncached {
val files = val files =
for(i <- 0 until groups; j <- 1 to groupSize) yield for(i <- 0 until groups; j <- 1 to groupSize) yield
file(groupPrefix(i) + j) file(groupPrefix(i) + j)

View File

@ -48,7 +48,7 @@ a21 := 21
a22 := 22 a22 := 22
a23 := 23 a23 := 23
TaskKey[Unit]("check") := { TaskKey[Unit]("check") := Def.uncached {
val sum = ( val sum = (
a1.value ++ List( a1.value ++ List(
a2.value, a2.value,
@ -76,4 +76,5 @@ TaskKey[Unit]("check") := {
) )
).sum ).sum
assert(sum == 276, sum) assert(sum == 276, sum)
()
} }

View File

@ -11,11 +11,12 @@ lazy val root = (project in file("."))
libraryDependencies += { libraryDependencies += {
"org.scala-lang" % "scala-compiler" % scalaVersion.value % OtherScala.name "org.scala-lang" % "scala-compiler" % scalaVersion.value % OtherScala.name
}, },
OtherScala / managedClasspath := OtherScala / managedClasspath := Def.uncached {
Classpaths.managedJars(OtherScala, classpathTypes.value, update.value, fileConverter.value), Classpaths.managedJars(OtherScala, classpathTypes.value, update.value, fileConverter.value)
},
// Hack in the scala instance // Hack in the scala instance
scalaInstance := { scalaInstance := Def.uncached {
val converter = fileConverter.value val converter = fileConverter.value
val rawJars = (OtherScala / managedClasspath).value.map(c => converter.toPath(c.data).toFile) val rawJars = (OtherScala / managedClasspath).value.map(c => converter.toPath(c.data).toFile)
val scalaHome = (target.value / "scala-home") val scalaHome = (target.value / "scala-home")

View File

@ -5,4 +5,5 @@ TaskKey[Unit]("check") := {
val c = fileConverter.value val c = fileConverter.value
Using.jarFile(false)(c.toPath(p).toFile()): jar => Using.jarFile(false)(c.toPath(p).toFile()): jar =>
assert(jar.getJarEntry("ch/epfl/scala/Client.class") ne null) assert(jar.getJarEntry("ch/epfl/scala/Client.class") ne null)
()
} }

Some files were not shown because too many files have changed in this diff Show More