mirror of https://github.com/sbt/sbt.git
Add Initialize[Task[T]].taskValue: Task[T] to allow selecting the Task for use by *Generators. Fixes #866.
This commit is contained in:
parent
1d9b44d5d7
commit
fcb35f3b8f
|
|
@ -63,7 +63,7 @@ object Def extends Init[Scope] with TaskMacroExtra
|
||||||
import language.experimental.macros
|
import language.experimental.macros
|
||||||
import std.TaskMacro.{inputTaskMacroImpl, inputTaskDynMacroImpl, taskDynMacroImpl, taskMacroImpl}
|
import std.TaskMacro.{inputTaskMacroImpl, inputTaskDynMacroImpl, taskDynMacroImpl, taskMacroImpl}
|
||||||
import std.SettingMacro.{settingDynMacroImpl,settingMacroImpl}
|
import std.SettingMacro.{settingDynMacroImpl,settingMacroImpl}
|
||||||
import std.{InputEvaluated, MacroValue, ParserInput}
|
import std.{InputEvaluated, MacroValue, MacroTaskValue, ParserInput}
|
||||||
|
|
||||||
def task[T](t: T): Def.Initialize[Task[T]] = macro taskMacroImpl[T]
|
def task[T](t: T): Def.Initialize[Task[T]] = macro taskMacroImpl[T]
|
||||||
def taskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[Task[T]] = macro taskDynMacroImpl[T]
|
def taskDyn[T](t: Def.Initialize[Task[T]]): Def.Initialize[Task[T]] = macro taskDynMacroImpl[T]
|
||||||
|
|
@ -78,6 +78,7 @@ object Def extends Init[Scope] with TaskMacroExtra
|
||||||
implicit def macroValueI[T](in: Initialize[T]): MacroValue[T] = ???
|
implicit def macroValueI[T](in: Initialize[T]): MacroValue[T] = ???
|
||||||
implicit def macroValueIT[T](in: Initialize[Task[T]]): MacroValue[T] = ???
|
implicit def macroValueIT[T](in: Initialize[Task[T]]): MacroValue[T] = ???
|
||||||
implicit def macroValueIInT[T](in: Initialize[InputTask[T]]): InputEvaluated[T] = ???
|
implicit def macroValueIInT[T](in: Initialize[InputTask[T]]): InputEvaluated[T] = ???
|
||||||
|
implicit def taskMacroValueIT[T](in: Initialize[Task[T]]): MacroTaskValue[T] = ???
|
||||||
|
|
||||||
// The following conversions enable the types Parser[T], Initialize[Parser[T]], and Initialize[State => Parser[T]] to
|
// The following conversions enable the types Parser[T], Initialize[Parser[T]], and Initialize[State => Parser[T]] to
|
||||||
// be used in the inputTask macro as an input with an ultimate result of type T
|
// be used in the inputTask macro as an input with an ultimate result of type T
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ object Scoped
|
||||||
def set(app: Initialize[Task[S]], source: SourcePosition): Setting[Task[S]] = Def.setting(scopedKey, app, source)
|
def set(app: Initialize[Task[S]], source: SourcePosition): Setting[Task[S]] = Def.setting(scopedKey, app, source)
|
||||||
def transform(f: S => S, source: SourcePosition): Setting[Task[S]] = set( scopedKey(_ map f), source)
|
def transform(f: S => S, source: SourcePosition): Setting[Task[S]] = set( scopedKey(_ map f), source)
|
||||||
|
|
||||||
|
@deprecated("No longer needed with new task syntax and SettingKey inheriting from Initialize.", "0.13.2")
|
||||||
def task: SettingKey[Task[S]] = scopedSetting(scope, key)
|
def task: SettingKey[Task[S]] = scopedSetting(scope, key)
|
||||||
def get(settings: Settings[Scope]): Option[Task[S]] = settings.get(scope, key)
|
def get(settings: Settings[Scope]): Option[Task[S]] = settings.get(scope, key)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,12 +85,23 @@ object InputWrapper
|
||||||
InputWrapper.wrapInputTask[T](c)(ts,pos)
|
InputWrapper.wrapInputTask[T](c)(ts,pos)
|
||||||
else if(tpe <:< c.weakTypeOf[Initialize[InputTask[T]]])
|
else if(tpe <:< c.weakTypeOf[Initialize[InputTask[T]]])
|
||||||
InputWrapper.wrapInitInputTask[T](c)(ts,pos)
|
InputWrapper.wrapInitInputTask[T](c)(ts,pos)
|
||||||
|
|
||||||
else
|
else
|
||||||
c.abort(pos, s"Internal sbt error. Unexpected type $tpe")
|
c.abort(pos, s"Internal sbt error. Unexpected type ${tpe.widen}")
|
||||||
|
}
|
||||||
|
def taskValueMacroImpl[T: c.WeakTypeTag](c: Context): c.Expr[Task[T]] =
|
||||||
|
ContextUtil.selectMacroImpl[Task[T]](c) { (ts, pos) =>
|
||||||
|
val tpe = ts.tree.tpe
|
||||||
|
if(tpe <:< c.weakTypeOf[Initialize[Task[T]]])
|
||||||
|
InputWrapper.wrapInit[Task[T]](c)(ts,pos)
|
||||||
|
else
|
||||||
|
c.abort(pos, s"Internal sbt error. Unexpected type ${tpe.widen}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed abstract class MacroTaskValue[T] {
|
||||||
|
@compileTimeOnly("`taskValue` can only be used within a setting macro, such as :=, +=, ++=, or Def.setting.")
|
||||||
|
def taskValue: Task[T] = macro InputWrapper.taskValueMacroImpl[T]
|
||||||
|
}
|
||||||
sealed abstract class MacroValue[T] {
|
sealed abstract class MacroValue[T] {
|
||||||
@compileTimeOnly("`value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.")
|
@compileTimeOnly("`value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.")
|
||||||
def value: T = macro InputWrapper.valueMacroImpl[T]
|
def value: T = macro InputWrapper.valueMacroImpl[T]
|
||||||
|
|
|
||||||
|
|
@ -9,31 +9,31 @@ sbt provides standard hooks for adding source or resource generation tasks.
|
||||||
:title: Generate sources
|
:title: Generate sources
|
||||||
:type: setting
|
:type: setting
|
||||||
|
|
||||||
sourceGenerators in Compile <+= <your Task[Seq[File]] here>
|
sourceGenerators in Compile += <task of type Seq[File]>.taskValue
|
||||||
|
|
||||||
A source generation task should generate sources in a subdirectory of :key:`sourceManaged` and return a sequence of files generated. The key to add the task to is called :key:`sourceGenerators`. It should be scoped according to whether the generated files are main (`Compile`) or test (`Test`) sources. This basic structure looks like:
|
A source generation task should generate sources in a subdirectory of :key:`sourceManaged` and return a sequence of files generated. The key to add the task to is called :key:`sourceGenerators`. Because we want to add the unexecuted task, we use `taskValue` instead of the usual `value`. :key:`sourceGenerators` should be scoped according to whether the generated files are main (`Compile`) or test (`Test`) sources. This basic structure looks like:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
sourceGenerators in Compile <+= <your Task[Seq[File]] here>
|
sourceGenerators in Compile += <task of type Seq[File]>.taskValue
|
||||||
|
|
||||||
For example, assuming a method `def makeSomeSources(base: File): Seq[File]`,
|
For example, assuming a method `def makeSomeSources(base: File): Seq[File]`,
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
sourceGenerators in Compile <+=
|
sourceGenerators in Compile +=
|
||||||
Def.task { makeSomeSources( (sourceManaged in Compile).value / "demo" ) }
|
Def.task( makeSomeSources( (sourceManaged in Compile).value / "demo" ) ).taskValue
|
||||||
|
|
||||||
|
|
||||||
As a specific example, the following generates a hello world source file:
|
As a specific example, the following generates a hello world source file:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
sourceGenerators in Compile <+= Def.task {
|
sourceGenerators in Compile += Def.task {
|
||||||
val file = (sourceManaged in Compile).value / "demo" / "Test.scala"
|
val file = (sourceManaged in Compile).value / "demo" / "Test.scala"
|
||||||
IO.write(file, """object Test extends App { println("Hi") }""")
|
IO.write(file, """object Test extends App { println("Hi") }""")
|
||||||
Seq(file)
|
Seq(file)
|
||||||
}
|
}.taskValue
|
||||||
|
|
||||||
Executing 'run' will print "Hi". Change `Compile` to `Test` to make it a test source. For efficiency, you would only want to generate sources when necessary and not every run.
|
Executing 'run' will print "Hi". Change `Compile` to `Test` to make it a test source. For efficiency, you would only want to generate sources when necessary and not every run.
|
||||||
|
|
||||||
|
|
@ -44,32 +44,32 @@ By default, generated sources are not included in the packaged source artifact.
|
||||||
:title: Generate resources
|
:title: Generate resources
|
||||||
:type: setting
|
:type: setting
|
||||||
|
|
||||||
resourceGenerators in Compile <+= <your Task[Seq[File]] here>
|
resourceGenerators in Compile += <task of type Seq[File]>
|
||||||
|
|
||||||
A resource generation task should generate resources in a subdirectory of :key:`resourceManaged` and return a sequence of files generated. The key to add the task to is called :key:`resourceGenerators`. It should be scoped according to whether the generated files are main (`Compile`) or test (`Test`) resources. This basic structure looks like:
|
A resource generation task should generate resources in a subdirectory of :key:`resourceManaged` and return a sequence of files generated. The key to add the task to is called :key:`resourceGenerators`. Because we want to add the unexecuted task, we use `taskValue` instead of the usual `value`. It should be scoped according to whether the generated files are main (`Compile`) or test (`Test`) resources. This basic structure looks like:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
resourceGenerators in Compile <+= <your Task[Seq[File]] here>
|
resourceGenerators in Compile += <task of type Seq[File]>.taskValue
|
||||||
|
|
||||||
For example, assuming a method `def makeSomeResources(base: File): Seq[File]`,
|
For example, assuming a method `def makeSomeResources(base: File): Seq[File]`,
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
resourceGenerators in Compile <+= Def.task {
|
resourceGenerators in Compile += Def.task {
|
||||||
makeSomeResources( (resourceManaged in Compile).value / "demo")
|
makeSomeResources( (resourceManaged in Compile).value / "demo")
|
||||||
}
|
}.taskValue
|
||||||
|
|
||||||
As a specific example, the following generates a properties file containing the application name and version:
|
As a specific example, the following generates a properties file containing the application name and version:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
resourceGenerators in Compile <+= {
|
resourceGenerators in Compile += Def.task {
|
||||||
val file = (resourceManaged in Compile).value / "demo" / "myapp.properties"
|
val file = (resourceManaged in Compile).value / "demo" / "myapp.properties"
|
||||||
val contents = "name=%s\nversion=%s".format(name.value,version.value)
|
val contents = "name=%s\nversion=%s".format(name.value,version.value)
|
||||||
IO.write(file, contents)
|
IO.write(file, contents)
|
||||||
Seq(file)
|
Seq(file)
|
||||||
}
|
}.taskValue
|
||||||
|
|
||||||
Change `Compile` to `Test` to make it a test resource. Normally, you would only want to generate resources when necessary and not every run.
|
Change `Compile` to `Test` to make it a test resource. Normally, you would only want to generate resources when necessary and not every run.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue