diff options
author | Som Snytt <som.snytt@gmail.com> | 2013-12-03 16:38:55 -0800 |
---|---|---|
committer | Som Snytt <som.snytt@gmail.com> | 2013-12-03 16:56:18 -0800 |
commit | 30f779b4d9b699800e323eeba31cf04c16b4fbcd (patch) | |
tree | 128e704dd783731294062b76c832abb17c0c778d | |
parent | 6c63ab153651f7946ece5740d52e0f2b701e349d (diff) | |
download | scala-30f779b4d9b699800e323eeba31cf04c16b4fbcd.tar.gz scala-30f779b4d9b699800e323eeba31cf04c16b4fbcd.tar.bz2 scala-30f779b4d9b699800e323eeba31cf04c16b4fbcd.zip |
SI-8027 REPL double tab regression
Where did double tab go? "The shadow knows."
The regression was introduced by the last flurry
before we were left to wallow in whatever white
space remained.
Some xs put other xs under erasure.
It's clear that somebody's daughter walked into
the room and asked for a story, because, shockingly,
the case arrows don't line up.
We need a plug-in for Jenkins, or I guess Travis, to
fail the build if arrows and equals don't align,
because it clearly indicates a lapse of some kind.
3 files changed, 64 insertions, 9 deletions
diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala index 14f349f502..efb8126ff0 100644 --- a/src/reflect/scala/reflect/internal/util/StringOps.scala +++ b/src/reflect/scala/reflect/internal/util/StringOps.scala @@ -23,12 +23,16 @@ trait StringOps { def oempty(xs: String*) = xs filterNot (x => x == null || x == "") def ojoin(xs: String*): String = oempty(xs: _*) mkString " " def longestCommonPrefix(xs: List[String]): String = xs match { - case Nil => "" - case xs if xs contains "" => "" - case x :: xs => - val ch = x charAt 0 - if (xs exists (_.head != ch)) "" - else "" + ch + longestCommonPrefix(xs map (_ substring 1)) + case Nil => "" + case w :: Nil => w + case _ => + def lcp(ss: List[String]): String = { + val w :: ws = ss + if (w == "") "" + else if (ws exists (s => s == "" || (s charAt 0) != (w charAt 0))) "" + else w.substring(0, 1) + lcp(ss map (_ substring 1)) + } + lcp(xs) } /** Like String#trim, but trailing whitespace only. */ diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala index 1b3d60d41a..53c7c82e89 100644 --- a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -294,7 +294,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput // This is jline's entry point for completion. override def complete(buf: String, cursor: Int): Candidates = { verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0 - repldbg("\ncomplete(%s, %d) last = (%s, %d), verbosity: %s".format(buf, cursor, lastBuf, lastCursor, verbosity)) + repldbg(f"%ncomplete($buf, $cursor%d) last = ($lastBuf, $lastCursor%d), verbosity: $verbosity") // we don't try lower priority completions unless higher ones return no results. def tryCompletion(p: Parsed, completionFunction: Parsed => List[String]): Option[Candidates] = { @@ -307,8 +307,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput val advance = longestCommonPrefix(winners) lastCursor = p.position + advance.length lastBuf = (buf take p.position) + advance - repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format( - p, lastBuf, lastCursor, p.position)) + repldbg(s"tryCompletion($p, _) lastBuf = $lastBuf, lastCursor = $lastCursor, p.position = ${p.position}") p.position } diff --git a/test/junit/scala/reflect/internal/util/StringOpsTest.scala b/test/junit/scala/reflect/internal/util/StringOpsTest.scala new file mode 100644 index 0000000000..13d3a6435e --- /dev/null +++ b/test/junit/scala/reflect/internal/util/StringOpsTest.scala @@ -0,0 +1,52 @@ +package scala.reflect.internal.util + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class StringOpsTest { + @Test + def prefixOfNone(): Unit = { + val so = new StringOps { } + val ss = Nil + val lcp = so longestCommonPrefix ss + assert(lcp == "") + } + @Test + def prefixWithEmpty(): Unit = { + val so = new StringOps { } + val ss = List("abc", "", "abd") + val lcp = so longestCommonPrefix ss + assert(lcp == "") + } + @Test + def prefixOfOne(): Unit = { + val so = new StringOps { } + val ss = List("abc") + val lcp = so longestCommonPrefix ss + assert(lcp == "abc") + } + @Test + def prefixOfMany(): Unit = { + val so = new StringOps { } + val ss = List("abc", "abd", "abe") + val lcp = so longestCommonPrefix ss + assert(lcp == "ab") + } + @Test + def prefixOfPrefix(): Unit = { + val so = new StringOps { } + val ss = List("abc", "abcd") + val lcp = so longestCommonPrefix ss + assert(lcp == "abc") + } + @Test + def prefixOfPrefixMiddling(): Unit = { + val so = new StringOps { } + val ss = List("abce", "abc", "abcd") + val lcp = so longestCommonPrefix ss + assert(lcp == "abc") + } +} |