mirror of https://github.com/sbt/sbt.git
Merge pull request #2469 from Duhemm/wip/fix-2460
Completion for build-level keys
This commit is contained in:
commit
884da06170
|
|
@ -48,12 +48,22 @@ object Act {
|
||||||
new ParsedKey(makeScopedKey(proj, conf, task, extra, key), mask)
|
new ParsedKey(makeScopedKey(proj, conf, task, extra, key), mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
val projectKeys =
|
||||||
rawProject <- optProjectRef(index, current)
|
for {
|
||||||
proj = resolveProject(rawProject, current)
|
rawProject <- optProjectRef(index, current)
|
||||||
confAmb <- config(index configs proj)
|
proj = resolveProject(rawProject, current)
|
||||||
partialMask = ScopeMask(rawProject.isExplicit, confAmb.isExplicit, false, false)
|
confAmb <- config(index configs proj)
|
||||||
} yield taskKeyExtra(proj, confAmb, partialMask)
|
partialMask = ScopeMask(rawProject.isExplicit, confAmb.isExplicit, false, false)
|
||||||
|
} yield taskKeyExtra(proj, confAmb, partialMask)
|
||||||
|
|
||||||
|
val build = Some(BuildRef(current.build))
|
||||||
|
val buildKeys =
|
||||||
|
for {
|
||||||
|
confAmb <- config(index configs build)
|
||||||
|
partialMask = ScopeMask(false, confAmb.isExplicit, false, false)
|
||||||
|
} yield taskKeyExtra(build, confAmb, partialMask)
|
||||||
|
|
||||||
|
buildKeys combinedWith projectKeys map (_.flatten)
|
||||||
}
|
}
|
||||||
def makeScopedKey(proj: Option[ResolvedReference], conf: Option[String], task: Option[AttributeKey[_]], extra: ScopeAxis[AttributeMap], key: AttributeKey[_]): ScopedKey[_] =
|
def makeScopedKey(proj: Option[ResolvedReference], conf: Option[String], task: Option[AttributeKey[_]], extra: ScopeAxis[AttributeMap], key: AttributeKey[_]): ScopedKey[_] =
|
||||||
ScopedKey(Scope(toAxis(proj, Global), toAxis(conf map ConfigKey.apply, Global), toAxis(task, Global), extra), key)
|
ScopedKey(Scope(toAxis(proj, Global), toAxis(conf map ConfigKey.apply, Global), toAxis(task, Global), extra), key)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ object ParseKey extends Properties("Key parser test") {
|
||||||
parseExpected(structure, string, expected, mask)
|
parseExpected(structure, string, expected, mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
property("An unspecified project axis resolves to the current project") =
|
property("An unspecified project axis resolves to the current project or the build of the current project") =
|
||||||
forAllNoShrink(structureDefinedKey) { (skm: StructureKeyMask) =>
|
forAllNoShrink(structureDefinedKey) { (skm: StructureKeyMask) =>
|
||||||
import skm.{ structure, key }
|
import skm.{ structure, key }
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ object ParseKey extends Properties("Key parser test") {
|
||||||
("Current: " + structure.current) |:
|
("Current: " + structure.current) |:
|
||||||
parse(structure, string) {
|
parse(structure, string) {
|
||||||
case Left(err) => false
|
case Left(err) => false
|
||||||
case Right(sk) => sk.scope.project == Select(structure.current)
|
case Right(sk) => sk.scope.project == Select(structure.current) || sk.scope.project == Select(BuildRef(structure.current.build))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[@Duhemm]: https://github.com/Duhemm
|
||||||
|
[#2460]: https://github.com/sbt/sbt/issues/2460
|
||||||
|
[#2469]: https://github.com/sbt/sbt/pull/2469
|
||||||
|
|
||||||
|
### Fixes with compatibility implications
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Fixes tab completion for tasks defined in AutoPlugin's buildSettings [#2460][#2460]/[#2469][#2469] by [@Duhemm][@Duhemm]
|
||||||
|
|
@ -126,6 +126,9 @@ sealed trait RichParser[A] {
|
||||||
|
|
||||||
/** Applies the original parser, applies `f` to the result to get the next parser, and applies that parser and uses its result for the overall result. */
|
/** Applies the original parser, applies `f` to the result to get the next parser, and applies that parser and uses its result for the overall result. */
|
||||||
def flatMap[B](f: A => Parser[B]): Parser[B]
|
def flatMap[B](f: A => Parser[B]): Parser[B]
|
||||||
|
|
||||||
|
/** Applied both the original parser and `b` on the same input and returns the results produced by each parser */
|
||||||
|
def combinedWith(b: Parser[A]): Parser[Seq[A]]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Contains Parser implementation helper methods not typically needed for using parsers. */
|
/** Contains Parser implementation helper methods not typically needed for using parsers. */
|
||||||
|
|
@ -309,6 +312,11 @@ trait ParserMain {
|
||||||
def filter(f: A => Boolean, msg: String => String): Parser[A] = filterParser(a, f, "", msg)
|
def filter(f: A => Boolean, msg: String => String): Parser[A] = filterParser(a, f, "", msg)
|
||||||
def string(implicit ev: A <:< Seq[Char]): Parser[String] = map(_.mkString)
|
def string(implicit ev: A <:< Seq[Char]): Parser[String] = map(_.mkString)
|
||||||
def flatMap[B](f: A => Parser[B]) = bindParser(a, f)
|
def flatMap[B](f: A => Parser[B]) = bindParser(a, f)
|
||||||
|
def combinedWith(b: Parser[A]): Parser[Seq[A]] =
|
||||||
|
if (a.valid)
|
||||||
|
if (b.valid) new CombiningParser(a, b) else a.map(Seq(_))
|
||||||
|
else
|
||||||
|
b.map(Seq(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
implicit def literalRichCharParser(c: Char): RichParser[Char] = richParser(c)
|
implicit def literalRichCharParser(c: Char): RichParser[Char] = richParser(c)
|
||||||
|
|
@ -633,6 +641,24 @@ private final class HetParser[A, B](a: Parser[A], b: Parser[B]) extends ValidPar
|
||||||
def completions(level: Int) = a.completions(level) ++ b.completions(level)
|
def completions(level: Int) = a.completions(level) ++ b.completions(level)
|
||||||
override def toString = "(" + a + " || " + b + ")"
|
override def toString = "(" + a + " || " + b + ")"
|
||||||
}
|
}
|
||||||
|
private final class CombiningParser[T](a: Parser[T], b: Parser[T]) extends ValidParser[Seq[T]] {
|
||||||
|
lazy val result: Option[Seq[T]] = (a.result.toSeq ++ b.result.toSeq) match { case Seq() => None; case seq => Some(seq) }
|
||||||
|
def completions(level: Int) = a.completions(level) ++ b.completions(level)
|
||||||
|
def derive(i: Char) =
|
||||||
|
(a.valid, b.valid) match {
|
||||||
|
case (true, true) => new CombiningParser(a derive i, b derive i)
|
||||||
|
case (true, false) => a derive i map (Seq(_))
|
||||||
|
case (false, true) => b derive i map (Seq(_))
|
||||||
|
case (false, false) => new Invalid(mkFailure("No valid parser available."))
|
||||||
|
}
|
||||||
|
def resultEmpty =
|
||||||
|
(a.resultEmpty, b.resultEmpty) match {
|
||||||
|
case (Value(ra), Value(rb)) => Value(Seq(ra, rb))
|
||||||
|
case (Value(ra), _) => Value(Seq(ra))
|
||||||
|
case (_, Value(rb)) => Value(Seq(rb))
|
||||||
|
case _ => Value(Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
private final class ParserSeq[T](a: Seq[Parser[T]], errors: => Seq[String]) extends ValidParser[Seq[T]] {
|
private final class ParserSeq[T](a: Seq[Parser[T]], errors: => Seq[String]) extends ValidParser[Seq[T]] {
|
||||||
assert(a.nonEmpty)
|
assert(a.nonEmpty)
|
||||||
lazy val resultEmpty: Result[Seq[T]] =
|
lazy val resultEmpty: Result[Seq[T]] =
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,15 @@ object ParserTest extends Properties("Completing Parser") {
|
||||||
property("repeatDep requires at least one token") = !matches(repeat, "")
|
property("repeatDep requires at least one token") = !matches(repeat, "")
|
||||||
property("repeatDep accepts one token") = matches(repeat, colors.toSeq.head)
|
property("repeatDep accepts one token") = matches(repeat, colors.toSeq.head)
|
||||||
property("repeatDep accepts two tokens") = matches(repeat, colors.toSeq.take(2).mkString(" "))
|
property("repeatDep accepts two tokens") = matches(repeat, colors.toSeq.take(2).mkString(" "))
|
||||||
|
property("combined parser gives completion of both parsers") = {
|
||||||
|
val prefix = "fix"
|
||||||
|
val p1Suffixes = Set("", "ated", "ation")
|
||||||
|
val p2Suffixes = Set("es", "ed")
|
||||||
|
val p1: Parser[String] = p1Suffixes map (suffix => (prefix + suffix): Parser[String]) reduce (_ | _)
|
||||||
|
val p2: Parser[String] = p2Suffixes map (suffix => (prefix + suffix): Parser[String]) reduce (_ | _)
|
||||||
|
val suggestions: Set[Completion] = p1Suffixes ++ p2Suffixes map (new Suggestion(_))
|
||||||
|
checkAll(prefix, p1 combinedWith p2, Completions(suggestions))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
object ParserExample {
|
object ParserExample {
|
||||||
val ws = charClass(_.isWhitespace)+
|
val ws = charClass(_.isWhitespace)+
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue