Skip to content

Commit

Permalink
Working diff-base completion
Browse files Browse the repository at this point in the history
```
> scalafix --diff-base <tab>
HEAD
ag/gh-pages
ag/issue-260
ag/issue-319
ag/master
...
v0.5.5
v0.5.6
|00| 51abefa -- wip improve sbt completion (13 hours ago)
|01| 3f63b5b -- Merge pull request scalacenter#474 from marcelocenerine/trim_includeNewLine (13 hours ago)
|02| 47b94c0 -- Add leadingSpaces/trailingSpaces methods to TokenList (13 hours ago)
|03| 8bd026d -- Merge pull request scalacenter#503 from MasseGuillaume/feature/368-escape-patches (13 hours ago)
|04| 20e445f -- Escape hatch on Patch (fix scalacenter#368) (13 hours ago)
|05| a2c5d70 -- Merge pull request scalacenter#500 from MasseGuillaume/feature/495-custom-id (13 hours ago)
|06| 59efe7d -- Add CustomMessage to the public api (13 hours ago)
|07| 9ae6071 -- Add id for CustomMessage (fix scalacenter#495) (13 hours ago)
|08| e4a5c35 -- Merge pull request scalacenter#494 from MasseGuillaume/disable-regex (13 hours ago)
|09| a422860 -- Merge pull request scalacenter#497 from olafurpg/disable-signatures (13 hours ago)
|10| 7930947 -- DisableSyntax add regex (13 hours ago)
|11| 5dbdd6b -- IntervalSet test for empty and add toString (13 hours ago)
|12| b022fbd -- DisableSyntax don't repeat DisableSyntax.keyword in message (13 hours ago)
|13| a992b02 -- Assert instead of scalafix:ok (13 hours ago)
|14| 7896ccd -- Refactor Disable to use views. (13 hours ago)
|15| 58acdbe -- Fix scalacenter#493, handle synthetics and symbol signatures in Disable. (13 hours ago)
|16| b48d7f0 -- Merge pull request scalacenter#490 from olafurpg/unmanagedSources (13 hours ago)
|17| e9b2b0a -- s/canFormat/canFix/ (13 hours ago)
|18| 26be6fa -- Use unmanagedSources instead of unmanagedSourceDirectories. (13 hours ago)
|19| 4d46001 -- Merge pull request scalacenter#488 from olafurpg/master (13 hours ago)
```
  • Loading branch information
MasseGuillaume committed Dec 22, 2017
1 parent 511a0a6 commit 0fc821c
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,22 @@ import org.eclipse.jgit.util.GitDateFormatter
import scala.collection.JavaConverters._

