mirror of https://github.com/sbt/sbt.git
Use ClassTag instead of Manifest
This commit is contained in:
parent
ecd59bd3e1
commit
fbc98ed72e
|
|
@ -16,7 +16,7 @@ import sbt.ConcurrentRestrictions.Tag
|
||||||
import sbt.Def.{ Initialize, ScopedKey, Setting, setting }
|
import sbt.Def.{ Initialize, ScopedKey, Setting, setting }
|
||||||
import std.TaskMacro
|
import std.TaskMacro
|
||||||
import std.TaskExtra.{ task => mktask, _ }
|
import std.TaskExtra.{ task => mktask, _ }
|
||||||
import scala.reflect.ManifestFactory
|
import scala.reflect.{ ClassTag, ManifestFactory }
|
||||||
|
|
||||||
/** An abstraction on top of Settings for build configuration and task definition. */
|
/** An abstraction on top of Settings for build configuration and task definition. */
|
||||||
sealed trait Scoped extends Equals:
|
sealed trait Scoped extends Equals:
|
||||||
|
|
@ -261,6 +261,11 @@ object Scoped:
|
||||||
implicit def inputScopedToKey[T](s: InputKey[T]): ScopedKey[InputTask[T]] =
|
implicit def inputScopedToKey[T](s: InputKey[T]): ScopedKey[InputTask[T]] =
|
||||||
ScopedKey(s.scope, s.key)
|
ScopedKey(s.scope, s.key)
|
||||||
|
|
||||||
|
private[sbt] def coerceTag[A1: ClassTag]: Manifest[A1] =
|
||||||
|
summon[ClassTag[A1]] match
|
||||||
|
case mf: Manifest[A1] => mf
|
||||||
|
case tag => ManifestFactory.classType[A1](tag.runtimeClass)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mixin trait for adding convenience vocabulary associated with specifying the [[Scope]] of a setting.
|
* Mixin trait for adding convenience vocabulary associated with specifying the [[Scope]] of a setting.
|
||||||
* Allows specification of the Scope or part of the [[Scope]] of a setting being referenced.
|
* Allows specification of the Scope or part of the [[Scope]] of a setting being referenced.
|
||||||
|
|
@ -593,6 +598,12 @@ object Scoped:
|
||||||
// format: off
|
// format: off
|
||||||
|
|
||||||
type ST[X] = Taskable[X]
|
type ST[X] = Taskable[X]
|
||||||
|
final class RichTaskable1[A1](t1: ST[A1]) extends RichTaskables[[F[_]] =>> F[A1]](t1)(using AList.single[A1]):
|
||||||
|
type Fun[M[_], Ret] = M[A1] => Ret
|
||||||
|
def identityMap = mapN(identity)
|
||||||
|
protected def convert[M[_], R](f: M[A1] => R) = f
|
||||||
|
end RichTaskable1
|
||||||
|
|
||||||
final class RichTaskable2[A, B](t2: (ST[A], ST[B])) extends RichTaskables[AList.Tuple2K[A, B]](t2)(using AList.tuple2[A, B]) {
|
final class RichTaskable2[A, B](t2: (ST[A], ST[B])) extends RichTaskables[AList.Tuple2K[A, B]](t2)(using AList.tuple2[A, B]) {
|
||||||
type Fun[M[_], Ret] = (M[A], M[B]) => Ret
|
type Fun[M[_], Ret] = (M[A], M[B]) => Ret
|
||||||
def identityMap = mapN(mkTuple2)
|
def identityMap = mapN(mkTuple2)
|
||||||
|
|
@ -736,6 +747,7 @@ trait TupleSyntax:
|
||||||
|
|
||||||
// this is the least painful arrangement I came up with
|
// this is the least painful arrangement I came up with
|
||||||
type ST[T] = Taskable[T]
|
type ST[T] = Taskable[T]
|
||||||
|
implicit def taskableToTable1[A1](t1: ST[A1]): RichTaskable1[A1] = new RichTaskable1(t1)
|
||||||
implicit def t2ToTable2[A, B](t2: (ST[A], ST[B])): RichTaskable2[A, B] = new RichTaskable2(t2)
|
implicit def t2ToTable2[A, B](t2: (ST[A], ST[B])): RichTaskable2[A, B] = new RichTaskable2(t2)
|
||||||
implicit def t3ToTable3[A, B, C](t3: (ST[A], ST[B], ST[C])): RichTaskable3[A, B, C] = new RichTaskable3(t3)
|
implicit def t3ToTable3[A, B, C](t3: (ST[A], ST[B], ST[C])): RichTaskable3[A, B, C] = new RichTaskable3(t3)
|
||||||
implicit def t4ToTable4[A, B, C, D](t4: (ST[A], ST[B], ST[C], ST[D])): RichTaskable4[A, B, C, D] = new RichTaskable4(t4)
|
implicit def t4ToTable4[A, B, C, D](t4: (ST[A], ST[B], ST[C], ST[D])): RichTaskable4[A, B, C, D] = new RichTaskable4(t4)
|
||||||
|
|
@ -763,35 +775,36 @@ end TupleSyntax
|
||||||
|
|
||||||
object TupleSyntax extends TupleSyntax
|
object TupleSyntax extends TupleSyntax
|
||||||
|
|
||||||
import Scoped.extendScoped
|
import Scoped.{ coerceTag, extendScoped }
|
||||||
|
|
||||||
/** Constructs InputKeys, which are associated with input tasks to define a setting. */
|
/** Constructs InputKeys, which are associated with input tasks to define a setting. */
|
||||||
object InputKey:
|
object InputKey:
|
||||||
def apply[A1: Manifest](
|
|
||||||
|
def apply[A1: ClassTag](
|
||||||
label: String,
|
label: String,
|
||||||
description: String = "",
|
description: String = "",
|
||||||
rank: Int = KeyRanks.DefaultInputRank
|
rank: Int = KeyRanks.DefaultInputRank
|
||||||
): InputKey[A1] =
|
): InputKey[A1] =
|
||||||
given mf: Manifest[InputTask[A1]] =
|
given mf: ClassTag[InputTask[A1]] =
|
||||||
ManifestFactory.classType[InputTask[A1]](classOf[InputTask[A1]], manifest[A1])
|
ManifestFactory.classType[InputTask[A1]](classOf[InputTask[A1]], coerceTag[A1])
|
||||||
apply(AttributeKey[InputTask[A1]](label, description, rank))
|
apply(AttributeKey[InputTask[A1]](label, description, rank))
|
||||||
|
|
||||||
def apply[A1: Manifest](
|
def apply[A1: ClassTag](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
extend1: Scoped,
|
extend1: Scoped,
|
||||||
extendN: Scoped*
|
extendN: Scoped*
|
||||||
): InputKey[A1] = apply(label, description, KeyRanks.DefaultInputRank, extend1, extendN: _*)
|
): InputKey[A1] = apply(label, description, KeyRanks.DefaultInputRank, extend1, extendN: _*)
|
||||||
|
|
||||||
def apply[A1: Manifest](
|
def apply[A1: ClassTag](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
rank: Int,
|
rank: Int,
|
||||||
extend1: Scoped,
|
extend1: Scoped,
|
||||||
extendN: Scoped*
|
extendN: Scoped*
|
||||||
): InputKey[A1] =
|
): InputKey[A1] =
|
||||||
given mf: Manifest[InputTask[A1]] =
|
given mf: ClassTag[InputTask[A1]] =
|
||||||
ManifestFactory.classType[InputTask[A1]](classOf[InputTask[A1]], manifest[A1])
|
ManifestFactory.classType[InputTask[A1]](classOf[InputTask[A1]], coerceTag[A1])
|
||||||
apply(AttributeKey[InputTask[A1]](label, description, extendScoped(extend1, extendN), rank))
|
apply(AttributeKey[InputTask[A1]](label, description, extendScoped(extend1, extendN), rank))
|
||||||
|
|
||||||
def apply[A1](akey: AttributeKey[InputTask[A1]]): InputKey[A1] =
|
def apply[A1](akey: AttributeKey[InputTask[A1]]): InputKey[A1] =
|
||||||
|
|
@ -801,49 +814,63 @@ end InputKey
|
||||||
|
|
||||||
/** Constructs TaskKeys, which are associated with tasks to define a setting. */
|
/** Constructs TaskKeys, which are associated with tasks to define a setting. */
|
||||||
object TaskKey:
|
object TaskKey:
|
||||||
def apply[A1: Manifest](
|
def apply[A1: ClassTag](label: String): TaskKey[A1] =
|
||||||
|
apply[A1](
|
||||||
|
label = label,
|
||||||
|
description = "",
|
||||||
|
rank = Int.MaxValue,
|
||||||
|
)
|
||||||
|
|
||||||
|
def apply[A1: ClassTag](label: String, description: String): TaskKey[A1] =
|
||||||
|
apply[A1](
|
||||||
|
label = label,
|
||||||
|
description = description,
|
||||||
|
rank = Int.MaxValue,
|
||||||
|
)
|
||||||
|
|
||||||
|
def apply[A1: ClassTag](
|
||||||
label: String,
|
label: String,
|
||||||
description: String = "",
|
description: String,
|
||||||
rank: Int = KeyRanks.DefaultTaskRank
|
rank: Int,
|
||||||
): TaskKey[A1] =
|
): TaskKey[A1] =
|
||||||
given mf: Manifest[Task[A1]] =
|
given mf: ClassTag[Task[A1]] =
|
||||||
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], manifest[A1])
|
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1])
|
||||||
apply(AttributeKey[Task[A1]](label, description, rank))
|
apply(AttributeKey[Task[A1]](label, description, rank))
|
||||||
|
|
||||||
def apply[A1: Manifest](
|
def apply[A1: ClassTag](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
extend1: Scoped,
|
extend1: Scoped,
|
||||||
extendN: Scoped*
|
extendN: Scoped*
|
||||||
): TaskKey[A1] =
|
): TaskKey[A1] =
|
||||||
given mf: Manifest[Task[A1]] =
|
given mf: ClassTag[Task[A1]] =
|
||||||
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], manifest[A1])
|
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1])
|
||||||
apply(AttributeKey[Task[A1]](label, description, extendScoped(extend1, extendN)))
|
apply(AttributeKey[Task[A1]](label, description, extendScoped(extend1, extendN)))
|
||||||
|
|
||||||
def apply[A1: Manifest](
|
def apply[A1: ClassTag](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
rank: Int,
|
rank: Int,
|
||||||
extend1: Scoped,
|
extend1: Scoped,
|
||||||
extendN: Scoped*
|
extendN: Scoped*
|
||||||
): TaskKey[A1] =
|
): TaskKey[A1] =
|
||||||
given mf: Manifest[Task[A1]] =
|
given mf: ClassTag[Task[A1]] =
|
||||||
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], manifest[A1])
|
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1])
|
||||||
apply(AttributeKey[Task[A1]](label, description, extendScoped(extend1, extendN), rank))
|
apply(AttributeKey[Task[A1]](label, description, extendScoped(extend1, extendN), rank))
|
||||||
|
|
||||||
def apply[A1](akey: AttributeKey[Task[A1]]): TaskKey[A1] =
|
def apply[A1](akey: AttributeKey[Task[A1]]): TaskKey[A1] =
|
||||||
Scoped.scopedTask(Scope.ThisScope, akey)
|
Scoped.scopedTask(Scope.ThisScope, akey)
|
||||||
|
|
||||||
def local[A1: Manifest]: TaskKey[A1] =
|
def local[A1: ClassTag]: TaskKey[A1] =
|
||||||
given mf: Manifest[Task[A1]] =
|
given mf: ClassTag[Task[A1]] =
|
||||||
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], manifest[A1])
|
ManifestFactory.classType[Task[A1]](classOf[Task[A1]], coerceTag[A1])
|
||||||
apply[A1](AttributeKey.local[Task[A1]])
|
apply[A1](AttributeKey.local[Task[A1]])
|
||||||
|
|
||||||
end TaskKey
|
end TaskKey
|
||||||
|
|
||||||
/** Constructs SettingKeys, which are associated with a value to define a basic setting. */
|
/** Constructs SettingKeys, which are associated with a value to define a basic setting. */
|
||||||
object SettingKey:
|
object SettingKey:
|
||||||
def apply[A1: Manifest: OptJsonWriter](
|
def apply[A1: ClassTag: OptJsonWriter](
|
||||||
label: String,
|
label: String,
|
||||||
): SettingKey[A1] =
|
): SettingKey[A1] =
|
||||||
apply[A1](
|
apply[A1](
|
||||||
|
|
@ -852,7 +879,7 @@ object SettingKey:
|
||||||
rank = KeyRanks.DefaultSettingRank
|
rank = KeyRanks.DefaultSettingRank
|
||||||
)
|
)
|
||||||
|
|
||||||
def apply[A1: Manifest: OptJsonWriter](
|
def apply[A1: ClassTag: OptJsonWriter](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
): SettingKey[A1] =
|
): SettingKey[A1] =
|
||||||
|
|
@ -862,14 +889,14 @@ object SettingKey:
|
||||||
rank = KeyRanks.DefaultSettingRank,
|
rank = KeyRanks.DefaultSettingRank,
|
||||||
)
|
)
|
||||||
|
|
||||||
def apply[A1: Manifest: OptJsonWriter](
|
def apply[A1: ClassTag: OptJsonWriter](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
rank: Int
|
rank: Int
|
||||||
): SettingKey[A1] =
|
): SettingKey[A1] =
|
||||||
apply(AttributeKey[A1](label, description, rank))
|
apply(AttributeKey[A1](label, description, rank))
|
||||||
|
|
||||||
def apply[A1: Manifest: OptJsonWriter](
|
def apply[A1: ClassTag: OptJsonWriter](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
extend1: Scoped,
|
extend1: Scoped,
|
||||||
|
|
@ -877,7 +904,7 @@ object SettingKey:
|
||||||
): SettingKey[A1] =
|
): SettingKey[A1] =
|
||||||
apply(AttributeKey[A1](label, description, extendScoped(extend1, extendN)))
|
apply(AttributeKey[A1](label, description, extendScoped(extend1, extendN)))
|
||||||
|
|
||||||
def apply[A1: Manifest: OptJsonWriter](
|
def apply[A1: ClassTag: OptJsonWriter](
|
||||||
label: String,
|
label: String,
|
||||||
description: String,
|
description: String,
|
||||||
rank: Int,
|
rank: Int,
|
||||||
|
|
@ -889,7 +916,8 @@ object SettingKey:
|
||||||
def apply[A1](akey: AttributeKey[A1]): SettingKey[A1] =
|
def apply[A1](akey: AttributeKey[A1]): SettingKey[A1] =
|
||||||
Scoped.scopedSetting(Scope.ThisScope, akey)
|
Scoped.scopedSetting(Scope.ThisScope, akey)
|
||||||
|
|
||||||
def local[A1: Manifest: OptJsonWriter]: SettingKey[A1] = apply[A1](AttributeKey.local[A1])
|
def local[A1: ClassTag: OptJsonWriter]: SettingKey[A1] =
|
||||||
|
apply[A1](AttributeKey.local[A1])
|
||||||
|
|
||||||
end SettingKey
|
end SettingKey
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ package std
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
import scala.quoted.*
|
import scala.quoted.*
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
import sbt.util.OptJsonWriter
|
import sbt.util.OptJsonWriter
|
||||||
|
|
||||||
|
|
@ -42,21 +43,21 @@ private[sbt] object KeyMacro:
|
||||||
}
|
}
|
||||||
|
|
||||||
private def keyImpl[A1: Type, A2: Type](methodName: String)(
|
private def keyImpl[A1: Type, A2: Type](methodName: String)(
|
||||||
f: (String, Expr[Manifest[A1]]) => Expr[A2]
|
f: (String, Expr[ClassTag[A1]]) => Expr[A2]
|
||||||
)(using qctx: Quotes): Expr[A2] =
|
)(using qctx: Quotes): Expr[A2] =
|
||||||
val tpe = summon[Type[A1]]
|
val tpe = summon[Type[A1]]
|
||||||
f(
|
f(
|
||||||
definingValName(errorMsg(methodName)),
|
definingValName(errorMsg(methodName)),
|
||||||
Expr.summon[Manifest[A1]].getOrElse(sys.error("Manifest[A] not found for $tpe"))
|
Expr.summon[ClassTag[A1]].getOrElse(sys.error("ClassTag[A] not found for $tpe"))
|
||||||
)
|
)
|
||||||
|
|
||||||
private def keyImpl2[A1: Type, A2: Type](methodName: String)(
|
private def keyImpl2[A1: Type, A2: Type](methodName: String)(
|
||||||
f: (String, Expr[Manifest[A1]], Expr[OptJsonWriter[A1]]) => Expr[A2]
|
f: (String, Expr[ClassTag[A1]], Expr[OptJsonWriter[A1]]) => Expr[A2]
|
||||||
)(using qctx: Quotes): Expr[A2] =
|
)(using qctx: Quotes): Expr[A2] =
|
||||||
val tpe = summon[Type[A1]]
|
val tpe = summon[Type[A1]]
|
||||||
f(
|
f(
|
||||||
definingValName(errorMsg(methodName)),
|
definingValName(errorMsg(methodName)),
|
||||||
Expr.summon[Manifest[A1]].getOrElse(sys.error("Manifest[A] not found for $tpe")),
|
Expr.summon[ClassTag[A1]].getOrElse(sys.error("ClassTag[A] not found for $tpe")),
|
||||||
Expr.summon[OptJsonWriter[A1]].getOrElse(sys.error("OptJsonWriter[A] not found for $tpe")),
|
Expr.summon[OptJsonWriter[A1]].getOrElse(sys.error("OptJsonWriter[A] not found for $tpe")),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import xsbti.compile.CompilerCache
|
||||||
import scala.annotation.{ nowarn, tailrec }
|
import scala.annotation.{ nowarn, tailrec }
|
||||||
import scala.concurrent.ExecutionContext
|
import scala.concurrent.ExecutionContext
|
||||||
import scala.concurrent.duration.Duration
|
import scala.concurrent.duration.Duration
|
||||||
|
import scala.reflect.ClassTag
|
||||||
import scala.util.control.NonFatal
|
import scala.util.control.NonFatal
|
||||||
|
|
||||||
/** This class is the entry point for sbt. */
|
/** This class is the entry point for sbt. */
|
||||||
|
|
@ -517,11 +518,14 @@ object BuiltinCommands {
|
||||||
def sortByRank(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] = keys.sortBy(_.rank)
|
def sortByRank(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] = keys.sortBy(_.rank)
|
||||||
def withDescription(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] =
|
def withDescription(keys: Seq[AttributeKey[_]]): Seq[AttributeKey[_]] =
|
||||||
keys.filter(_.description.isDefined)
|
keys.filter(_.description.isDefined)
|
||||||
|
|
||||||
def isTask(
|
def isTask(
|
||||||
mf: Manifest[_]
|
mf: ClassTag[_]
|
||||||
)(implicit taskMF: Manifest[Task[_]], inputMF: Manifest[InputTask[_]]): Boolean =
|
)(using taskMF: ClassTag[Task[_]], inputMF: ClassTag[InputTask[_]]): Boolean =
|
||||||
mf.runtimeClass == taskMF.runtimeClass || mf.runtimeClass == inputMF.runtimeClass
|
mf.runtimeClass == taskMF.runtimeClass || mf.runtimeClass == inputMF.runtimeClass
|
||||||
|
|
||||||
def topNRanked(n: Int) = (keys: Seq[AttributeKey[_]]) => sortByRank(keys).take(n)
|
def topNRanked(n: Int) = (keys: Seq[AttributeKey[_]]) => sortByRank(keys).take(n)
|
||||||
|
|
||||||
def highPass(rankCutoff: Int) =
|
def highPass(rankCutoff: Int) =
|
||||||
(keys: Seq[AttributeKey[_]]) => sortByRank(keys).takeWhile(_.rank <= rankCutoff)
|
(keys: Seq[AttributeKey[_]]) => sortByRank(keys).takeWhile(_.rank <= rankCutoff)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,10 @@ final case class ScopedKeyData[A](scoped: ScopedKey[A], value: Any) {
|
||||||
"Setting: %s = %s" format (key.manifest.toString, value.toString)
|
"Setting: %s = %s" format (key.manifest.toString, value.toString)
|
||||||
)
|
)
|
||||||
def fold[T](targ: OptManifest[_] => T, itarg: OptManifest[_] => T, s: => T): T =
|
def fold[T](targ: OptManifest[_] => T, itarg: OptManifest[_] => T, s: => T): T =
|
||||||
key.manifest.runtimeClass match {
|
key.manifest.runtimeClass match
|
||||||
case TaskClass => targ(key.manifest.typeArguments.head)
|
case TaskClass => targ(key.manifest.typeArguments.head)
|
||||||
case InputTaskClass => itarg(key.manifest.typeArguments.head)
|
case InputTaskClass => itarg(key.manifest.typeArguments.head)
|
||||||
case _ => s
|
case _ => s
|
||||||
}
|
|
||||||
def fmtMf(s: String): OptManifest[_] => String = s format _
|
def fmtMf(s: String): OptManifest[_] => String = s format _
|
||||||
|
|
||||||
private val TaskClass = classOf[Task[_]]
|
private val TaskClass = classOf[Task[_]]
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import Types.idFun
|
||||||
import complete._
|
import complete._
|
||||||
import DefaultParsers._
|
import DefaultParsers._
|
||||||
import scala.annotation.nowarn
|
import scala.annotation.nowarn
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The resulting `session` and verbose and quiet summaries of the result of a set operation.
|
* The resulting `session` and verbose and quiet summaries of the result of a set operation.
|
||||||
|
|
@ -352,32 +353,33 @@ private[sbt] object SettingCompletions {
|
||||||
def configScalaID(c: String): String = Util.quoteIfKeyword(c.capitalize)
|
def configScalaID(c: String): String = Util.quoteIfKeyword(c.capitalize)
|
||||||
|
|
||||||
/** Applies a function on the underlying manifest for T for `key` depending if it is for a `Setting[T]`, `Task[T]`, or `InputTask[T]`. */
|
/** Applies a function on the underlying manifest for T for `key` depending if it is for a `Setting[T]`, `Task[T]`, or `InputTask[T]`. */
|
||||||
|
@nowarn
|
||||||
def keyType[S](key: AttributeKey[_])(
|
def keyType[S](key: AttributeKey[_])(
|
||||||
onSetting: Manifest[_] => S,
|
onSetting: ClassTag[_] => S,
|
||||||
onTask: Manifest[_] => S,
|
onTask: ClassTag[_] => S,
|
||||||
onInput: Manifest[_] => S
|
onInput: ClassTag[_] => S
|
||||||
)(implicit tm: Manifest[Task[_]], im: Manifest[InputTask[_]]): S = {
|
)(using tm: ClassTag[Task[_]], im: ClassTag[InputTask[_]]): S =
|
||||||
def argTpe = key.manifest.typeArguments.head
|
def argTpe = key.manifest.typeArguments.head match
|
||||||
|
case m: Manifest[_] => m
|
||||||
|
case _ => sys.error(s"Manifest not found for ${key} typeArgument")
|
||||||
val TaskClass = tm.runtimeClass
|
val TaskClass = tm.runtimeClass
|
||||||
val InputTaskClass = im.runtimeClass
|
val InputTaskClass = im.runtimeClass
|
||||||
key.manifest.runtimeClass match {
|
key.manifest.runtimeClass match
|
||||||
case TaskClass => onTask(argTpe)
|
case TaskClass => onTask(argTpe)
|
||||||
case InputTaskClass => onInput(argTpe)
|
case InputTaskClass => onInput(argTpe)
|
||||||
case _ => onSetting(key.manifest)
|
case _ => onSetting(key.manifest)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** For a Task[T], InputTask[T], or Setting[T], this returns the manifest for T. */
|
/** For a Task[T], InputTask[T], or Setting[T], this returns the manifest for T. */
|
||||||
def keyUnderlyingType(key: AttributeKey[_]): Manifest[_] = keyType(key)(idFun, idFun, idFun)
|
def keyUnderlyingType(key: AttributeKey[_]): ClassTag[_] =
|
||||||
|
keyType(key)(idFun, idFun, idFun)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of the underlying type T for a `key` representing a `Setting[T]`, `Task[T]`, or `InputTask[T]`.
|
* Returns a string representation of the underlying type T for a `key` representing a `Setting[T]`, `Task[T]`, or `InputTask[T]`.
|
||||||
* This string representation is currently a cleaned up toString of the underlying Manifest.
|
* This string representation is currently a cleaned up toString of the underlying ClassTag.
|
||||||
*/
|
*/
|
||||||
def keyTypeString[T](key: AttributeKey[_]): String = {
|
def keyTypeString[T](key: AttributeKey[_]): String =
|
||||||
val mfToString = (mf: Manifest[_]) => complete.TypeString.cleanup(mf.toString)
|
val tagToString = (tag: ClassTag[_]) => complete.TypeString.cleanup(tag.toString)
|
||||||
keyType(key)(mfToString, mfToString, mfToString)
|
keyType(key)(tagToString, tagToString, tagToString)
|
||||||
}
|
|
||||||
|
|
||||||
/** True if the `key` represents a setting or task that may be appended using an assignment method such as `+=`. */
|
/** True if the `key` represents a setting or task that may be appended using an assignment method such as `+=`. */
|
||||||
def appendable(key: AttributeKey[_]): Boolean = {
|
def appendable(key: AttributeKey[_]): Boolean = {
|
||||||
|
|
|
||||||
|
|
@ -93,15 +93,15 @@ private[sbt] object Settings {
|
||||||
addTaskDefinition(Def.setting[Task[Seq[Path]]](key, init, setting.pos)) ::
|
addTaskDefinition(Def.setting[Task[Seq[Path]]](key, init, setting.pos)) ::
|
||||||
outputsAndStamps(taskKey)
|
outputsAndStamps(taskKey)
|
||||||
}
|
}
|
||||||
ak.manifest.typeArguments match {
|
ak.manifest.typeArguments match
|
||||||
case t :: Nil if seqClass.isAssignableFrom(t.runtimeClass) =>
|
case (t: Manifest[_]) :: Nil if seqClass.isAssignableFrom(t.runtimeClass) =>
|
||||||
t.typeArguments match {
|
t.typeArguments match {
|
||||||
case p :: Nil if pathClass.isAssignableFrom(p.runtimeClass) => mkSetting[Seq[Path]]
|
case p :: Nil if pathClass.isAssignableFrom(p.runtimeClass) => mkSetting[Seq[Path]]
|
||||||
case _ => default
|
case _ => default
|
||||||
}
|
}
|
||||||
case t :: Nil if pathClass.isAssignableFrom(t.runtimeClass) => mkSetting[Path]
|
case (t: Manifest[_]) :: Nil if pathClass.isAssignableFrom(t.runtimeClass) =>
|
||||||
case _ => default
|
mkSetting[Path]
|
||||||
}
|
case _ => default
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ object Dependencies {
|
||||||
// val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % "2.0.10"
|
// val lmCoursierShaded = "io.get-coursier" %% "lm-coursier-shaded" % "2.0.10"
|
||||||
val lmCoursierShaded = "org.scala-sbt" %% "librarymanagement-coursier" % "2.0.0-alpha2"
|
val lmCoursierShaded = "org.scala-sbt" %% "librarymanagement-coursier" % "2.0.0-alpha2"
|
||||||
|
|
||||||
lazy val sjsonNewVersion = "0.10.0"
|
lazy val sjsonNewVersion = "0.11.0"
|
||||||
def sjsonNew(n: String) = Def.setting(
|
def sjsonNew(n: String) = Def.setting(
|
||||||
"com.eed3si9n" %% n % sjsonNewVersion
|
"com.eed3si9n" %% n % sjsonNewVersion
|
||||||
) // contrabandSjsonNewVersion.value
|
) // contrabandSjsonNewVersion.value
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
import sbt._, Keys._
|
import sbt._, Keys._
|
||||||
import Def.Initialize
|
import Def.Initialize
|
||||||
|
import sbt.TupleSyntax.*
|
||||||
|
|
||||||
object Marker extends AutoPlugin {
|
object Marker extends AutoPlugin:
|
||||||
override def trigger = allRequirements
|
override def trigger = allRequirements
|
||||||
override def requires = sbt.plugins.JvmPlugin
|
override def requires = sbt.plugins.JvmPlugin
|
||||||
object autoImport {
|
object autoImport {
|
||||||
final lazy val Mark = TaskKey[Unit]("mark")
|
final lazy val Mark = TaskKey[Unit]("mark")
|
||||||
final def mark: Initialize[Task[Unit]] = mark(baseDirectory)
|
final def mark: Initialize[Task[Unit]] = mark(baseDirectory)
|
||||||
final def mark(project: Reference): Initialize[Task[Unit]] = mark(baseDirectory in project)
|
final def mark(project: Reference): Initialize[Task[Unit]] = mark(project / baseDirectory)
|
||||||
final def mark(baseKey: SettingKey[File]): Initialize[Task[Unit]] = baseKey map { base =>
|
final def mark(baseKey: SettingKey[File]): Initialize[Task[Unit]] = baseKey.toTaskable mapN {
|
||||||
val toMark = base / "ran"
|
base =>
|
||||||
if(toMark.exists)
|
val toMark = base / "ran"
|
||||||
sys.error("Already ran (" + toMark + " exists)")
|
if (toMark.exists)
|
||||||
else
|
sys.error("Already ran (" + toMark + " exists)")
|
||||||
IO touch toMark
|
else
|
||||||
|
IO touch toMark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
end Marker
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ $ exists ran
|
||||||
$ delete ran
|
$ delete ran
|
||||||
|
|
||||||
# single project, aggregate = true on Mark
|
# single project, aggregate = true on Mark
|
||||||
> set aggregate in Mark := true
|
> set Mark / aggregate := true
|
||||||
> mark
|
> mark
|
||||||
$ exists ran
|
$ exists ran
|
||||||
$ delete ran
|
$ delete ran
|
||||||
|
|
||||||
# single project, aggregate = false on Mark
|
# single project, aggregate = false on Mark
|
||||||
> set aggregate in Mark := false
|
> set Mark / aggregate := false
|
||||||
> mark
|
> mark
|
||||||
$ exists ran
|
$ exists ran
|
||||||
$ delete ran
|
$ delete ran
|
||||||
|
|
@ -58,8 +58,8 @@ $ touch aggregate
|
||||||
> reload
|
> reload
|
||||||
|
|
||||||
# add tasks to each subproject
|
# add tasks to each subproject
|
||||||
> set Mark in sub := mark(sub).value
|
> set sub / Mark := mark(sub).value
|
||||||
> set Mark in sub2 := mark(sub2).value
|
> set sub2 / Mark := mark(sub2).value
|
||||||
|
|
||||||
# check that aggregation works when root project has no task
|
# check that aggregation works when root project has no task
|
||||||
> mark
|
> mark
|
||||||
|
|
@ -77,15 +77,15 @@ $ delete sub/ran sub/sub/ran
|
||||||
> set Mark := mark.value
|
> set Mark := mark.value
|
||||||
|
|
||||||
# disable aggregation for sub/mark so that sub2/mark doesn't run
|
# disable aggregation for sub/mark so that sub2/mark doesn't run
|
||||||
> set aggregate in (sub,Mark) := false
|
> set sub / Mark / aggregate := false
|
||||||
> mark
|
> mark
|
||||||
$ exists ran sub/ran
|
$ exists ran sub/ran
|
||||||
$ absent sub/sub/ran
|
$ absent sub/sub/ran
|
||||||
$ delete ran sub/ran
|
$ delete ran sub/ran
|
||||||
|
|
||||||
# the aggregation setting in a leaf shouldn't affect whether it can be run directly
|
# the aggregation setting in a leaf shouldn't affect whether it can be run directly
|
||||||
> set aggregate in (sub2, Mark) := false
|
> set sub2 / Mark / aggregate := false
|
||||||
> sub2/mark
|
> sub2/mark
|
||||||
$ exists sub/sub/ran
|
$ exists sub/sub/ran
|
||||||
$ absent ran sub/ran
|
$ absent ran sub/ran
|
||||||
$ delete sub/sub/ran
|
$ delete sub/sub/ran
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ import sbt.util.OptJsonWriter
|
||||||
sealed trait AttributeKey[A]:
|
sealed trait AttributeKey[A]:
|
||||||
|
|
||||||
/** The runtime evidence for `A`. */
|
/** The runtime evidence for `A`. */
|
||||||
def manifest: Manifest[A]
|
def manifest: ClassTag[A]
|
||||||
// def classTag: ClassTag[A]
|
// def classTag: ClassTag[A]
|
||||||
|
|
||||||
/** The label is the identifier for the key and is camelCase by convention. */
|
/** The label is the identifier for the key and is camelCase by convention. */
|
||||||
|
|
@ -52,7 +52,7 @@ sealed trait AttributeKey[A]:
|
||||||
|
|
||||||
end AttributeKey
|
end AttributeKey
|
||||||
|
|
||||||
private[sbt] abstract class SharedAttributeKey[T] extends AttributeKey[T] {
|
private[sbt] abstract class SharedAttributeKey[A] extends AttributeKey[A]:
|
||||||
override final def toString = label
|
override final def toString = label
|
||||||
override final def hashCode = label.hashCode
|
override final def hashCode = label.hashCode
|
||||||
override final def equals(o: Any) =
|
override final def equals(o: Any) =
|
||||||
|
|
@ -61,74 +61,72 @@ private[sbt] abstract class SharedAttributeKey[T] extends AttributeKey[T] {
|
||||||
case _ => false
|
case _ => false
|
||||||
})
|
})
|
||||||
final def isLocal: Boolean = false
|
final def isLocal: Boolean = false
|
||||||
}
|
end SharedAttributeKey
|
||||||
|
|
||||||
object AttributeKey {
|
object AttributeKey {
|
||||||
def apply[T: Manifest: OptJsonWriter](name: String): AttributeKey[T] =
|
def apply[A: ClassTag: OptJsonWriter](name: String): AttributeKey[A] =
|
||||||
make(name, None, Nil, Int.MaxValue)
|
make(name, None, Nil, Int.MaxValue)
|
||||||
|
|
||||||
def apply[T: Manifest: OptJsonWriter](name: String, rank: Int): AttributeKey[T] =
|
def apply[A: ClassTag: OptJsonWriter](name: String, rank: Int): AttributeKey[A] =
|
||||||
make(name, None, Nil, rank)
|
make(name, None, Nil, rank)
|
||||||
|
|
||||||
def apply[T: Manifest: OptJsonWriter](name: String, description: String): AttributeKey[T] =
|
def apply[A: ClassTag: OptJsonWriter](name: String, description: String): AttributeKey[A] =
|
||||||
apply(name, description, Nil)
|
apply(name, description, Nil)
|
||||||
|
|
||||||
def apply[T: Manifest: OptJsonWriter](
|
def apply[A: ClassTag: OptJsonWriter](
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
rank: Int
|
rank: Int
|
||||||
): AttributeKey[T] =
|
): AttributeKey[A] =
|
||||||
apply(name, description, Nil, rank)
|
apply(name, description, Nil, rank)
|
||||||
|
|
||||||
def apply[T: Manifest: OptJsonWriter](
|
def apply[A: ClassTag: OptJsonWriter](
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
extend: Seq[AttributeKey[_]]
|
extend: Seq[AttributeKey[_]]
|
||||||
): AttributeKey[T] =
|
): AttributeKey[A] =
|
||||||
apply(name, description, extend, Int.MaxValue)
|
apply(name, description, extend, Int.MaxValue)
|
||||||
|
|
||||||
def apply[T: Manifest: OptJsonWriter](
|
def apply[A: ClassTag: OptJsonWriter](
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
extend: Seq[AttributeKey[_]],
|
extend: Seq[AttributeKey[_]],
|
||||||
rank: Int
|
rank: Int
|
||||||
): AttributeKey[T] =
|
): AttributeKey[A] =
|
||||||
make(name, Some(description), extend, rank)
|
make(name, Some(description), extend, rank)
|
||||||
|
|
||||||
private[sbt] def copyWithRank[T](a: AttributeKey[T], rank: Int): AttributeKey[T] =
|
private[sbt] def copyWithRank[A](a: AttributeKey[A], rank: Int): AttributeKey[A] =
|
||||||
make(a.label, a.description, a.extend, rank)(a.manifest, a.optJsonWriter)
|
make(a.label, a.description, a.extend, rank)(using a.manifest, a.optJsonWriter)
|
||||||
|
|
||||||
private[this] def make[T](
|
private[this] def make[A](
|
||||||
name: String,
|
name: String,
|
||||||
description0: Option[String],
|
description0: Option[String],
|
||||||
extend0: Seq[AttributeKey[_]],
|
extend0: Seq[AttributeKey[_]],
|
||||||
rank0: Int
|
rank0: Int
|
||||||
)(implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] =
|
)(using mf: ClassTag[A], ojw: OptJsonWriter[A]): AttributeKey[A] =
|
||||||
new SharedAttributeKey[T] {
|
new SharedAttributeKey[A]:
|
||||||
require(
|
require(
|
||||||
name.headOption.exists(_.isLower),
|
name.headOption.exists(_.isLower),
|
||||||
s"A named attribute key must start with a lowercase letter: $name"
|
s"A named attribute key must start with a lowercase letter: $name"
|
||||||
)
|
)
|
||||||
|
|
||||||
def manifest = mf
|
override def manifest: ClassTag[A] = mf
|
||||||
val label = Util.hyphenToCamel(name)
|
override val label: String = Util.hyphenToCamel(name)
|
||||||
def description = description0
|
override def description: Option[String] = description0
|
||||||
def extend = extend0
|
override def extend: Seq[AttributeKey[_]] = extend0
|
||||||
def rank = rank0
|
override def rank: Int = rank0
|
||||||
def optJsonWriter = ojw
|
override def optJsonWriter: OptJsonWriter[A] = ojw
|
||||||
}
|
|
||||||
|
|
||||||
private[sbt] def local[T](implicit mf: Manifest[T], ojw: OptJsonWriter[T]): AttributeKey[T] =
|
private[sbt] def local[A](using ct: ClassTag[A], ojw: OptJsonWriter[A]): AttributeKey[A] =
|
||||||
new AttributeKey[T] {
|
new AttributeKey[A]:
|
||||||
def manifest = mf
|
override def manifest: ClassTag[A] = ct
|
||||||
def label = LocalLabel
|
override def label: String = LocalLabel
|
||||||
def description = None
|
override def description: Option[String] = None
|
||||||
def extend = Nil
|
override def extend: Seq[AttributeKey[_]] = Nil
|
||||||
override def toString = label
|
override def toString = label
|
||||||
def isLocal: Boolean = true
|
override def isLocal: Boolean = true
|
||||||
def rank = Int.MaxValue
|
override def rank: Int = Int.MaxValue
|
||||||
val optJsonWriter = ojw
|
override val optJsonWriter: OptJsonWriter[A] = ojw
|
||||||
}
|
|
||||||
|
|
||||||
private[sbt] final val LocalLabel = "$" + "local"
|
private[sbt] final val LocalLabel = "$" + "local"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue