正如丹尼尔·C·索布拉尔提到的,parsed
and evaluated
是宏,定义于InputWrapper
.
由于它们是在编译时执行的,并且参数是在运行时检索的,因此它们不能很好地混合。特别是,args 的值仅在运行时真正定义,并且不能由evaluated
macro.
EDIT: 与OP聊天后,我确定他的目标是写作的捷径 myTask Foo bar
代替 testOnly *Foo* -- --tests=*bar*
,我相应地更新了我的答案。
更新答案
正如所讨论的,因为你基本上想要一个“宏”来编写myTask Foo bar
代替testOnly *Foo* -- --tests=*bar*
,这是我的解决方案:
val filtersParser = {
import complete.DefaultParsers._
(token(Space) ~> token(StringBasic, "<classFilter>")) ~
(token(Space) ~> token(StringBasic, "<methodFilter>"))
}
lazy val testFiltered = inputKey[Unit]("runs test methods matching *<methodFilter>* within classes matching *<classFilter>*")
testFiltered.in(Test) := Def.inputTaskDyn {
val (classFilter, methodFilter) = filtersParser.parsed
runTestsFiltered(classFilter, methodFilter)
}.evaluated
def runTestsFiltered(classFilter: String, methodFilter: String) = Def.taskDyn {
(testOnly in Test).toTask(s" *$classFilter* -- --tests *$methodFilter*")
}
更详细
您需要一个自定义解析器来检索您期望的两个参数。这是通过以下代码实现的,该代码基本上定义了两个组,“咀嚼”两个空格而不记住它们,以及两个StringBasic
参数,它们是解析器的结果(filtersParser
属于类型Parser[(String, String)]
)
val filtersParser = {
import complete.DefaultParsers._
(token(Space) ~> token(StringBasic, "<classFilter>")) ~
(token(Space) ~> token(StringBasic, "<methodFilter>"))
}
然后,您需要一个输入任务来使用解析器的结果并将其转发到测试框架。
这是在下一个片段中完成的(如果比我更有知识的人希望插话使用inputTaskDyn
,我很乐意受到启发:))。请注意任务范围的定义.in(Test)
它授予对测试依赖项的访问权限。
lazy val testFiltered = inputKey[Unit]("runs test methods matching *<methodFilter>* within classes matching *<classFilter>*")
testFiltered.in(Test) := Def.inputTaskDyn {
val (classFilter, methodFilter) = filtersParser.parsed
runTestsFiltered(classFilter, methodFilter)
}.evaluated
最后一段代码只是将参数转发给预先存在的testOnly
task:
def runTestsFiltered(classFilter: String, methodFilter: String) = Def.taskDyn {
(testOnly in Test).toTask(s" *$classFilter* -- --tests *$methodFilter*")
}
之前的回答
但是,您应该能够通过将定义和用法分为两个任务来解决这个问题:
import sbt._
import complete.DefaultParsers._
lazy val loadArgTask = inputKey[Unit]("loads and transforms argument")
lazy val runStuff = taskKey[Unit]("Runs some stuff")
lazy val loadArgIntoPropertyTask: Def.Initialize[InputTask[Unit]] = Def.inputTask {
val myArg = (token(Space) ~> token(StringBasic, "<myArg>")).parsed
System.setProperty("myArg", myArg + "foo")
}
loadArgTask <<= loadArgIntoPropertyTask
runStuff := {
println(System.getProperty("myArg"))
}
可以如下使用
> loadArgTask orange
[success] Total time: 0 s, completed [...]
> runStuff
orangefoo
[success] Total time: 0 s, completed [...]