mirror of https://github.com/sbt/sbt.git
Parser.failOnException method, don't let rhs of alias fail the parse. Fixes #572.
alias only parses the right hand side for tab completion help. The assignment should happen whether or not the parse is successful because the context may change by the time the alias is actually evaluated. In particular, the 'set' command uses the loaded project for tab completion in 0.12.1. When a .sbtrc file is processed, the project has not been loaded yet, so aliases involving set fail. Wrapping the rhs in failOnException addresses this.
This commit is contained in:
parent
aee2742932
commit
1f88fe9d7c
|
|
@ -45,6 +45,9 @@ sealed trait RichParser[A]
|
||||||
|
|
||||||
/** Uses the specified message if the original Parser fails.*/
|
/** Uses the specified message if the original Parser fails.*/
|
||||||
def !!!(msg: String): Parser[A]
|
def !!!(msg: String): Parser[A]
|
||||||
|
/** If an exception is thrown by the original Parser,
|
||||||
|
* capture it and fail locally instead of allowing the exception to propagate up and terminate parsing.*/
|
||||||
|
def failOnException: Parser[A]
|
||||||
|
|
||||||
def unary_- : Parser[Unit]
|
def unary_- : Parser[Unit]
|
||||||
def & (o: Parser[_]): Parser[A]
|
def & (o: Parser[_]): Parser[A]
|
||||||
|
|
@ -173,6 +176,8 @@ object Parser extends ParserMain
|
||||||
|
|
||||||
def onFailure[T](delegate: Parser[T], msg: String): Parser[T] =
|
def onFailure[T](delegate: Parser[T], msg: String): Parser[T] =
|
||||||
if(delegate.valid) new OnFailure(delegate, msg) else failure(msg)
|
if(delegate.valid) new OnFailure(delegate, msg) else failure(msg)
|
||||||
|
def trapAndFail[T](delegate: Parser[T]): Parser[T] =
|
||||||
|
delegate.ifValid( new TrapAndFail(delegate) )
|
||||||
|
|
||||||
def zeroOrMore[T](p: Parser[T]): Parser[Seq[T]] = repeat(p, 0, Infinite)
|
def zeroOrMore[T](p: Parser[T]): Parser[Seq[T]] = repeat(p, 0, Infinite)
|
||||||
def oneOrMore[T](p: Parser[T]): Parser[Seq[T]] = repeat(p, 1, Infinite)
|
def oneOrMore[T](p: Parser[T]): Parser[Seq[T]] = repeat(p, 1, Infinite)
|
||||||
|
|
@ -233,6 +238,7 @@ trait ParserMain
|
||||||
def <~[B](b: Parser[B]): Parser[A] = (a ~ b) map { case av ~ _ => av }
|
def <~[B](b: Parser[B]): Parser[A] = (a ~ b) map { case av ~ _ => av }
|
||||||
def ~>[B](b: Parser[B]): Parser[B] = (a ~ b) map { case _ ~ bv => bv }
|
def ~>[B](b: Parser[B]): Parser[B] = (a ~ b) map { case _ ~ bv => bv }
|
||||||
def !!!(msg: String): Parser[A] = onFailure(a, msg)
|
def !!!(msg: String): Parser[A] = onFailure(a, msg)
|
||||||
|
def failOnException: Parser[A] = trapAndFail(a)
|
||||||
|
|
||||||
def unary_- = not(a)
|
def unary_- = not(a)
|
||||||
def & (o: Parser[_]) = and(a, o)
|
def & (o: Parser[_]) = and(a, o)
|
||||||
|
|
@ -425,6 +431,18 @@ private final case class Invalid(fail: Failure) extends Parser[Nothing]
|
||||||
def valid = false
|
def valid = false
|
||||||
def ifValid[S](p: => Parser[S]): Parser[S] = this
|
def ifValid[S](p: => Parser[S]): Parser[S] = this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class TrapAndFail[A](a: Parser[A]) extends ValidParser[A]
|
||||||
|
{
|
||||||
|
def result = try { a.result } catch { case e: Exception => None }
|
||||||
|
def resultEmpty = try { a.resultEmpty } catch { case e: Exception => fail(e) }
|
||||||
|
def derive(c: Char) = try { trapAndFail(a derive c) } catch { case e: Exception => Invalid(fail(e)) }
|
||||||
|
def completions(level: Int) = try { a.completions(level) } catch { case e: Exception => Completions.nil }
|
||||||
|
override def toString = "trap(" + a + ")"
|
||||||
|
override def isTokenStart = a.isTokenStart
|
||||||
|
private[this] def fail(e: Exception): Failure = mkFailure(e.toString)
|
||||||
|
}
|
||||||
|
|
||||||
private final class OnFailure[A](a: Parser[A], message: String) extends ValidParser[A]
|
private final class OnFailure[A](a: Parser[A], message: String) extends ValidParser[A]
|
||||||
{
|
{
|
||||||
def result = a.result
|
def result = a.result
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue