Skip to content

Commit

Permalink
Backport "Repl - method signatures in autocomplete" to LTS (#20995)
Browse files Browse the repository at this point in the history
Backports #19917 to the LTS branch.

PR submitted by the release tooling.
[skip ci]
  • Loading branch information
WojciechMazur authored Jul 4, 2024
2 parents e48cbe7 + 9960977 commit 6ba333b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 15 deletions.
55 changes: 41 additions & 14 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import dotty.tools.dotc.util.{SourceFile, SourcePosition}
import dotty.tools.dotc.{CompilationUnit, Driver}
import dotty.tools.dotc.config.CompilerCommand
import dotty.tools.io.*
import dotty.tools.repl.Rendering.showUser
import dotty.tools.runner.ScalaClassLoader.*
import org.jline.reader.*

Expand Down Expand Up @@ -148,11 +149,36 @@ class ReplDriver(settings: Array[String],

/** Blockingly read a line, getting back a parse result */
def readLine()(using state: State): ParseResult = {
val completer: Completer = { (_, line, candidates) =>
val comps = completions(line.cursor, line.line, state)
candidates.addAll(comps.asJava)
}
given Context = state.context
val completer: Completer = { (lineReader, line, candidates) =>
def makeCandidate(label: String) = {
new Candidate(
/* value = */ label,
/* displ = */ stripBackTicks(label), // displayed value
/* group = */ null, // can be used to group completions together
/* descr = */ null, // TODO use for documentation?
/* suffix = */ null,
/* key = */ null,
/* complete = */ false // if true adds space when completing
)
}
val comps = completionsWithSignatures(line.cursor, line.line, state)
candidates.addAll(comps.map(_.label).distinct.map(makeCandidate).asJava)
val lineWord = line.word()
comps.filter(c => c.label == lineWord && c.symbols.nonEmpty) match
case Nil =>
case exachMatches =>
val terminal = lineReader.nn.getTerminal
lineReader.callWidget(LineReader.CLEAR)
terminal.writer.println()
exachMatches.foreach: exact =>
exact.symbols.foreach: sym =>
terminal.writer.println(SyntaxHighlighting.highlight(sym.showUser))
lineReader.callWidget(LineReader.REDRAW_LINE)
lineReader.callWidget(LineReader.REDISPLAY)
terminal.flush()
}

try {
val line = terminal.readLine(completer)
ParseResult(line)
Expand Down Expand Up @@ -228,24 +254,26 @@ class ReplDriver(settings: Array[String],
else
label

/** Extract possible completions at the index of `cursor` in `expr` */
@deprecated("Use completionsWithSignatures instead", "3.3.4")
protected final def completions(cursor: Int, expr: String, state0: State): List[Candidate] =
def makeCandidate(label: String) = {

completionsWithSignatures(cursor, expr, state0).map: c =>
new Candidate(
/* value = */ label,
/* displ = */ stripBackTicks(label), // displayed value
/* value = */ c.label,
/* displ = */ stripBackTicks(c.label), // displayed value
/* group = */ null, // can be used to group completions together
/* descr = */ null, // TODO use for documentation?
/* suffix = */ null,
/* key = */ null,
/* complete = */ false // if true adds space when completing
)
}
end completions


/** Extract possible completions at the index of `cursor` in `expr` */
protected final def completionsWithSignatures(cursor: Int, expr: String, state0: State): List[Completion] =
if expr.startsWith(":") then
ParseResult.commands.collect {
case command if command._1.startsWith(expr) => makeCandidate(command._1)
case command if command._1.startsWith(expr) => Completion(command._1, "", List())
}
else
given state: State = newRun(state0)
Expand All @@ -258,11 +286,10 @@ class ReplDriver(settings: Array[String],
unit.tpdTree = tpdTree
given Context = state.context.fresh.setCompilationUnit(unit)
val srcPos = SourcePosition(file, Span(cursor))
val completions = try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil
completions.map(_.label).distinct.map(makeCandidate)
try Completion.completions(srcPos)._2 catch case NonFatal(_) => Nil
}
.getOrElse(Nil)
end completions
end completionsWithSignatures

protected def interpret(res: ParseResult, quiet: Boolean = false)(using state: State): State = {
res match {
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/repl/TabcompleteTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TabcompleteTests extends ReplTest {

/** Returns the `(<instance completions>, <companion completions>)`*/
private def tabComplete(src: String)(implicit state: State): List[String] =
completions(src.length, src, state).map(_.value).sorted
completionsWithSignatures(src.length, src, state).map(_.label).sorted.distinct

@Test def tabCompleteList = initially {
val comp = tabComplete("List.r")
Expand Down

0 comments on commit 6ba333b

Please sign in to comment.