class JGitCompletion(cwd: Path) {
val builder = new FileRepositoryBuilder()
val repo = builder.readEnvironment().setWorkTree(cwd.toFile).build()
val refList = repo.getRefDatabase().getRefs(RefDatabase.ALL).asScala
val branchAndTags = refList.map {
case (a, b) => Repository.shortenRefName(a)
}
val git = new Git(repo)
val refs = git.log().setMaxCount(20).call().asScala.toList
val dateFormatter = new GitDateFormatter(GitDateFormatter.Format.RELATIVE)
private val builder = new FileRepositoryBuilder()
private val repo = builder.readEnvironment().setWorkTree(cwd.toFile).build()
private val refList = repo.getRefDatabase().getRefs(RefDatabase.ALL).asScala
private val git = new Git(repo)
private val refs = git.log().setMaxCount(20).call().asScala.toList
private val dateFormatter = new GitDateFormatter(GitDateFormatter.Format.RELATIVE)

val last20Commits = refs.map { ref =>
val relativeCommitTime =
dateFormatter.formatDate(refs.head.getCommitterIdent)
val abrev = ref.abbreviate(8).name
val short = ref.getShortMessage
// TODO: figure out how to display the whole message but only auto-complete on abrev
s"$abrev -- $short ($relativeCommitTime)"
}
val branchesAndTags: List[String] =
refList.map{ case (a, b) => Repository.shortenRefName(a)}.toList

def all: Iterable[String] = branchAndTags ++ last20Commits
val last20Commits: List[(String, String)] =
refs.map { ref =>
val relativeCommitTime =
dateFormatter.formatDate(refs.head.getCommitterIdent)
val abrev = ref.abbreviate(8).name
val short = ref.getShortMessage
(s"$abrev -- $short ($relativeCommitTime)", abrev)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ import java.util.regex.Pattern

import scala.util.control.NonFatal

import sbt.complete.DefaultParsers
import sbt.complete._
import sbt.complete.DefaultParsers._
import sbt.complete.FileExamples
import sbt.complete.Parser
import sbt.complete.FixedSetExamples

object ScalafixCompletions {
private val names = ScalafixRuleNames.all
private val namedRule: Parser[String] = names.map(literal).reduceLeft(_ | _)

private def toAbsolutePath(path: Path, cwd: Path): Path = {
if (path.isAbsolute) path
Expand Down Expand Up @@ -43,136 +41,40 @@ object ScalafixCompletions {
private def uri(protocol: String) =
token(protocol + ":") ~> NotQuoted.map(x => s"$protocol:$x")

private val namedRule: Parser[String] =
names.map(literal).reduceLeft(_ | _)


def parser(cwd: Path): Parser[Seq[String]] = {

// like repsep but keep the sep and flatten everything back
def repsep[T](rep: Parser[String], sep: Parser[String]): Parser[String] =
(rep ~ (sep ~ rep).*).map {
case x ~ xs =>
x + xs.map { case s ~ y => s + y }.mkString("")
}

def single[T](p: Parser[T]): Parser[Seq[T]] =
p.map(Seq(_))

def join[T](a: Parser[T], b: Parser[T]): Parser[Seq[T]] =
(a ~ b).map { case (ra, rb) => Seq(ra, rb) }

def joinSeq[T](a: Parser[Seq[T]], b: Parser[Seq[T]]): Parser[Seq[T]] =
(a ~ b).map { case (ra, rb) => ra ++ rb }

def flatten[T](p: Parser[Seq[Seq[T]]]): Parser[Seq[T]] =
p.map(_.flatten)

def mapOrFail[S, T](p: Parser[S])(f: S => T): Parser[T] =
p.flatMap(s =>
try { success(f(s)) } catch { case NonFatal(e) => failure(e.toString) })

val string: Parser[String] = StringBasic

// val pathExamples: Parser[String] =
// string
// .examples(new AbsolutePathExamples(cwd))
// .map { f =>
// toAbsolutePath(Paths.get(f), cwd).toString
// }

// val regexPath: Parser[String] = mapOrFail(pathExamples) { regex =>
// Pattern.compile(regex)
// regex
// }

// val fileRule: Parser[String] = token("file:") ~> pathExamples.map(
// "file:" + _)

// val classpathExamples: Parser[String] =
// repsep(pathExamples, ":")

val jgitCompletion = new JGitCompletion(cwd)
val gitBase: Parser[String] =
string.examples(new FixedSetExamples(jgitCompletion.all))

type P = Parser[Seq[String]]
val space: P = single(" ")
val usage: P = single("--usage")
val help: P = single("--help") | single("-h")
val version: P = single("--version") | single("-v")
val verbose: P = single("--verbose")
// val config: P = join(("--config" | "-c"), pathExamples)
val configStr: P = join(("--config-str" | "-c"), string)
// val sourceroot: P = join(("--config-str" | "-c"), pathExamples)
// val classpath: P = join("--classpath", classpathExamples)
// val classpathAutoRoots: P = join("--classpath-auto-roots", pathExamples)
// val toolClasspath: P = join("--tool-classpath", classpathExamples)
val noStrictSemanticdb: P = single("--no-strict-semanticdb")
val rules: P =
flatten(
join(
"--rule" | "-r",
token(
namedRule |
// fileRule |
uri("github") |
uri("replace") |
uri("http") |
uri("https") |
uri("scala")
)
).*
)
// val files: P = join("--files" | "-f", pathExamples) // extra
val stdout: P = single("--stdout")
val test: P = single("--test")
// val outFrom: P = join("--out-from", regexPath)
// val outTo: P = join("--out-to", regexPath)
// val exclude: P = join("exclude", regexPath)
val singleThread: P = single("--single-thread")
val noSysExit: P = single("--no-sys-exit")
val inPlace: P = single("-i" | "in-place")
val quietParseErrors: P = single("--quiet-parse-errors")
val bash: P = single("--bash")
val zsh: P = single("--zsh")
val nonInteractive: P = single("--non-interactive")
val projectId: P = join("--project-id", string)
val diff: P = single("--diff")
val diffBase: P = join("--diff-base", gitBase)

val all = usage | help

// |
// help |
// version |
// verbose |
// // config |
// configStr |
// // sourceroot |
// // classpath |
// // classpathAutoRoots |
// // toolClasspath |
// noStrictSemanticdb |
// rules |
// // files |
// stdout |
// test |
// // outFrom |
// // outTo |
// // exclude |
// singleThread |
// noSysExit |
// inPlace |
// quietParseErrors |
// bash |
// zsh |
// nonInteractive |
// projectId |
// diff |
// diffBase

val space: Parser[String] = token(Space).map(_.toString)

val diffBase: Parser[String] =
("--diff-base" ~ space ~ token(NotQuoted, TokenCompletions.fixed(
(seen, level) => {
val last20Commits =
jgitCompletion.last20Commits
.filter{ case (_, sha1) => sha1.startsWith(seen)}
.zipWithIndex
.map{
case ((log, sha1), i) => {
val idx = if(i < 10) "0" + i.toString else i.toString
new Token(display = s"|$idx| $log", append = sha1.stripPrefix(seen))
}
}
.toSet

val branchesAndTags =
jgitCompletion.branchesAndTags
.filter(info => info.startsWith(seen))
.map(info => new Token(display = info, append = info.stripPrefix(seen)))
.toSet

Completions.strict(last20Commits ++ branchesAndTags)
}
))).map {
case a ~ b ~ c => a + b + c
}


flatten(joinSeq(space, all).*)
(token(Space) ~> diffBase).* <~ SpaceClass.*
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@ import java.nio.file.Paths
import org.scalatest.FunSuite
import sbt.complete.Parser


import sbt.complete.JLineCompletion

class ScalafixCompletionsTest extends FunSuite {
val cwd = Paths.get("").toAbsolutePath
println(cwd)
val parser = ScalafixCompletions.parser(cwd)
val expected = Set("-diff", "-testkit", "-sbt", "-core", "-cli")
def check(path: String): Unit = {
test(path) {
val completions = Parser.completions(parser, " file:" + path, 0)
val obtained = completions.get.map(_.append).intersect(expected)
assert(obtained == expected)
}
}
// val cwd = Paths.get("").toAbsolutePath
// println(cwd)
// val parser = ScalafixCompletions.parser(cwd)
// val expected = Set("-diff", "-testkit", "-sbt", "-core", "-cli")
// def check(path: String): Unit = {
// test(path) {
// val completions = Parser.completions(parser, " file:" + path, 0)
// val obtained = completions.get.map(_.append).intersect(expected)
// assert(obtained == expected)
// }
// }

// check("scalafix") // relative path
// check(cwd.resolve("scalafix").toString) // absolute path
// check(Paths.get("..").resolve("scalafix").resolve("scalafix").toString)


check("scalafix") // relative path
check(cwd.resolve("scalafix").toString) // absolute path
check(Paths.get("..").resolve("scalafix").resolve("scalafix").toString)

test("completion") {
val cwd = Paths.get("").toAbsolutePath
val parser = ScalafixCompletions.parser(cwd)

val completions = Parser.completions(parser, " --diff-base ", 0)

val (insert, display) = JLineCompletion.convertCompletions(completions)
// insert.zip(display).foreach(println)
display.foreach(println)

}
}

0 comments on commit 0fc821c

Please sign in to comment.