Merge pull request #8161 from eed3si9n/wip/cached-by-default

[2.x] Default to cached task
This commit is contained in:
eugene yokota 2025-06-21 03:39:32 -04:00 committed by GitHub
commit 1a06f29d0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
103 changed files with 781 additions and 503 deletions

View File

@ -94,17 +94,25 @@ trait Cont:
import conv.qctx
import qctx.reflect.*
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
.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]] =
import conv.qctx
import qctx.reflect.*
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
.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]] =
import conv.qctx
@ -112,7 +120,7 @@ trait Cont:
given qctx.type = qctx
Expr
.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.
@ -334,7 +342,11 @@ trait Cont:
cacheConfigExpr: Expr[BuildWideCacheConfiguration],
tags: List[CacheLevelTag],
)(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 aJsonFormat = summonJsonFormat[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 _ => 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:
case File
case Directory
@ -178,5 +200,15 @@ end ContextUtil
object ContextUtil:
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
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,
BuildWideCacheConfiguration,
cacheLevel,
DiskActionCacheStore
DiskActionCacheStore,
Uncached,
}
import Util.*
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]] =
${ 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]] =
${ 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 =
t.get(isDummyTask).getOrElse(false)
/**
* Marker function to make the task uncached.
*/
inline def uncached[A1](inline a: A1): A1 = Uncached(a)
end Def
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] =
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]] =
append1[A2](taskMacro(v))
@ -165,6 +168,9 @@ sealed abstract class TaskKey[A1]
): Setting[Task[A1]] =
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]] =
appendN(taskMacro[A2](vs))
@ -427,8 +433,8 @@ object Scoped:
sealed trait DefinableTask[A1] { self: TaskKey[A1] =>
/** Internal function for the task macro. */
inline def taskMacro[A](inline a: A): Initialize[Task[A]] =
${ TaskMacro.taskMacroImpl[A]('a, cached = false) }
inline def taskMacro[A2](inline a: A2): Initialize[Task[A2]] =
${ TaskMacro.taskMacroImpl[A2]('a, 'this) }
private[sbt] inline def :==(app: A1): Setting[Task[A1]] =
set(Def.valueStrict(std.TaskExtra.constant(app)))

View File

@ -15,10 +15,9 @@ import sbt.internal.util.appmacro.{
Cont,
// Instance,
// LinterDSL,
// MixedBuilder,
// MonadInstance
ContextUtil,
ContextUtil0,
}
// import Instance.Transform
import sbt.internal.util.{ LinePosition, NoPosition, SourcePosition }
import language.experimental.macros
@ -49,6 +48,42 @@ object TaskMacro:
// 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
qctx: Quotes
): Expr[Initialize[Task[A1]]] =

View File

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

View File

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

View File

@ -399,12 +399,12 @@ object Cross {
val scope = Scope(Select(project), Zero, Zero, Zero)
instance match {
case Some((home, inst)) =>
case Some((home, inst1)) =>
Seq(
scope / scalaVersion := version,
scope / crossScalaVersions := scalaVersions,
scope / scalaHome := Some(home),
scope / scalaInstance := inst,
scope / scalaInstance := Def.uncached(inst1),
)
case None =>
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
val injectStreams: ScopedKey[?] => Seq[Setting[?]] = scoped =>
if (scoped.key == streams.key) {
Seq(scoped.scope / streams := {
Seq(scoped.scope / streams := Def.uncached {
(streamsManager.map { mgr =>
val stream = mgr(scoped)
stream.open()

View File

@ -180,8 +180,12 @@ object Keys {
// Output paths
@cacheLevel(include = Array.empty)
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 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 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)
@ -209,6 +213,7 @@ object Keys {
val compileInputs = taskKey[Inputs]("Collects all inputs needed for compilation.").withRank(DTask)
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)
@cacheLevel(include = Array.empty)
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 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 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)
@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)
@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)
// Run Keys
@ -356,6 +365,8 @@ object Keys {
val testOptions = taskKey[Seq[TestOption]]("Options for running tests.").withRank(BPlusTask)
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)
@cacheLevel(include = Array.empty)
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 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 csrFallbackDependencies = taskKey[Seq[FallbackDependency]]("")
val csrLogger = taskKey[Option[CacheLogger]]("")
@cacheLevel(include = Array.empty)
val csrExtraCredentials = taskKey[Seq[lmcoursier.credentials.Credentials]]("")
val csrPublications = taskKey[Seq[(lmcoursier.definitions.Configuration, lmcoursier.definitions.Publication)]]("")
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 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)
@cacheLevel(include = Array.empty)
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 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 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)
@cacheLevel(include = Array.empty)
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)
@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)
@cacheLevel(include = Array.empty)
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 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 ivyValidate = settingKey[Boolean]("Enables/disables Ivy validation of module metadata.").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 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)
@ -641,6 +665,8 @@ object Keys {
val streams = taskKey[TaskStreams]("Provides streams for logging and persisting data.").withRank(DTask)
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.")
@cacheLevel(include = Array.empty)
val state = Def.stateKey
val streamsManager = Def.streamsManagerKey
// wrapper to work around SI-2915

View File

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

View File

@ -62,16 +62,18 @@ object ScriptedPlugin extends AutoPlugin {
override lazy val projectSettings: Seq[Setting[?]] = Seq(
ivyConfigurations ++= Seq(ScriptedConf, ScriptedLaunchConf),
scriptedSbt := (pluginCrossBuild / sbtVersion).value,
sbtLauncher := getJars(ScriptedLaunchConf)
.map(_.get().head)
.value,
sbtLauncher := Def.uncached(
getJars(ScriptedLaunchConf)
.map(_.get().head)
.value
),
sbtTestDirectory := sourceDirectory.value / "sbt-test",
libraryDependencies ++= Seq(
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % ScriptedConf,
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % ScriptedLaunchConf
),
scriptedClasspath := getJars(ScriptedConf).value,
scriptedTests := scriptedTestsTask.value,
scriptedClasspath := Def.uncached(getJars(ScriptedConf).value),
scriptedTests := Def.uncached(scriptedTestsTask.value),
scriptedParallelInstances := 1,
scriptedBatchExecution := {
val binVersion = CrossVersionUtil.binarySbtVersion(scriptedSbt.value)
@ -82,8 +84,8 @@ object ScriptedPlugin extends AutoPlugin {
case _ => false
}
},
scriptedRun := scriptedRunTask.value,
scriptedDependencies := {
scriptedRun := Def.uncached(scriptedRunTask.value),
scriptedDependencies := Def.uncached {
def use[A](@deprecated("unused", "") x: A*): Unit = () // avoid unused warnings
val analysis = (Test / Keys.compile).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[?] = {
csrPublications := CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs*).value
csrPublications := Def.uncached(
CoursierArtifactsTasks.coursierPublicationsTask(packageConfigs*).value
)
}
// 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.internal.util.{ Attributed, StringAttributeMap }
import sbt.internal.inc.{ FileAnalysisStore, ReflectUtilities }
import sbt.util.CacheImplicits.given
import xsbti.{ FileConverter, VirtualFileRef }
import xsbti.compile.CompileAnalysis

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,6 +20,7 @@ import sbt.internal.util.AttributeKey
import sbt.internal.util.complete.Parser
import sbt.nio.file.{ FileAttributes, FileTreeView, Glob, PathFilter }
import sbt.*
import sbt.util.cacheLevel
import scala.concurrent.duration.FiniteDuration
@ -39,6 +40,8 @@ object Keys {
settingKey[PathFilter]("A filter to apply to the input sources of a task.")
val fileInputExcludeFilter =
settingKey[PathFilter]("An exclusion filter to apply to the input sources of a task.")
@cacheLevel(include = Array.empty)
val inputFileStamper = settingKey[FileStamper](
"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 =
taskKey[Seq[(Path, FileAttributes)]]("Get all of the file inputs for a task")
.withRank(Invisible)
@cacheLevel(include = Array.empty)
private[sbt] val unmanagedFileStampCache = taskKey[FileStamp.Cache](
"Map of managed file stamps that may be cleared between task evaluation runs."
).withRank(Invisible)
@cacheLevel(include = Array.empty)
private[sbt] val managedFileStampCache = taskKey[FileStamp.Cache](
"Map of managed file stamps that may be cleared between task evaluation runs."
).withRank(Invisible)

View File

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

View File

@ -38,11 +38,11 @@ object DependencyTreeSettings {
// dependency tree
dependencyTreeIgnoreMissingUpdate / updateOptions := updateOptions.value
.withCachedResolution(false),
dependencyTreeIgnoreMissingUpdate / ivyConfiguration := {
dependencyTreeIgnoreMissingUpdate / ivyConfiguration := Def.uncached {
// inTask will make sure the new definition will pick up `updateOptions in dependencyTreeIgnoreMissingUpdate`
Project.inTask(dependencyTreeIgnoreMissingUpdate, Classpaths.mkIvyConfiguration).value
},
dependencyTreeIgnoreMissingUpdate / ivyModule := {
dependencyTreeIgnoreMissingUpdate / ivyModule := Def.uncached {
// 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
// implementations like `Classpaths.mkIvyConfiguration` or `Classpaths.updateTask`)
@ -52,7 +52,7 @@ object DependencyTreeSettings {
// don't fail on missing dependencies
dependencyTreeIgnoreMissingUpdate / updateConfiguration := updateConfiguration.value
.withMissingOk(true),
dependencyTreeIgnoreMissingUpdate := {
dependencyTreeIgnoreMissingUpdate := Def.uncached {
// inTask will make sure the new definition will pick up `ivyModule/updateConfiguration in ignoreMissingUpdate`
Project.inTask(dependencyTreeIgnoreMissingUpdate, Classpaths.updateTask).value
},
@ -67,7 +67,7 @@ object DependencyTreeSettings {
dependencyTreeCrossProjectId := CrossVersion(scalaVersion.value, scalaBinaryVersion.value)(
projectID.value
),
dependencyTreeModuleGraph0 := {
dependencyTreeModuleGraph0 := Def.uncached {
val sv = scalaVersion.value
val g = dependencyTreeIgnoreMissingUpdate.value
.configuration(configuration.value)
@ -107,12 +107,14 @@ object DependencyTreeSettings {
val config = configuration.value
target.value / s"dependencies-${config.toString}.dot"
},
dependencyDot / asString := rendering.DOT.dotGraph(
dependencyTreeModuleGraph0.value,
dependencyDotHeader.value,
dependencyDotNodeLabel.value,
rendering.DOT.HTMLLabelRendering.AngleBrackets,
dependencyDotNodeColors.value
dependencyDot / asString := Def.uncached(
rendering.DOT.dotGraph(
dependencyTreeModuleGraph0.value,
dependencyDotHeader.value,
dependencyDotNodeLabel.value,
rendering.DOT.HTMLLabelRendering.AngleBrackets,
dependencyDotNodeColors.value
)
),
dependencyDot := writeToFile(dependencyDot / asString, dependencyDotFile).value,
dependencyDotHeader :=

View File

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

View File

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

View File

@ -6,4 +6,7 @@ val updateReports = Def.taskDyn { updateClassifiers.all(ScopeFilter(configuratio
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
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.")
expectErrorNotCrash := {
expectErrorNotCrash := Def.uncached {
val fail = (Compile / compileIncremental).failure.value
Incomplete.allExceptions(fail).headOption match
case Some(x: xsbti.CompileFailed) => ()

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
-> 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

View File

@ -1,4 +1,4 @@
import sbt._
import sbt.*
object FooPlugin extends AutoPlugin {
override def trigger = noTrigger
@ -9,6 +9,6 @@ object FooPlugin extends AutoPlugin {
import autoImport._
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) },
posAction := { IO.write(output.value, s"pos\n", append = true) },
TaskKey[Unit]("checkTrue") := checkLines("true"),
TaskKey[Unit]("checkFalse") := checkLines("false"),
TaskKey[Unit]("checkNeg") := checkLines("neg"),
TaskKey[Unit]("checkZero") := checkLines("zero"),
TaskKey[Unit]("checkTrue") := checkLines("true").value,
TaskKey[Unit]("checkFalse") := checkLines("false").value,
TaskKey[Unit]("checkNeg") := checkLines("neg").value,
TaskKey[Unit]("checkZero") := checkLines("zero").value,
// https://github.com/sbt/sbt/issues/5625
javacOptions ++= (
@ -49,6 +49,6 @@ lazy val root = (project in file("."))
def checkLines(content: String) = Def.task {
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(
crossScalaVersions := Seq(scala212, scala213),
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.0",
check := {
check := Def.uncached {
// This tests that +check will respect bar's crossScalaVersions and not switch
val x = (LocalProject("bar") / scalaVersion).value
assert(x == scala212, s"$x == $scala212")
(Compile / compile).value
Def.unit((Compile / compile).value)
},
(Test / testOnly) := {
// 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")
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
val x = (LocalProject("bar") / scalaVersion).value
assert(x == scalaVersion.value, s"$x == ${scalaVersion.value}")
(Compile / compile).value
Def.unit((Compile / compile).value)
},
)
lazy val bar = project
.settings(
crossScalaVersions := Seq(scala212),
check := (Compile / compile).value,
compile2 := (Compile / compile).value,
check := Def.uncached {
Def.unit((Compile / compile).value)
},
compile2 := Def.uncached(Def.unit((Compile / compile).value)),
)
lazy val baz = project
.settings(
crossScalaVersions := Seq(scala213),
check := {
check := Def.uncached {
// This tests that +baz/check will respect bar's crossScalaVersions and not switch
val x = (LocalProject("bar") / scalaVersion).value
assert(x == scala212, s"$x == $scala212")
(Compile / compile).value
Def.unit((Compile / compile).value)
},
)
lazy val client = project
.settings(
crossScalaVersions := Seq(scala212, scala213),
check := (Compile / compile).value,
compile2 := (Compile / compile).value,
check := Def.uncached(Def.unit((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
.dependsOn(c)
.settings(
externalResolvers := Seq(aResolver.value, bResolver.value),
externalResolvers := Def.uncached(Seq(aResolver.value, bResolver.value)),
addDep("a"),
addDep("b"),
checkApiMappings := {
checkApiMappings := Def.uncached {
val actual = (Compile / doc / apiMappings).value
println("Actual API Mappings: " + actual.mkString("\n\t", "\n\t", ""))
val expected = expectedMappings.value
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._
val cacheTask = taskKey[Int]("task")
cacheTask := 1
cacheTask := Def.uncached(1)
val checkTask = inputKey[Unit]("validate that the correct value is set by cacheTask")
checkTask := {
val expected = Def.spaceDelimited("").parsed.head.toInt
assert(cacheTask.previous.getOrElse(0) == expected)
}
}

View File

@ -1,3 +1,5 @@
Global / localCacheDirectory := baseDirectory.value / "diskcache"
import sjsonnew.BasicJsonProtocol._
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:
// 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 = {
import complete.DefaultParsers._
@ -24,9 +26,9 @@ def parser = {
}
checkNext := {
val (expectedA, expectedB) = parser.parsed
val actualA = a.value
val actualB = b.value
assert(actualA == expectedA, s"Expected 'a' to be $expectedA, got $actualA")
assert(actualB == expectedB, s"Expected 'b' to be $expectedB, got $actualB")
val (expectedA, expectedB) = parser.parsed
val actualA = a.value
val actualB = b.value
assert(actualA == expectedA, s"Expected 'a' to be $expectedA, got $actualA")
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 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
// verify that This is properly resolved to Global and not the defining key's scope
val xg = x.previous getOrElse 0 // 3
@ -22,7 +22,7 @@ subA / Compile / x := {
}
inConfig(Compile)(Seq(
subB / y := {
subB / y := Def.uncached {
// verify that the referenced key gets delegated
val xty = (Test / y / x).previous getOrElse 0 // 13
// verify that inConfig gets applied
@ -37,7 +37,7 @@ def parser = {
(Space ~> IntBasic) ~ (Space ~> IntBasic)
}
checkScopes := {
checkScopes := Def.uncached {
val (expectedX, expectedY) = parser.parsed
val actualX = (subA/ Compile / x).value
val actualY = (subB / Test / y).value

View File

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

View File

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

View File

@ -4,7 +4,7 @@ version := {
version.value
}
TaskKey[Unit]("evil-clear-logger") := {
TaskKey[Unit]("evil-clear-logger") := Def.uncached {
val logger = sLog.value
val cls = logger.getClass
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")
}
TaskKey[Unit]("evil-clear-logger") := {
TaskKey[Unit]("evil-clear-logger") := Def.uncached {
val logger = sLog.value
val cls = logger.getClass
val field = cls.getDeclaredField("ref")
@ -16,6 +16,7 @@ TaskKey[Unit]("evil-clear-logger") := {
val ref = field.get(logger).asInstanceOf[java.lang.ref.WeakReference[_]]
// MUHAHAHHAHAHAHAHHAHA, I am de evil GC, I clear things.
ref.clear()
()
}
commands ++= Seq(

View File

@ -6,23 +6,45 @@ val taskF = taskKey[File]("")
scalaVersion := "3.3.1"
name := "task-map"
taskA := touch(target.value / "a")
taskB := touch(target.value / "b")
taskA := {
val c = fileConverter.value
touch(target.value / "a")
Def.declareOutput(c.toVirtualFile((target.value / "a").toPath()))
target.value / "a"
}
taskE := touch(target.value / "e")
taskF := touch(target.value / "f")
taskB := {
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
// means "a" will be triggered by "b"
// 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
// means "e" will be run before running "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
def touch(f: File): File = { IO.touch(f); f }

View File

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

View File

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

View File

@ -3,7 +3,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := {
recordPreviousIterations := Def.uncached {
val log = streams.value.log
CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -14,6 +14,7 @@ recordPreviousIterations := {
case Some(a: Analysis) => a.compilations.allCompilations.size
}
}
()
}
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"
pure1 := (Def.cachedTask {
pure1 := {
val output = StringVirtualFile1("target/out/a.txt", "foo")
Def.declareOutput(output)
()
}).value
}
map1 := (Def.cachedTask {
map1 := {
pure1.value
val output1 = StringVirtualFile1("target/out/b1.txt", "foo")
val output2 = StringVirtualFile1("target/out/b2.txt", "foo")
Def.declareOutput(output1)
Def.declareOutput(output2)
"something"
}).value
}
mapN1 := (Def.cachedTask {
mapN1 := {
pure1.value
map1.value
val output = StringVirtualFile1("target/out/c.txt", "foo")
Def.declareOutput(output)
()
}).value
}
checkMapN1 := {
checkMapN1 := Def.uncached {
val s = streams.value
val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s
case s => sys.error(s"empty event log")
assert(prev.hitCount == 2, s"prev.hitCount = ${prev.hitCount}")
case s => sys.error(s"empty event log")
assert(prev.hitCount == 2, s"prev.hitCount = ${prev.hitCount} (expected 2)")
}

View File

@ -1,16 +1,18 @@
import sbt.internal.util.CacheEventSummary
import complete.DefaultParsers.*
lazy val checkMiss = taskKey[Unit]("")
lazy val checkMiss = inputKey[Unit]("")
Global / localCacheDirectory := baseDirectory.value / "diskcache"
scalaVersion := "3.7.1"
checkMiss := {
val expected: Int = (Space ~> NatBasic).parsed
val s = streams.value
val config = Def.cacheConfiguration.value
val prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s
case _ => sys.error(s"empty event log")
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
> run 1
> checkMiss
> checkMiss 1
$ copy-file changes/A2.scala A.scala
> run 2
> checkMiss
> checkMiss 1

View File

@ -7,12 +7,14 @@ Global / localCacheDirectory := baseDirectory.value / "diskcache"
scalaVersion := "2.13.16"
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 prev = config.cacheEventLog.previous match
case s: CacheEventSummary.Data => s
case s => sys.error(s"empty event log")
assert(prev.hitCount == 1, s"prev.hitCount = ${prev.hitCount}")
case s => sys.error(s"empty event log")
s.log.info(s"prev.missCount = ${prev.missCount}")
assert(prev.missCount == 0, s"prev.missCount = ${prev.missCount}")
}
lazy val foo = (project in file("foo"))

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
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 classDir = (Compile / classDirectory).value
val base = baseDirectory.value

View File

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

View File

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

View File

@ -3,9 +3,10 @@ import xsbti.compile.TastyFiles
ThisBuild / scalaVersion := "3.3.1"
TaskKey[Unit]("check") := {
TaskKey[Unit]("check") := Def.uncached {
assert((Compile / auxiliaryClassFiles).value == Seq(TastyFiles.instance))
assert((Test / auxiliaryClassFiles).value == Seq(TastyFiles.instance))
()
}
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 ignore = (Compile / compile).failure.value
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 sourcePath = first.position.sourcePath.get
assert(sourcePath == expected, s"$sourcePath == $expected was false")
()
}
TaskKey[Unit]("checkScalaFailures") := {
TaskKey[Unit]("checkScalaFailures") := Def.uncached {
val reporter = savedReporter.value
val ignore = (Compile / compile).failure.value
val ps = reporter.problems
@ -22,4 +23,5 @@ TaskKey[Unit]("checkScalaFailures") := {
val expected = "${BASE}/src/main/scala/bad.scala"
val sourcePath = first.position.sourcePath.get
assert(sourcePath == expected, s"$sourcePath == $expected was false")
()
}

View File

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

View File

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

View File

@ -22,7 +22,7 @@ lazy val realCommonsIoClient = project.
libraryDependencies := Seq(
"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.

View File

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

View File

@ -6,7 +6,7 @@ ThisBuild / csrCacheDirectory := (ThisBuild / baseDirectory).value / "coursier-c
def commonSettings: Seq[Def.Setting[_]] =
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")),
scalaCompilerBridgeResolvers += userLocalFileResolver(appConfiguration.value),
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(".")).
settings(
check := {
check := Def.uncached {
(a / update).value
(b / update).value
val acp = (a / Compile / externalDependencyClasspath).value.sortBy {_.data.name}

View File

@ -1,7 +1,7 @@
import scala.xml._
lazy val root = (project in file(".")) settings (
readPom := {
readPom := Def.uncached {
val vf = makePom.value
val converter = fileConverter.value
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")
}
lazy val checkExtra = readPom map { pomXML =>
lazy val checkExtra = readPom.map: pomXML =>
checkProject(pomXML)
val extra = pomXML \ extraTagName
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
for {
dep <- pomXml \ "dependencies" \ "dependency"
@ -52,19 +51,18 @@ lazy val checkVersionPlusMapping = (readPom) map { (pomXml) =>
if (dep \ "version").text != "[1.3,1.4)"
} 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"
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"
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
checkProject(pomXML)
val ivyRepositories = fullResolvers.value

View File

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

View File

@ -9,7 +9,7 @@ lazy val common =
name := "config",
organization := "com.typesafe",
version := "0.4.9-SNAPSHOT",
publishTo := Some(localRemote),
publishTo := Def.uncached(Some(localRemote)),
autoScalaLibrary := false,
crossPaths := false
)
@ -24,7 +24,7 @@ lazy val analyze =
resolvers += localRemote,
resolvers += Resolver.mavenLocal,
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]("")
check := {
check := Def.uncached {
val bridge = scalaCompilerBridgeBinaryJar.value
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")
makeHome := {
makeHome := Def.uncached {
val lib = baseDirectory.value / "home" / "lib"
for(jar <- scalaInstance.value.allJars)
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")
checkUpdate := {
checkUpdate := Def.uncached {
val report = update.value
val lib = (scalaHome.value.get / "lib").getCanonicalFile
for(f <- report.allFiles)

View File

@ -33,6 +33,6 @@ lazy val dependent = project
.settings(
// Ignore the inter-project resolver, so we force to look remotely.
resolvers += sharedResolver,
fullResolvers := fullResolvers.value.filterNot(_==projectResolver.value),
fullResolvers := Def.uncached(fullResolvers.value.filterNot(_==projectResolver.value)),
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")
}
dependencyResolution := {
dependencyResolution := Def.uncached {
throw new RuntimeException("updateSbtClassifiers should use updateSbtClassifiers / dependencyResolution")
}
@ -12,7 +12,7 @@ lazy val root = (project in file("."))
scalaOrganization := "doesnt.exist",
name := "myProjectName",
TaskKey[Unit]("checkModuleIdsInUpdateSbtClassifiers") := {
TaskKey[Unit]("checkModuleIdsInUpdateSbtClassifiers") := Def.uncached {
val updateReport = updateSbtClassifiers.value
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 =
// 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(
"Unexpected module ids in updateSbtClassifiers",

View File

@ -1,12 +1,14 @@
TaskKey[Unit]("checkIsDefaultCache") := {
TaskKey[Unit]("checkIsDefaultCache") := Def.uncached {
val csrCacheDir = csrCacheDirectory.value
assert(csrCacheDir == sbt.coursierint.LMCoursier.defaultCacheLocation, csrCacheDir.toString)
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 ip = ivyPaths.value
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"
logFile := baseDirectory.value / "log"
csrLogger := {
csrLogger := Def.uncached {
var logStream: java.io.PrintStream = null
def log(msg: String): Unit = {
println(msg)

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
lazy val runTest = taskKey[Unit]("Run the test applications.")
def runTestTask(pre: Def.Initialize[Task[Unit]]) =
runTest := {
runTest := Def.uncached {
val _ = pre.value
val r = (Compile / run / runner).value
val cp = (Compile / fullClasspath).value
@ -9,11 +9,12 @@ def runTestTask(pre: Def.Initialize[Task[Unit]]) =
val args = baseDirectory.value.getAbsolutePath :: Nil
given FileConverter = fileConverter.value
r.run(main, cp.files, args, streams.value.log).get
()
}
lazy val b = project.settings(
runTestTask( waitForCStart ),
runTest := {
runTest := Def.uncached {
val _ = runTest.value
val cFinished = (c / baseDirectory).value / "finished"
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
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := {
recordPreviousIterations := Def.uncached {
val log = streams.value.log
CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -14,6 +14,7 @@ recordPreviousIterations := {
case Some(a: Analysis) => a.compilations.allCompilations.size
}
}
()
}
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
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := {
recordPreviousIterations := Def.uncached {
val log = streams.value.log
CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -14,6 +14,7 @@ recordPreviousIterations := {
case Some(a: Analysis) => a.compilations.allCompilations.size
}
}
()
}
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 dir = c.toPath((Compile / backendOutput).value).toFile()
def classes = dir.**("*.class").get()

View File

@ -5,7 +5,7 @@ import complete.DefaultParsers._
// Reset compiler iterations, necessary because tests run in batch mode
val recordPreviousIterations = taskKey[Unit]("Record previous iterations.")
recordPreviousIterations := {
recordPreviousIterations := Def.uncached {
val log = streams.value.log
CompileState.previousIterations = {
val previousAnalysis = (Compile / previousCompile).value.analysis.asScala
@ -17,6 +17,7 @@ recordPreviousIterations := {
case Some(_) => -1 // should be unreachable but causes warnings
}
}
()
}
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.analysis.{ Compilation => XCompilation }
(Compile / previousCompile) := {
(Compile / previousCompile) := Def.uncached {
val previous = (Compile / previousCompile).value
if (!CompileState.isNew) {
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
* 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 srcDir = (Compile / scalaSource).value
def findFile(className: String): VirtualFileRef = {

View File

@ -7,7 +7,7 @@ import xsbti.compile.analysis.{ Compilation => XCompilation }
logLevel := Level.Debug
// Reset compile status because scripted tests are run in batch mode
(Compile / previousCompile) := {
(Compile / previousCompile) := Def.uncached {
val previous = (Compile / previousCompile).value
if (!CompileState.isNew) {
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
// in this test we want precise information about recompiled files
// which that heuristic would distort
incOptions := incOptions.value.withRecompileAllFraction(1.0)
incOptions := Def.uncached(incOptions.value.withRecompileAllFraction(1.0))
Global / allowMachinePath := false
@ -28,7 +28,7 @@ Global / allowMachinePath := false
* a) checks in which compilation given set of files was recompiled
* b) checks overall number of compilations performed
*/
TaskKey[Unit]("checkCompilations") := {
TaskKey[Unit]("checkCompilations") := Def.uncached {
val log = streams.value.log
val c = fileConverter.value
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
recompiledFilesInIteration(2, Set("B.scala", "C.scala", "D.scala"))
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")
Configurations.Test / testOptions ++= {
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
args("success1", "-n", "test2 test3") ++
args("success2", "-n", "test2") ++

View File

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

View File

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

View File

@ -8,7 +8,7 @@ Global / concurrentRestrictions := Seq(Tags.limit(TestATypeTag, 1), Tags.limit(T
libraryDependencies += specs % Test
inConfig(Test)(Seq(
testGrouping := {
testGrouping := Def.uncached {
val home = javaHome.value
val strategy = outputStrategy.value
val baseDir = baseDirectory.value
@ -29,5 +29,8 @@ inConfig(Test)(Seq(
), 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))
libraryDependencies += specs % Test
inConfig(Test)(Seq(
testGrouping := {
testGrouping := Def.uncached {
val home = javaHome.value
val strategy = outputStrategy.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("."))
.settings(
Test / testGrouping := {
Test / testGrouping := Def.uncached {
val tests = (Test / definedTests).value
assert(tests.size == 3)
for (idx <- 0 until groups) yield
@ -26,7 +26,7 @@ lazy val root = (project in file("."))
SubProcess(ForkOptions().withRunJVMOptions(Vector("-Dgroup.prefix=" + groupPrefix(idx))))
)
},
check := {
check := Def.uncached {
val files =
for(i <- 0 until groups; j <- 1 to groupSize) yield
file(groupPrefix(i) + j)

View File

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

View File

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

View File

@ -5,4 +5,5 @@ TaskKey[Unit]("check") := {
val c = fileConverter.value
Using.jarFile(false)(c.toPath(p).toFile()): jar =>
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